in src/main/cpp/patternparser.cpp [115:304]
void PatternParser::parse(
const LogString& pattern,
std::vector<PatternConverterPtr>& patternConverters,
std::vector<FormattingInfoPtr>& formattingInfos,
const PatternMap& rules)
{
LogString currentLiteral;
size_t patternLength = pattern.length();
int state = LITERAL_STATE;
logchar c;
size_t i = 0;
FormattingInfoPtr formattingInfo(FormattingInfo::getDefault());
while (i < patternLength)
{
c = pattern[i++];
switch (state)
{
case LITERAL_STATE:
// In literal state, the last char is always a literal.
if (i == patternLength)
{
currentLiteral.append(1, c);
continue;
}
if (c == ESCAPE_CHAR)
{
// peek at the next char.
if (pattern[i] == ESCAPE_CHAR)
{
currentLiteral.append(1, c);
i++; // move pointer
}
else
{
if (!currentLiteral.empty())
{
patternConverters.push_back(
LiteralPatternConverter::newInstance(currentLiteral));
formattingInfos.push_back(FormattingInfo::getDefault());
currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
}
currentLiteral.append(1, c); // append %
state = CONVERTER_STATE;
formattingInfo = FormattingInfo::getDefault();
}
}
else
{
currentLiteral.append(1, c);
}
break;
case CONVERTER_STATE:
currentLiteral.append(1, c);
switch (c)
{
case 0x2D: // '-'
formattingInfo = std::make_shared<FormattingInfo>(
true, formattingInfo->getMinLength(),
formattingInfo->getMaxLength());
break;
case 0x2E: // '.'
state = DOT_STATE;
break;
default:
if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
{
formattingInfo = std::make_shared<FormattingInfo>(
formattingInfo->isLeftAligned(), c - 0x30 /* '0' */,
formattingInfo->getMaxLength());
state = MIN_STATE;
}
else
{
i = finalizeConverter(
c, pattern, i, currentLiteral, formattingInfo,
rules, patternConverters, formattingInfos);
// Next pattern is assumed to be a literal.
state = LITERAL_STATE;
formattingInfo = FormattingInfo::getDefault();
if (!currentLiteral.empty())
{
currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
}
}
} // switch
break;
case MIN_STATE:
currentLiteral.append(1, c);
if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
{
formattingInfo = std::make_shared<FormattingInfo>(
formattingInfo->isLeftAligned(),
(formattingInfo->getMinLength() * 10) + (c - 0x30 /* '0' */),
formattingInfo->getMaxLength());
}
else if (c == 0x2E /* '.' */)
{
state = DOT_STATE;
}
else
{
i = finalizeConverter(
c, pattern, i, currentLiteral, formattingInfo,
rules, patternConverters, formattingInfos);
state = LITERAL_STATE;
formattingInfo = FormattingInfo::getDefault();
if (!currentLiteral.empty())
{
currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
}
}
break;
case DOT_STATE:
currentLiteral.append(1, c);
if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
{
formattingInfo = std::make_shared<FormattingInfo>(
formattingInfo->isLeftAligned(), formattingInfo->getMinLength(),
c - 0x30 /* '0' */);
state = MAX_STATE;
}
else
{
LogLog::error(LOG4CXX_STR("Error in pattern, was expecting digit."));
state = LITERAL_STATE;
}
break;
case MAX_STATE:
currentLiteral.append(1, c);
if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */))
{
formattingInfo = std::make_shared<FormattingInfo>(
formattingInfo->isLeftAligned(), formattingInfo->getMinLength(),
(formattingInfo->getMaxLength() * 10) + (c - 0x30 /* '0' */));
}
else
{
i = finalizeConverter(
c, pattern, i, currentLiteral, formattingInfo,
rules, patternConverters, formattingInfos);
state = LITERAL_STATE;
formattingInfo = FormattingInfo::getDefault();
if (!currentLiteral.empty())
{
currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
}
}
break;
} // switch
}
// while
if (currentLiteral.length() != 0)
{
patternConverters.push_back(
LiteralPatternConverter::newInstance(currentLiteral));
formattingInfos.push_back(FormattingInfo::getDefault());
}
}