diff --git a/src/Nibbler.cpp b/src/Nibbler.cpp index d30ceea8d..3630924e4 100644 --- a/src/Nibbler.cpp +++ b/src/Nibbler.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -264,6 +265,19 @@ bool Nibbler::getQuoted ( return false; } +//////////////////////////////////////////////////////////////////////////////// +bool Nibbler::getDigit (int& result) +{ + if (mCursor < mLength && + isdigit (mInput[mCursor])) + { + result = mInput[mCursor++] - '0'; + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////////////////// bool Nibbler::getInt (int& result) { @@ -501,6 +515,78 @@ bool Nibbler::getUUID (std::string& result) return false; } +//////////////////////////////////////////////////////////////////////////////// +// 19980119T070000Z = YYYYMMDDThhmmssZ +bool Nibbler::getDateISO (time_t& t) +{ + std::string::size_type i = mCursor; + + if (i < mLength && + mLength - i >= 16) + { + if (isdigit (mInput[i + 0]) && + isdigit (mInput[i + 1]) && + isdigit (mInput[i + 2]) && + isdigit (mInput[i + 3]) && + isdigit (mInput[i + 4]) && + isdigit (mInput[i + 5]) && + isdigit (mInput[i + 6]) && + isdigit (mInput[i + 7]) && + mInput[i + 8] == 'T' && + isdigit (mInput[i + 9]) && + isdigit (mInput[i + 10]) && + isdigit (mInput[i + 11]) && + isdigit (mInput[i + 12]) && + isdigit (mInput[i + 13]) && + isdigit (mInput[i + 14]) && + mInput[i + 15] == 'Z') + { + mCursor += 16; + + int year = (mInput[i + 0] - '0') * 1000 + + (mInput[i + 1] - '0') * 100 + + (mInput[i + 2] - '0') * 10 + + (mInput[i + 3] - '0'); + + int month = (mInput[i + 4] - '0') * 10 + + (mInput[i + 5] - '0'); + + int day = (mInput[i + 6] - '0') * 10 + + (mInput[i + 7] - '0'); + + int hour = (mInput[i + 9] - '0') * 10 + + (mInput[i + 10] - '0'); + + int minute = (mInput[i + 11] - '0') * 10 + + (mInput[i + 12] - '0'); + + int second = (mInput[i + 13] - '0') * 10 + + (mInput[i + 14] - '0'); + + // Convert to epoch. + struct tm tms = {0}; + tms.tm_isdst = -1; // Requests that mktime determine summer time effect. + tms.tm_mday = day; + tms.tm_mon = month - 1; + tms.tm_year = year - 1900; + tms.tm_hour = hour; + tms.tm_min = minute; + tms.tm_sec = second; + + t = timegm (&tms); + return true; + } + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Nibbler::getDate (const std::string& format, time_t& t) +{ + return false; +} + //////////////////////////////////////////////////////////////////////////////// bool Nibbler::skipN (const int quantity /* = 1 */) { diff --git a/src/Nibbler.h b/src/Nibbler.h index 0e0853acb..9dc92e9f3 100644 --- a/src/Nibbler.h +++ b/src/Nibbler.h @@ -53,6 +53,7 @@ public: */ bool getQuoted (char, std::string&, bool quote = false); + bool getDigit (int&); bool getInt (int&); bool getHex (int&); bool getUnsignedInt (int&); @@ -60,6 +61,8 @@ public: bool getLiteral (const std::string&); bool getRx (const std::string&, std::string&); bool getUUID (std::string&); + bool getDateISO (time_t&); + bool getDate (const std::string&, time_t&); bool skipN (const int quantity = 1); bool skip (char); diff --git a/test/nibbler.t.cpp b/test/nibbler.t.cpp index b59457bf6..a6ed28e33 100644 --- a/test/nibbler.t.cpp +++ b/test/nibbler.t.cpp @@ -33,7 +33,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { - UnitTest t (171); + UnitTest t (185); try { @@ -41,6 +41,7 @@ int main (int argc, char** argv) std::string s; int i; double d; + time_t ti; // Make sure the nibbler behaves itself with trivial input. t.diag ("Test all nibbler calls given empty input"); @@ -53,11 +54,14 @@ int main (int argc, char** argv) t.notok (n.skipAll ('x'), "trivial: skipAll"); t.notok (n.skipAllOneOf ("abc"), "trivial: skipAllOneOf"); t.notok (n.getQuoted ('"', s), "trivial: getQuoted"); + t.notok (n.getDigit (i), "trivial: getDigit"); t.notok (n.getInt (i), "trivial: getInt"); t.notok (n.getHex (i), "trivial: getHex"); t.notok (n.getUnsignedInt (i), "trivial: getUnsignedInt"); t.notok (n.getUntilEOL (s), "trivial: getUntilEOL"); t.notok (n.getUntilEOS (s), "trivial: getUntilEOS"); + t.notok (n.getDateISO (ti), "trivial: getDateISO"); + t.notok (n.getDate ("YYYYMMDD", ti), "trivial: getDate"); t.ok (n.depleted (), "trivial: depleted"); // bool getUntil (char, std::string&); @@ -209,6 +213,15 @@ int main (int argc, char** argv) t.ok (n.getQuoted ('"', s, true), "\"one\\\"two\" : getQuoted ('\"', true, true) -> true"); // 93 t.is (s, "\"one\"two\"", "getQuoted ('\"', true) -> \"one\"two\""); // 94 + // bool getDigit (int&); + t.diag ("Nibbler::getDigit"); + n = Nibbler ("12x"); + t.ok (n.getDigit (i), " '12x' : getdigit () -> true"); + t.is (i, 1, " '12x' : getdigit () -> 1"); + t.ok (n.getDigit (i), " '2x' : getdigit () -> true"); + t.is (i, 2, " '2x' : getdigit () -> 2"); + t.notok (n.getDigit (i), " 'x' : getdigit () -> false"); + // bool getInt (int&); t.diag ("Nibbler::getInt"); n = Nibbler ("123 -4"); @@ -286,6 +299,18 @@ int main (int argc, char** argv) t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5", "uuid 2 -> correct"); t.ok (n.depleted (), "depleted"); + // bool getDateISO (time_t&); + t.diag ("Nibbler::getDateISO"); + n = Nibbler ("19980119T070000Z"); + t.ok (n.getDateISO (ti), "'19980119T070000Z': getDateISO () -> true"); + t.is (ti, 885193200, "'19980119T070000Z': getDateISO () -> 885193200"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("20090213T233130Z"); + t.ok (n.getDateISO (ti), "'20090213T233130Z': getDateISO () -> true"); + t.is (ti, 1234567890, "'20090213T233130Z': getDateISO () -> 1234567890"); + t.ok (n.depleted (), "depleted"); + // bool getUntilEOL (std::string&); t.diag ("Nibbler::getUntilEOL"); n = Nibbler ("one\ntwo");