void PatternParser::parse()

in src/main/cpp/patternparser.cpp [115:309]


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;
	int minDigitCount{ 0 }, maxDigitCount{ 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;
							minDigitCount = 1;
						}
						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' */) && minDigitCount < 3)
				{
					formattingInfo = std::make_shared<FormattingInfo>(
								formattingInfo->isLeftAligned(),
								(formattingInfo->getMinLength() * 10) + (c - 0x30 /* '0' */),
								formattingInfo->getMaxLength());
					++minDigitCount;
				}
				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;
					maxDigitCount = 1;
				}
				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' */) && maxDigitCount < 3)
				{
					formattingInfo = std::make_shared<FormattingInfo>(
								formattingInfo->isLeftAligned(), formattingInfo->getMinLength(),
								(formattingInfo->getMaxLength() * 10) + (c - 0x30 /* '0' */));
					++maxDigitCount;
				}
				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());
	}
}