From 2f399ddeb37727ecd29a5aa4e8d81957ad9f5551 Mon Sep 17 00:00:00 2001 From: Andrew Auclair Date: Mon, 24 Jun 2024 20:41:01 -0400 Subject: [PATCH 1/5] DateTimeParser Improvements Improve the validation of DateTimeParser by validating the numbers parsed for day, month, year, hour, minute, second, millis and micros. Improve performance by caching the RegularExpressions created in DateTimeFormat::isValid. --- Foundation/src/DateTimeFormat.cpp | 24 +- Foundation/src/DateTimeParser.cpp | 227 +++++++++++++----- .../testsuite/src/DateTimeParserTest.cpp | 6 + 3 files changed, 198 insertions(+), 59 deletions(-) diff --git a/Foundation/src/DateTimeFormat.cpp b/Foundation/src/DateTimeFormat.cpp index 27057143a0..ce085f50ff 100644 --- a/Foundation/src/DateTimeFormat.cpp +++ b/Foundation/src/DateTimeFormat.cpp @@ -150,11 +150,25 @@ bool DateTimeFormat::hasFormat(const std::string& fmt) bool DateTimeFormat::isValid(const std::string& dateTime) { - for (const auto& f : REGEX_LIST) - { - if (RegularExpression(*f).match(dateTime)) return true; - } - return false; + + static const RegularExpression regs[] = { + RegularExpression(DateTimeFormat::ISO8601_REGEX), + RegularExpression(DateTimeFormat::RFC822_REGEX), + RegularExpression(DateTimeFormat::RFC1123_REGEX), + RegularExpression(DateTimeFormat::HTTP_REGEX), + RegularExpression(DateTimeFormat::RFC850_REGEX), + RegularExpression(DateTimeFormat::RFC1036_REGEX), + RegularExpression(DateTimeFormat::ASCTIME_REGEX), + RegularExpression(DateTimeFormat::SORTABLE_REGEX) + }; + // make sure the regex list and the array of regexes are in sync + poco_assert((sizeof(regs) / sizeof(regs[0])) == REGEX_LIST.size()); + + for (const auto& f : regs) + { + if (f.match(dateTime)) return true; + } + return false; } diff --git a/Foundation/src/DateTimeParser.cpp b/Foundation/src/DateTimeParser.cpp index 9eb85f8c23..6be140f31e 100644 --- a/Foundation/src/DateTimeParser.cpp +++ b/Foundation/src/DateTimeParser.cpp @@ -18,42 +18,142 @@ #include "Poco/Exception.h" #include "Poco/Ascii.h" #include "Poco/String.h" +#include +namespace { + using parse_iter = std::string::const_iterator; -namespace Poco { + [[nodiscard]] parse_iter skip_non_digits(parse_iter it, parse_iter end) + { + while (it != end && !Poco::Ascii::isDigit(*it)) + { + ++it; + } + return it; + } -#define SKIP_JUNK() \ - while (it != end && !Ascii::isDigit(*it)) ++it + [[nodiscard]] parse_iter skip_digits(parse_iter it, parse_iter end) + { + while (it != end && Poco::Ascii::isDigit(*it)) + { + ++it; + } + return it; + } -#define SKIP_DIGITS() \ - while (it != end && Ascii::isDigit(*it)) ++it + int parse_number_n(const std::string& dtStr, parse_iter& it, parse_iter end, int n) + { + parse_iter num_start = end; + int i = 0; + for (; it != end && i < n && Poco::Ascii::isDigit(*it); ++it, ++i) + { + if (num_start == end) + { + num_start = it; + } + } -#define PARSE_NUMBER(var) \ - while (it != end && Ascii::isDigit(*it)) var = var*10 + ((*it++) - '0') + if (num_start == end) + { + throw Poco::SyntaxException("Invalid DateTimeString: " + dtStr + ", No number found to parse"); + } + std::string number(num_start, it); + int result = 0; + try + { + return std::stoi(number); + } + catch(const std::exception& e) + { + throw Poco::SyntaxException("Invalid DateTimeString: " + dtStr + ", invalid number: " + number); + } + } +} -#define PARSE_NUMBER_N(var, n) \ - { int i = 0; while (i++ < n && it != end && Ascii::isDigit(*it)) var = var*10 + ((*it++) - '0'); } +namespace Poco { -#define PARSE_FRACTIONAL_N(var, n) \ - { int i = 0; while (i < n && it != end && Ascii::isDigit(*it)) { var = var*10 + ((*it++) - '0'); i++; } while (i++ < n) var *= 10; } +void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, DateTime& dateTime, int& timeZoneDifferential) +{ + const auto str = Poco::trim(dtStr); + if (fmt.empty() || str.empty()) + { + throw SyntaxException("Invalid DateTimeString: " + dtStr); + } + else if (DateTimeFormat::hasFormat(fmt) && !DateTimeFormat::isValid(str)) + { + throw SyntaxException("Invalid DateTimeString: " + dtStr); + } + + const auto parse_number = [&dtStr](parse_iter& it, parse_iter end) + { + parse_iter num_start = end; -inline std::string cleanedInputString(const std::string& str) -{ - return Poco::trim(str); -} + for (; it != end && Poco::Ascii::isDigit(*it); ++it) + { + if (num_start == end) + { + num_start = it; + } + } -void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, DateTime& dateTime, int& timeZoneDifferential) -{ - const auto str = cleanedInputString(dtStr); + if (num_start == end) + { + throw Poco::SyntaxException("Invalid DateTimeString: " + dtStr + ", No number found to parse"); + } + + std::string number(num_start, it); + int result = 0; + try + { + return std::stoi(number); + } + catch(const std::exception& e) + { + throw SyntaxException("Invalid DateTimeString: " + dtStr + ", invalid number: " + number); + } + }; + + + + const auto parse_fractional_n = [dtStr](parse_iter& it, parse_iter end, int n) + { + parse_iter num_start = end; + int i = 0; + + for (; it != end && i < n && Poco::Ascii::isDigit(*it); ++it, ++i) + { + if (num_start == end) + { + num_start = it; + } + } + + if (num_start == end) + { + return 0; + } + + std::string number(num_start, it); + int result = 0; + try + { + result = std::stoi(number); + } + catch(const std::exception& e) + { + throw SyntaxException("Invalid DateTimeString: " + dtStr + ", invalid number: " + number); + } + + while (i++ < n) result *= 10; - if (fmt.empty() || str.empty() || (DateTimeFormat::hasFormat(fmt) && !DateTimeFormat::isValid(str))) - throw SyntaxException("Invalid DateTimeString:" + dtStr); + return result; + }; int year = 0; int month = 0; @@ -81,8 +181,8 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat { switch (*itf) { - case 'w': - case 'W': + case 'w': // Weekday, abbreviated + case 'W': // Weekday while (it != end && Ascii::isSpace(*it)) ++it; while (it != end && Ascii::isAlpha(*it)) ++it; break; @@ -94,32 +194,33 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat case 'd': case 'e': case 'f': - SKIP_JUNK(); - PARSE_NUMBER_N(day, 2); + it = skip_non_digits(it, end); + day = parse_number_n(dtStr, it, end, 2); dayParsed = true; break; case 'm': case 'n': case 'o': - SKIP_JUNK(); - PARSE_NUMBER_N(month, 2); + it = skip_non_digits(it, end); + month = parse_number_n(dtStr, it, end, 2); monthParsed = true; break; case 'y': - SKIP_JUNK(); - PARSE_NUMBER_N(year, 2); + it = skip_non_digits(it, end); + year = parse_number_n(dtStr, it, end, 2); if (year >= 69) year += 1900; else year += 2000; break; case 'Y': - SKIP_JUNK(); - PARSE_NUMBER_N(year, 4); + it = skip_non_digits(it, end); + year = parse_number_n(dtStr, it, end, 4); break; case 'r': - SKIP_JUNK(); - PARSE_NUMBER(year); + it = skip_non_digits(it, end); + year = parse_number(it, end); + if (year < 1000) { if (year >= 69) @@ -130,46 +231,47 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat break; case 'H': case 'h': - SKIP_JUNK(); - PARSE_NUMBER_N(hour, 2); + it = skip_non_digits(it, end); + hour = parse_number_n(dtStr, it, end, 2); break; case 'a': case 'A': hour = parseAMPM(it, end, hour); break; case 'M': - SKIP_JUNK(); - PARSE_NUMBER_N(minute, 2); + it = skip_non_digits(it, end); + minute = parse_number_n(dtStr, it, end, 2); break; case 'S': - SKIP_JUNK(); - PARSE_NUMBER_N(second, 2); + it = skip_non_digits(it, end); + second = parse_number_n(dtStr, it, end, 2); break; case 's': - SKIP_JUNK(); - PARSE_NUMBER_N(second, 2); + it = skip_non_digits(it, end); + second = parse_number_n(dtStr, it, end, 2); + if (it != end && (*it == '.' || *it == ',')) { ++it; - PARSE_FRACTIONAL_N(millis, 3); - PARSE_FRACTIONAL_N(micros, 3); - SKIP_DIGITS(); + millis = parse_fractional_n(it, end, 3); + micros = parse_fractional_n(it, end, 3); + it = skip_digits(it, end); } break; case 'i': - SKIP_JUNK(); - PARSE_NUMBER_N(millis, 3); + it = skip_non_digits(it, end); + millis = parse_number_n(dtStr, it, end, 3); break; case 'c': - SKIP_JUNK(); - PARSE_NUMBER_N(millis, 1); + it = skip_non_digits(it, end); + millis = parse_number_n(dtStr, it, end, 1); millis *= 100; break; case 'F': - SKIP_JUNK(); - PARSE_FRACTIONAL_N(millis, 3); - PARSE_FRACTIONAL_N(micros, 3); - SKIP_DIGITS(); + it = skip_non_digits(it, end); + millis = parse_number_n(dtStr, it, end, 3); + micros = parse_number_n(dtStr, it, end, 3); + it = skip_digits(it, end); break; case 'z': case 'Z': @@ -233,7 +335,7 @@ DateTime DateTimeParser::parse(const std::string& str, int& timeZoneDifferential bool DateTimeParser::tryParse(const std::string& dtStr, DateTime& dateTime, int& timeZoneDifferential) { - const auto str = cleanedInputString(dtStr); + const auto str = Poco::trim(dtStr); if (str.length() < 4) return false; @@ -338,12 +440,29 @@ int DateTimeParser::parseTZD(std::string::const_iterator& it, const std::string: int sign = *it == '+' ? 1 : -1; ++it; int hours = 0; - PARSE_NUMBER_N(hours, 2); + try + { + hours = parse_number_n("", it, end, 2); + } + catch(const SyntaxException& e) + { + throw SyntaxException("Timezone invalid number: hours"); + } + if (hours < 0 || hours > 23) throw SyntaxException("Timezone difference hours out of range"); if (it != end && *it == ':') ++it; int minutes = 0; - PARSE_NUMBER_N(minutes, 2); + try + { + minutes = parse_number_n("", it, end, 2); + } + catch(const SyntaxException& e) + { + throw SyntaxException("Timezone invalid number: minutes"); + } + + // PARSE_NUMBER_N(minutes, 2); if (minutes < 0 || minutes > 59) throw SyntaxException("Timezone difference minutes out of range"); tzd += sign*(hours*3600 + minutes*60); diff --git a/Foundation/testsuite/src/DateTimeParserTest.cpp b/Foundation/testsuite/src/DateTimeParserTest.cpp index 8bae2bd74e..b61cd9249c 100644 --- a/Foundation/testsuite/src/DateTimeParserTest.cpp +++ b/Foundation/testsuite/src/DateTimeParserTest.cpp @@ -616,6 +616,12 @@ void DateTimeParserTest::testCustom() catch (SyntaxException&) { } + + // bad year (not a number) + testBad("%y", "YY", tzd); + + // bad year (number too big) + testBad("%r", "123456789101112131415", tzd); } From 5d3d19a45b10580f999556a2df84b37ebe4e3faf Mon Sep 17 00:00:00 2001 From: Andrew Auclair Date: Mon, 24 Jun 2024 21:10:37 -0400 Subject: [PATCH 2/5] DateTimeParser Validation Additional change to validate milliseconds field if the . or , exists. --- Foundation/src/DateTimeParser.cpp | 6 ++++++ Foundation/testsuite/src/DateTimeParserTest.cpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/Foundation/src/DateTimeParser.cpp b/Foundation/src/DateTimeParser.cpp index 6be140f31e..7e10f2d139 100644 --- a/Foundation/src/DateTimeParser.cpp +++ b/Foundation/src/DateTimeParser.cpp @@ -253,6 +253,12 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat if (it != end && (*it == '.' || *it == ',')) { ++it; + + if (it != end && !Ascii::isDigit(*it)) + { + throw SyntaxException("Invalid DateTimeString: " + dtStr + ", missing millisecond"); + } + millis = parse_fractional_n(it, end, 3); micros = parse_fractional_n(it, end, 3); it = skip_digits(it, end); diff --git a/Foundation/testsuite/src/DateTimeParserTest.cpp b/Foundation/testsuite/src/DateTimeParserTest.cpp index b61cd9249c..e0afc67fd0 100644 --- a/Foundation/testsuite/src/DateTimeParserTest.cpp +++ b/Foundation/testsuite/src/DateTimeParserTest.cpp @@ -177,6 +177,7 @@ void DateTimeParserTest::testISO8601Frac() assertTrue (dt.microsecond() == 0); assertTrue (tzd == 0); testBad(DateTimeFormat::ISO8601_FRAC_FORMAT, "2005-01-08T12:30:00.1J", tzd); + testBad(DateTimeFormat::ISO8601_FRAC_FORMAT, "2005-01-08T12:30:00.Z", tzd); dt = DateTimeParser::parse(DateTimeFormat::ISO8601_FRAC_FORMAT, "2005-01-08T12:30:00.123+01:00", tzd); assertTrue (dt.year() == 2005); @@ -622,6 +623,9 @@ void DateTimeParserTest::testCustom() // bad year (number too big) testBad("%r", "123456789101112131415", tzd); + + // check that an invalid millisecond is detected with a custom format + testBad("T%H:%M:%s %z", "T12:30:00.Z", tzd); } From 85b3c347a0e2a83a1ebd45328322b2d364fa2eef Mon Sep 17 00:00:00 2001 From: Andrew Auclair Date: Tue, 25 Jun 2024 18:30:09 -0400 Subject: [PATCH 3/5] Fix CodeQL Issues --- Foundation/src/DateTimeParser.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Foundation/src/DateTimeParser.cpp b/Foundation/src/DateTimeParser.cpp index 7e10f2d139..f07b6091b7 100644 --- a/Foundation/src/DateTimeParser.cpp +++ b/Foundation/src/DateTimeParser.cpp @@ -62,7 +62,6 @@ namespace { } std::string number(num_start, it); - int result = 0; try { return std::stoi(number); @@ -108,7 +107,6 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat } std::string number(num_start, it); - int result = 0; try { return std::stoi(number); @@ -468,7 +466,6 @@ int DateTimeParser::parseTZD(std::string::const_iterator& it, const std::string: throw SyntaxException("Timezone invalid number: minutes"); } - // PARSE_NUMBER_N(minutes, 2); if (minutes < 0 || minutes > 59) throw SyntaxException("Timezone difference minutes out of range"); tzd += sign*(hours*3600 + minutes*60); From 00c6f94a9eefa54515bd76e55ef292af65eaff28 Mon Sep 17 00:00:00 2001 From: Andrew Auclair Date: Wed, 26 Jun 2024 09:37:36 -0400 Subject: [PATCH 4/5] Fix Naming --- Foundation/src/DateTimeParser.cpp | 102 +++++++++++++++--------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/Foundation/src/DateTimeParser.cpp b/Foundation/src/DateTimeParser.cpp index f07b6091b7..25afa54b42 100644 --- a/Foundation/src/DateTimeParser.cpp +++ b/Foundation/src/DateTimeParser.cpp @@ -21,9 +21,9 @@ #include namespace { - using parse_iter = std::string::const_iterator; + using ParseIter = std::string::const_iterator; - [[nodiscard]] parse_iter skip_non_digits(parse_iter it, parse_iter end) + [[nodiscard]] ParseIter skipNonDigits(ParseIter it, ParseIter end) { while (it != end && !Poco::Ascii::isDigit(*it)) { @@ -33,7 +33,7 @@ namespace { } - [[nodiscard]] parse_iter skip_digits(parse_iter it, parse_iter end) + [[nodiscard]] ParseIter skipDigits(ParseIter it, ParseIter end) { while (it != end && Poco::Ascii::isDigit(*it)) { @@ -43,25 +43,25 @@ namespace { } - int parse_number_n(const std::string& dtStr, parse_iter& it, parse_iter end, int n) + int parseNumberN(const std::string& dtStr, ParseIter& it, ParseIter end, int n) { - parse_iter num_start = end; + ParseIter numStart = end; int i = 0; for (; it != end && i < n && Poco::Ascii::isDigit(*it); ++it, ++i) { - if (num_start == end) + if (numStart == end) { - num_start = it; + numStart = it; } } - if (num_start == end) + if (numStart == end) { throw Poco::SyntaxException("Invalid DateTimeString: " + dtStr + ", No number found to parse"); } - std::string number(num_start, it); + std::string number(numStart, it); try { return std::stoi(number); @@ -89,24 +89,24 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat throw SyntaxException("Invalid DateTimeString: " + dtStr); } - const auto parse_number = [&dtStr](parse_iter& it, parse_iter end) + const auto parse_number = [&dtStr](ParseIter& it, ParseIter end) { - parse_iter num_start = end; + ParseIter numStart = end; for (; it != end && Poco::Ascii::isDigit(*it); ++it) { - if (num_start == end) + if (numStart == end) { - num_start = it; + numStart = it; } } - if (num_start == end) + if (numStart == end) { throw Poco::SyntaxException("Invalid DateTimeString: " + dtStr + ", No number found to parse"); } - std::string number(num_start, it); + std::string number(numStart, it); try { return std::stoi(number); @@ -119,25 +119,25 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat - const auto parse_fractional_n = [dtStr](parse_iter& it, parse_iter end, int n) + const auto parseFractionalN = [dtStr](ParseIter& it, ParseIter end, int n) { - parse_iter num_start = end; + ParseIter numStart = end; int i = 0; for (; it != end && i < n && Poco::Ascii::isDigit(*it); ++it, ++i) { - if (num_start == end) + if (numStart == end) { - num_start = it; + numStart = it; } } - if (num_start == end) + if (numStart == end) { return 0; } - std::string number(num_start, it); + std::string number(numStart, it); int result = 0; try { @@ -192,31 +192,31 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat case 'd': case 'e': case 'f': - it = skip_non_digits(it, end); - day = parse_number_n(dtStr, it, end, 2); + it = skipNonDigits(it, end); + day = parseNumberN(dtStr, it, end, 2); dayParsed = true; break; case 'm': case 'n': case 'o': - it = skip_non_digits(it, end); - month = parse_number_n(dtStr, it, end, 2); + it = skipNonDigits(it, end); + month = parseNumberN(dtStr, it, end, 2); monthParsed = true; break; case 'y': - it = skip_non_digits(it, end); - year = parse_number_n(dtStr, it, end, 2); + it = skipNonDigits(it, end); + year = parseNumberN(dtStr, it, end, 2); if (year >= 69) year += 1900; else year += 2000; break; case 'Y': - it = skip_non_digits(it, end); - year = parse_number_n(dtStr, it, end, 4); + it = skipNonDigits(it, end); + year = parseNumberN(dtStr, it, end, 4); break; case 'r': - it = skip_non_digits(it, end); + it = skipNonDigits(it, end); year = parse_number(it, end); if (year < 1000) @@ -229,24 +229,24 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat break; case 'H': case 'h': - it = skip_non_digits(it, end); - hour = parse_number_n(dtStr, it, end, 2); + it = skipNonDigits(it, end); + hour = parseNumberN(dtStr, it, end, 2); break; case 'a': case 'A': hour = parseAMPM(it, end, hour); break; case 'M': - it = skip_non_digits(it, end); - minute = parse_number_n(dtStr, it, end, 2); + it = skipNonDigits(it, end); + minute = parseNumberN(dtStr, it, end, 2); break; case 'S': - it = skip_non_digits(it, end); - second = parse_number_n(dtStr, it, end, 2); + it = skipNonDigits(it, end); + second = parseNumberN(dtStr, it, end, 2); break; case 's': - it = skip_non_digits(it, end); - second = parse_number_n(dtStr, it, end, 2); + it = skipNonDigits(it, end); + second = parseNumberN(dtStr, it, end, 2); if (it != end && (*it == '.' || *it == ',')) { @@ -257,25 +257,25 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, Dat throw SyntaxException("Invalid DateTimeString: " + dtStr + ", missing millisecond"); } - millis = parse_fractional_n(it, end, 3); - micros = parse_fractional_n(it, end, 3); - it = skip_digits(it, end); + millis = parseFractionalN(it, end, 3); + micros = parseFractionalN(it, end, 3); + it = skipDigits(it, end); } break; case 'i': - it = skip_non_digits(it, end); - millis = parse_number_n(dtStr, it, end, 3); + it = skipNonDigits(it, end); + millis = parseNumberN(dtStr, it, end, 3); break; case 'c': - it = skip_non_digits(it, end); - millis = parse_number_n(dtStr, it, end, 1); + it = skipNonDigits(it, end); + millis = parseNumberN(dtStr, it, end, 1); millis *= 100; break; case 'F': - it = skip_non_digits(it, end); - millis = parse_number_n(dtStr, it, end, 3); - micros = parse_number_n(dtStr, it, end, 3); - it = skip_digits(it, end); + it = skipNonDigits(it, end); + millis = parseNumberN(dtStr, it, end, 3); + micros = parseNumberN(dtStr, it, end, 3); + it = skipDigits(it, end); break; case 'z': case 'Z': @@ -446,7 +446,7 @@ int DateTimeParser::parseTZD(std::string::const_iterator& it, const std::string: int hours = 0; try { - hours = parse_number_n("", it, end, 2); + hours = parseNumberN("", it, end, 2); } catch(const SyntaxException& e) { @@ -459,7 +459,7 @@ int DateTimeParser::parseTZD(std::string::const_iterator& it, const std::string: int minutes = 0; try { - minutes = parse_number_n("", it, end, 2); + minutes = parseNumberN("", it, end, 2); } catch(const SyntaxException& e) { From 325f35e9a2da9dc33bf5e881b310d334bb7431f6 Mon Sep 17 00:00:00 2001 From: Andrew Auclair Date: Wed, 26 Jun 2024 09:39:41 -0400 Subject: [PATCH 5/5] Removing REGEX_LIST REGEX_LIST was only used in isValid, which now uses a cached list of RegularExpressions instead. --- Foundation/include/Poco/DateTimeFormat.h | 3 --- Foundation/src/DateTimeFormat.cpp | 22 +++------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/Foundation/include/Poco/DateTimeFormat.h b/Foundation/include/Poco/DateTimeFormat.h index 291bf18b22..069eebf119 100644 --- a/Foundation/include/Poco/DateTimeFormat.h +++ b/Foundation/include/Poco/DateTimeFormat.h @@ -128,9 +128,6 @@ class Foundation_API DateTimeFormat static bool isValid(const std::string& dateTime); /// Returns true if dateTime validates against at least one supported format. - typedef std::unordered_set RegexList; - static RegexList REGEX_LIST; - private: typedef std::unordered_set Formatlist; static Formatlist FORMAT_LIST; diff --git a/Foundation/src/DateTimeFormat.cpp b/Foundation/src/DateTimeFormat.cpp index ce085f50ff..0e296323f7 100644 --- a/Foundation/src/DateTimeFormat.cpp +++ b/Foundation/src/DateTimeFormat.cpp @@ -129,19 +129,6 @@ const std::string DateTimeFormat::MONTH_NAMES[] = }; -DateTimeFormat::RegexList DateTimeFormat::REGEX_LIST = -{ - &DateTimeFormat::ISO8601_REGEX, - &DateTimeFormat::RFC822_REGEX, - &DateTimeFormat::RFC1123_REGEX, - &DateTimeFormat::HTTP_REGEX, - &DateTimeFormat::RFC850_REGEX, - &DateTimeFormat::RFC1036_REGEX, - &DateTimeFormat::ASCTIME_REGEX, - &DateTimeFormat::SORTABLE_REGEX -}; - - bool DateTimeFormat::hasFormat(const std::string& fmt) { return FORMAT_LIST.find(fmt) != FORMAT_LIST.end(); @@ -150,8 +137,7 @@ bool DateTimeFormat::hasFormat(const std::string& fmt) bool DateTimeFormat::isValid(const std::string& dateTime) { - - static const RegularExpression regs[] = { + static const RegularExpression regexList[] = { RegularExpression(DateTimeFormat::ISO8601_REGEX), RegularExpression(DateTimeFormat::RFC822_REGEX), RegularExpression(DateTimeFormat::RFC1123_REGEX), @@ -161,10 +147,8 @@ bool DateTimeFormat::isValid(const std::string& dateTime) RegularExpression(DateTimeFormat::ASCTIME_REGEX), RegularExpression(DateTimeFormat::SORTABLE_REGEX) }; - // make sure the regex list and the array of regexes are in sync - poco_assert((sizeof(regs) / sizeof(regs[0])) == REGEX_LIST.size()); - - for (const auto& f : regs) + + for (const auto& f : regexList) { if (f.match(dateTime)) return true; }