mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Nibbler: Improve import performance
Takes the "import" performance test from 5m5s on a test machine to 13s total. A huge part of the previously morbid performance were memory allocation and release for very little benefit in the JSON parser. With this new approach the copying is kept to a minimum. There is still room for improvements.
This commit is contained in:
parent
e478396a04
commit
605f8020b7
2 changed files with 162 additions and 161 deletions
320
src/Nibbler.cpp
320
src/Nibbler.cpp
|
@ -39,14 +39,14 @@
|
||||||
#endif
|
#endif
|
||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
static const char* _uuid_pattern = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
|
static const char* _uuid_pattern = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
|
||||||
static const unsigned int _uuid_min_length = 8;
|
static const unsigned int _uuid_min_length = 8;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Nibbler::Nibbler ()
|
Nibbler::Nibbler ()
|
||||||
: _input ("")
|
: _length (0)
|
||||||
, _length (0)
|
|
||||||
, _cursor (0)
|
, _cursor (0)
|
||||||
, _saved (0)
|
, _saved (0)
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,7 @@ Nibbler::Nibbler ()
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Nibbler::Nibbler (const std::string& input)
|
Nibbler::Nibbler (const std::string& input)
|
||||||
: _input (input)
|
: _input (std::make_shared <std::string> (input))
|
||||||
, _length (input.length ())
|
, _length (input.length ())
|
||||||
, _cursor (0)
|
, _cursor (0)
|
||||||
{
|
{
|
||||||
|
@ -92,15 +92,15 @@ bool Nibbler::getUntil (char c, std::string& result)
|
||||||
{
|
{
|
||||||
if (_cursor < _length)
|
if (_cursor < _length)
|
||||||
{
|
{
|
||||||
auto i = _input.find (c, _cursor);
|
auto i = _input->find (c, _cursor);
|
||||||
if (i != std::string::npos)
|
if (i != std::string::npos)
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor, i - _cursor);
|
result = _input->substr (_cursor, i - _cursor);
|
||||||
_cursor = i;
|
_cursor = i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor);
|
result = _input->substr (_cursor);
|
||||||
_cursor = _length;
|
_cursor = _length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,15 +115,15 @@ bool Nibbler::getUntil (const std::string& terminator, std::string& result)
|
||||||
{
|
{
|
||||||
if (_cursor < _length)
|
if (_cursor < _length)
|
||||||
{
|
{
|
||||||
auto i = _input.find (terminator, _cursor);
|
auto i = _input->find (terminator, _cursor);
|
||||||
if (i != std::string::npos)
|
if (i != std::string::npos)
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor, i - _cursor);
|
result = _input->substr (_cursor, i - _cursor);
|
||||||
_cursor = i;
|
_cursor = i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor);
|
result = _input->substr (_cursor);
|
||||||
_cursor = _length;
|
_cursor = _length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,14 +142,14 @@ bool Nibbler::getUntilRx (const std::string& regex, std::string& result)
|
||||||
RX r (regex, true);
|
RX r (regex, true);
|
||||||
std::vector <int> start;
|
std::vector <int> start;
|
||||||
std::vector <int> end;
|
std::vector <int> end;
|
||||||
if (r.match (start, end, _input.substr (_cursor)))
|
if (r.match (start, end, _input->substr (_cursor)))
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor, start[0]);
|
result = _input->substr (_cursor, start[0]);
|
||||||
_cursor += start[0];
|
_cursor += start[0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor);
|
result = _input->substr (_cursor);
|
||||||
_cursor = _length;
|
_cursor = _length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,15 +165,15 @@ bool Nibbler::getUntilOneOf (const std::string& chars, std::string& result)
|
||||||
{
|
{
|
||||||
if (_cursor < _length)
|
if (_cursor < _length)
|
||||||
{
|
{
|
||||||
auto i = _input.find_first_of (chars, _cursor);
|
auto i = _input->find_first_of (chars, _cursor);
|
||||||
if (i != std::string::npos)
|
if (i != std::string::npos)
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor, i - _cursor);
|
result = _input->substr (_cursor, i - _cursor);
|
||||||
_cursor = i;
|
_cursor = i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor);
|
result = _input->substr (_cursor);
|
||||||
_cursor = _length;
|
_cursor = _length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ bool Nibbler::getUntilEOS (std::string& result)
|
||||||
{
|
{
|
||||||
if (_cursor < _length)
|
if (_cursor < _length)
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor);
|
result = _input->substr (_cursor);
|
||||||
_cursor = _length;
|
_cursor = _length;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ bool Nibbler::getN (const int quantity, std::string& result)
|
||||||
{
|
{
|
||||||
if (_cursor + quantity <= _length)
|
if (_cursor + quantity <= _length)
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor, quantity);
|
result = _input->substr (_cursor, quantity);
|
||||||
_cursor += quantity;
|
_cursor += quantity;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -234,14 +234,14 @@ bool Nibbler::getQuoted (
|
||||||
result = "";
|
result = "";
|
||||||
|
|
||||||
if (_cursor >= _length ||
|
if (_cursor >= _length ||
|
||||||
_input[_cursor] != c)
|
(*_input)[_cursor] != c)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i = _cursor; i < _length; ++i)
|
for (auto i = _cursor; i < _length; ++i)
|
||||||
{
|
{
|
||||||
current = _input[i];
|
current = (*_input)[i];
|
||||||
|
|
||||||
if (current == '\\' && !inescape)
|
if (current == '\\' && !inescape)
|
||||||
{
|
{
|
||||||
|
@ -285,9 +285,9 @@ bool Nibbler::getQuoted (
|
||||||
bool Nibbler::getDigit (int& result)
|
bool Nibbler::getDigit (int& result)
|
||||||
{
|
{
|
||||||
if (_cursor < _length &&
|
if (_cursor < _length &&
|
||||||
Lexer::isDigit (_input[_cursor]))
|
Lexer::isDigit ((*_input)[_cursor]))
|
||||||
{
|
{
|
||||||
result = _input[_cursor++] - '0';
|
result = (*_input)[_cursor++] - '0';
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,14 +301,14 @@ bool Nibbler::getDigit6 (int& result)
|
||||||
if (i < _length &&
|
if (i < _length &&
|
||||||
_length - i >= 6)
|
_length - i >= 6)
|
||||||
{
|
{
|
||||||
if (Lexer::isDigit (_input[i + 0]) &&
|
if (Lexer::isDigit ((*_input)[i + 0]) &&
|
||||||
Lexer::isDigit (_input[i + 1]) &&
|
Lexer::isDigit ((*_input)[i + 1]) &&
|
||||||
Lexer::isDigit (_input[i + 2]) &&
|
Lexer::isDigit ((*_input)[i + 2]) &&
|
||||||
Lexer::isDigit (_input[i + 3]) &&
|
Lexer::isDigit ((*_input)[i + 3]) &&
|
||||||
Lexer::isDigit (_input[i + 4]) &&
|
Lexer::isDigit ((*_input)[i + 4]) &&
|
||||||
Lexer::isDigit (_input[i + 5]))
|
Lexer::isDigit ((*_input)[i + 5]))
|
||||||
{
|
{
|
||||||
result = strtoimax (_input.substr (_cursor, 6).c_str (), NULL, 10);
|
result = strtoimax (_input->substr (_cursor, 6).c_str (), NULL, 10);
|
||||||
_cursor += 6;
|
_cursor += 6;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -324,12 +324,12 @@ bool Nibbler::getDigit4 (int& result)
|
||||||
if (i < _length &&
|
if (i < _length &&
|
||||||
_length - i >= 4)
|
_length - i >= 4)
|
||||||
{
|
{
|
||||||
if (Lexer::isDigit (_input[i + 0]) &&
|
if (Lexer::isDigit ((*_input)[i + 0]) &&
|
||||||
Lexer::isDigit (_input[i + 1]) &&
|
Lexer::isDigit ((*_input)[i + 1]) &&
|
||||||
Lexer::isDigit (_input[i + 2]) &&
|
Lexer::isDigit ((*_input)[i + 2]) &&
|
||||||
Lexer::isDigit (_input[i + 3]))
|
Lexer::isDigit ((*_input)[i + 3]))
|
||||||
{
|
{
|
||||||
result = strtoimax (_input.substr (_cursor, 4).c_str (), NULL, 10);
|
result = strtoimax (_input->substr (_cursor, 4).c_str (), NULL, 10);
|
||||||
_cursor += 4;
|
_cursor += 4;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -345,11 +345,11 @@ bool Nibbler::getDigit3 (int& result)
|
||||||
if (i < _length &&
|
if (i < _length &&
|
||||||
_length - i >= 3)
|
_length - i >= 3)
|
||||||
{
|
{
|
||||||
if (Lexer::isDigit (_input[i + 0]) &&
|
if (Lexer::isDigit ((*_input)[i + 0]) &&
|
||||||
Lexer::isDigit (_input[i + 1]) &&
|
Lexer::isDigit ((*_input)[i + 1]) &&
|
||||||
Lexer::isDigit (_input[i + 2]))
|
Lexer::isDigit ((*_input)[i + 2]))
|
||||||
{
|
{
|
||||||
result = strtoimax (_input.substr (_cursor, 3).c_str (), NULL, 10);
|
result = strtoimax (_input->substr (_cursor, 3).c_str (), NULL, 10);
|
||||||
_cursor += 3;
|
_cursor += 3;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -365,10 +365,10 @@ bool Nibbler::getDigit2 (int& result)
|
||||||
if (i < _length &&
|
if (i < _length &&
|
||||||
_length - i >= 2)
|
_length - i >= 2)
|
||||||
{
|
{
|
||||||
if (Lexer::isDigit (_input[i + 0]) &&
|
if (Lexer::isDigit ((*_input)[i + 0]) &&
|
||||||
Lexer::isDigit (_input[i + 1]))
|
Lexer::isDigit ((*_input)[i + 1]))
|
||||||
{
|
{
|
||||||
result = strtoimax (_input.substr (_cursor, 2).c_str (), NULL, 10);
|
result = strtoimax (_input->substr (_cursor, 2).c_str (), NULL, 10);
|
||||||
_cursor += 2;
|
_cursor += 2;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -384,19 +384,19 @@ bool Nibbler::getInt (int& result)
|
||||||
|
|
||||||
if (i < _length)
|
if (i < _length)
|
||||||
{
|
{
|
||||||
if (_input[i] == '-')
|
if ((*_input)[i] == '-')
|
||||||
++i;
|
++i;
|
||||||
else if (_input[i] == '+')
|
else if ((*_input)[i] == '+')
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Potential for use of find_first_not_of
|
// TODO Potential for use of find_first_not_of
|
||||||
while (i < _length && Lexer::isDigit (_input[i]))
|
while (i < _length && Lexer::isDigit ((*_input)[i]))
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
if (i > _cursor)
|
if (i > _cursor)
|
||||||
{
|
{
|
||||||
result = strtoimax (_input.substr (_cursor, i - _cursor).c_str (), NULL, 10);
|
result = strtoimax (_input->substr (_cursor, i - _cursor).c_str (), NULL, 10);
|
||||||
_cursor = i;
|
_cursor = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -409,12 +409,12 @@ bool Nibbler::getUnsignedInt (int& result)
|
||||||
{
|
{
|
||||||
auto i = _cursor;
|
auto i = _cursor;
|
||||||
// TODO Potential for use of find_first_not_of
|
// TODO Potential for use of find_first_not_of
|
||||||
while (i < _length && Lexer::isDigit (_input[i]))
|
while (i < _length && Lexer::isDigit ((*_input)[i]))
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
if (i > _cursor)
|
if (i > _cursor)
|
||||||
{
|
{
|
||||||
result = strtoimax (_input.substr (_cursor, i - _cursor).c_str (), NULL, 10);
|
result = strtoimax (_input->substr (_cursor, i - _cursor).c_str (), NULL, 10);
|
||||||
_cursor = i;
|
_cursor = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -443,42 +443,42 @@ bool Nibbler::getNumber (std::string& result)
|
||||||
auto i = _cursor;
|
auto i = _cursor;
|
||||||
|
|
||||||
// [+-]?
|
// [+-]?
|
||||||
if (i < _length && (_input[i] == '-' || _input[i] == '+'))
|
if (i < _length && ((*_input)[i] == '-' || (*_input)[i] == '+'))
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
// digit+
|
// digit+
|
||||||
if (i < _length && Lexer::isDigit (_input[i]))
|
if (i < _length && Lexer::isDigit ((*_input)[i]))
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
while (i < _length && Lexer::isDigit (_input[i]))
|
while (i < _length && Lexer::isDigit ((*_input)[i]))
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
// ( . digit+ )?
|
// ( . digit+ )?
|
||||||
if (i < _length && _input[i] == '.')
|
if (i < _length && (*_input)[i] == '.')
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
while (i < _length && Lexer::isDigit (_input[i]))
|
while (i < _length && Lexer::isDigit ((*_input)[i]))
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ( [eE] [+-]? digit+ )?
|
// ( [eE] [+-]? digit+ )?
|
||||||
if (i < _length && (_input[i] == 'e' || _input[i] == 'E'))
|
if (i < _length && ((*_input)[i] == 'e' || (*_input)[i] == 'E'))
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
if (i < _length && (_input[i] == '+' || _input[i] == '-'))
|
if (i < _length && ((*_input)[i] == '+' || (*_input)[i] == '-'))
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
if (i < _length && Lexer::isDigit (_input[i]))
|
if (i < _length && Lexer::isDigit ((*_input)[i]))
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
while (i < _length && Lexer::isDigit (_input[i]))
|
while (i < _length && Lexer::isDigit ((*_input)[i]))
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
result = _input.substr (_cursor, i - _cursor);
|
result = _input->substr (_cursor, i - _cursor);
|
||||||
_cursor = i;
|
_cursor = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -486,7 +486,7 @@ bool Nibbler::getNumber (std::string& result)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = _input.substr (_cursor, i - _cursor);
|
result = _input->substr (_cursor, i - _cursor);
|
||||||
_cursor = i;
|
_cursor = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -512,7 +512,7 @@ bool Nibbler::getNumber (double &result)
|
||||||
bool Nibbler::getLiteral (const std::string& literal)
|
bool Nibbler::getLiteral (const std::string& literal)
|
||||||
{
|
{
|
||||||
if (_cursor < _length &&
|
if (_cursor < _length &&
|
||||||
_input.find (literal, _cursor) == _cursor)
|
_input->find (literal, _cursor) == _cursor)
|
||||||
{
|
{
|
||||||
_cursor += literal.length ();
|
_cursor += literal.length ();
|
||||||
return true;
|
return true;
|
||||||
|
@ -537,7 +537,7 @@ bool Nibbler::getRx (const std::string& regex, std::string& result)
|
||||||
|
|
||||||
RX r (modified_regex, true);
|
RX r (modified_regex, true);
|
||||||
std::vector <std::string> results;
|
std::vector <std::string> results;
|
||||||
if (r.match (results, _input.substr (_cursor)))
|
if (r.match (results, _input->substr (_cursor)))
|
||||||
{
|
{
|
||||||
result = results[0];
|
result = results[0];
|
||||||
_cursor += result.length ();
|
_cursor += result.length ();
|
||||||
|
@ -558,44 +558,44 @@ bool Nibbler::getUUID (std::string& result)
|
||||||
_length - i >= 36)
|
_length - i >= 36)
|
||||||
{
|
{
|
||||||
// 88888888-4444-4444-4444-cccccccccccc
|
// 88888888-4444-4444-4444-cccccccccccc
|
||||||
if (isxdigit (_input[i + 0]) &&
|
if (isxdigit ((*_input)[i + 0]) &&
|
||||||
isxdigit (_input[i + 1]) &&
|
isxdigit ((*_input)[i + 1]) &&
|
||||||
isxdigit (_input[i + 2]) &&
|
isxdigit ((*_input)[i + 2]) &&
|
||||||
isxdigit (_input[i + 3]) &&
|
isxdigit ((*_input)[i + 3]) &&
|
||||||
isxdigit (_input[i + 4]) &&
|
isxdigit ((*_input)[i + 4]) &&
|
||||||
isxdigit (_input[i + 5]) &&
|
isxdigit ((*_input)[i + 5]) &&
|
||||||
isxdigit (_input[i + 6]) &&
|
isxdigit ((*_input)[i + 6]) &&
|
||||||
isxdigit (_input[i + 7]) &&
|
isxdigit ((*_input)[i + 7]) &&
|
||||||
_input[i + 8] == '-' &&
|
(*_input)[i + 8] == '-' &&
|
||||||
isxdigit (_input[i + 9]) &&
|
isxdigit ((*_input)[i + 9]) &&
|
||||||
isxdigit (_input[i + 10]) &&
|
isxdigit ((*_input)[i + 10]) &&
|
||||||
isxdigit (_input[i + 11]) &&
|
isxdigit ((*_input)[i + 11]) &&
|
||||||
isxdigit (_input[i + 12]) &&
|
isxdigit ((*_input)[i + 12]) &&
|
||||||
_input[i + 13] == '-' &&
|
(*_input)[i + 13] == '-' &&
|
||||||
isxdigit (_input[i + 14]) &&
|
isxdigit ((*_input)[i + 14]) &&
|
||||||
isxdigit (_input[i + 15]) &&
|
isxdigit ((*_input)[i + 15]) &&
|
||||||
isxdigit (_input[i + 16]) &&
|
isxdigit ((*_input)[i + 16]) &&
|
||||||
isxdigit (_input[i + 17]) &&
|
isxdigit ((*_input)[i + 17]) &&
|
||||||
_input[i + 18] == '-' &&
|
(*_input)[i + 18] == '-' &&
|
||||||
isxdigit (_input[i + 19]) &&
|
isxdigit ((*_input)[i + 19]) &&
|
||||||
isxdigit (_input[i + 20]) &&
|
isxdigit ((*_input)[i + 20]) &&
|
||||||
isxdigit (_input[i + 21]) &&
|
isxdigit ((*_input)[i + 21]) &&
|
||||||
isxdigit (_input[i + 22]) &&
|
isxdigit ((*_input)[i + 22]) &&
|
||||||
_input[i + 23] == '-' &&
|
(*_input)[i + 23] == '-' &&
|
||||||
isxdigit (_input[i + 24]) &&
|
isxdigit ((*_input)[i + 24]) &&
|
||||||
isxdigit (_input[i + 25]) &&
|
isxdigit ((*_input)[i + 25]) &&
|
||||||
isxdigit (_input[i + 26]) &&
|
isxdigit ((*_input)[i + 26]) &&
|
||||||
isxdigit (_input[i + 27]) &&
|
isxdigit ((*_input)[i + 27]) &&
|
||||||
isxdigit (_input[i + 28]) &&
|
isxdigit ((*_input)[i + 28]) &&
|
||||||
isxdigit (_input[i + 29]) &&
|
isxdigit ((*_input)[i + 29]) &&
|
||||||
isxdigit (_input[i + 30]) &&
|
isxdigit ((*_input)[i + 30]) &&
|
||||||
isxdigit (_input[i + 31]) &&
|
isxdigit ((*_input)[i + 31]) &&
|
||||||
isxdigit (_input[i + 32]) &&
|
isxdigit ((*_input)[i + 32]) &&
|
||||||
isxdigit (_input[i + 33]) &&
|
isxdigit ((*_input)[i + 33]) &&
|
||||||
isxdigit (_input[i + 34]) &&
|
isxdigit ((*_input)[i + 34]) &&
|
||||||
isxdigit (_input[i + 35]))
|
isxdigit ((*_input)[i + 35]))
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor, 36);
|
result = _input->substr (_cursor, 36);
|
||||||
_cursor = i + 36;
|
_cursor = i + 36;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -610,10 +610,10 @@ bool Nibbler::getPartialUUID (std::string& result)
|
||||||
std::string::size_type i;
|
std::string::size_type i;
|
||||||
for (i = 0; i < 36 && i < (_length - _cursor); i++)
|
for (i = 0; i < 36 && i < (_length - _cursor); i++)
|
||||||
{
|
{
|
||||||
if (_uuid_pattern[i] == 'x' && !isxdigit (_input[_cursor + i]))
|
if (_uuid_pattern[i] == 'x' && !isxdigit ((*_input)[_cursor + i]))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
else if (_uuid_pattern[i] == '-' && _input[_cursor + i] != '-')
|
else if (_uuid_pattern[i] == '-' && (*_input)[_cursor + i] != '-')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,10 +622,10 @@ bool Nibbler::getPartialUUID (std::string& result)
|
||||||
{
|
{
|
||||||
// Fail if there is another hex digit.
|
// Fail if there is another hex digit.
|
||||||
if (_cursor + i < _length &&
|
if (_cursor + i < _length &&
|
||||||
isxdigit (_input[_cursor + i]))
|
isxdigit ((*_input)[_cursor + i]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
result = _input.substr (_cursor, i);
|
result = _input->substr (_cursor, i);
|
||||||
_cursor += i;
|
_cursor += i;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -643,44 +643,44 @@ bool Nibbler::getDateISO (time_t& t)
|
||||||
if (i < _length &&
|
if (i < _length &&
|
||||||
_length - i >= 16)
|
_length - i >= 16)
|
||||||
{
|
{
|
||||||
if (Lexer::isDigit (_input[i + 0]) &&
|
if (Lexer::isDigit ((*_input)[i + 0]) &&
|
||||||
Lexer::isDigit (_input[i + 1]) &&
|
Lexer::isDigit ((*_input)[i + 1]) &&
|
||||||
Lexer::isDigit (_input[i + 2]) &&
|
Lexer::isDigit ((*_input)[i + 2]) &&
|
||||||
Lexer::isDigit (_input[i + 3]) &&
|
Lexer::isDigit ((*_input)[i + 3]) &&
|
||||||
Lexer::isDigit (_input[i + 4]) &&
|
Lexer::isDigit ((*_input)[i + 4]) &&
|
||||||
Lexer::isDigit (_input[i + 5]) &&
|
Lexer::isDigit ((*_input)[i + 5]) &&
|
||||||
Lexer::isDigit (_input[i + 6]) &&
|
Lexer::isDigit ((*_input)[i + 6]) &&
|
||||||
Lexer::isDigit (_input[i + 7]) &&
|
Lexer::isDigit ((*_input)[i + 7]) &&
|
||||||
_input[i + 8] == 'T' &&
|
(*_input)[i + 8] == 'T' &&
|
||||||
Lexer::isDigit (_input[i + 9]) &&
|
Lexer::isDigit ((*_input)[i + 9]) &&
|
||||||
Lexer::isDigit (_input[i + 10]) &&
|
Lexer::isDigit ((*_input)[i + 10]) &&
|
||||||
Lexer::isDigit (_input[i + 11]) &&
|
Lexer::isDigit ((*_input)[i + 11]) &&
|
||||||
Lexer::isDigit (_input[i + 12]) &&
|
Lexer::isDigit ((*_input)[i + 12]) &&
|
||||||
Lexer::isDigit (_input[i + 13]) &&
|
Lexer::isDigit ((*_input)[i + 13]) &&
|
||||||
Lexer::isDigit (_input[i + 14]) &&
|
Lexer::isDigit ((*_input)[i + 14]) &&
|
||||||
_input[i + 15] == 'Z')
|
(*_input)[i + 15] == 'Z')
|
||||||
{
|
{
|
||||||
_cursor += 16;
|
_cursor += 16;
|
||||||
|
|
||||||
int year = (_input[i + 0] - '0') * 1000
|
int year = ((*_input)[i + 0] - '0') * 1000
|
||||||
+ (_input[i + 1] - '0') * 100
|
+ ((*_input)[i + 1] - '0') * 100
|
||||||
+ (_input[i + 2] - '0') * 10
|
+ ((*_input)[i + 2] - '0') * 10
|
||||||
+ (_input[i + 3] - '0');
|
+ ((*_input)[i + 3] - '0');
|
||||||
|
|
||||||
int month = (_input[i + 4] - '0') * 10
|
int month = ((*_input)[i + 4] - '0') * 10
|
||||||
+ (_input[i + 5] - '0');
|
+ ((*_input)[i + 5] - '0');
|
||||||
|
|
||||||
int day = (_input[i + 6] - '0') * 10
|
int day = ((*_input)[i + 6] - '0') * 10
|
||||||
+ (_input[i + 7] - '0');
|
+ ((*_input)[i + 7] - '0');
|
||||||
|
|
||||||
int hour = (_input[i + 9] - '0') * 10
|
int hour = ((*_input)[i + 9] - '0') * 10
|
||||||
+ (_input[i + 10] - '0');
|
+ ((*_input)[i + 10] - '0');
|
||||||
|
|
||||||
int minute = (_input[i + 11] - '0') * 10
|
int minute = ((*_input)[i + 11] - '0') * 10
|
||||||
+ (_input[i + 12] - '0');
|
+ ((*_input)[i + 12] - '0');
|
||||||
|
|
||||||
int second = (_input[i + 13] - '0') * 10
|
int second = ((*_input)[i + 13] - '0') * 10
|
||||||
+ (_input[i + 14] - '0');
|
+ ((*_input)[i + 14] - '0');
|
||||||
|
|
||||||
// Convert to epoch.
|
// Convert to epoch.
|
||||||
struct tm tms = {0};
|
struct tm tms = {0};
|
||||||
|
@ -723,15 +723,15 @@ bool Nibbler::parseDigits(std::string::size_type& i,
|
||||||
// Check that 'f' of them are digits
|
// Check that 'f' of them are digits
|
||||||
unsigned int g;
|
unsigned int g;
|
||||||
for (g = 0; g < f; g++)
|
for (g = 0; g < f; g++)
|
||||||
if (! Lexer::isDigit (_input[i + g]))
|
if (! Lexer::isDigit ((*_input)[i + g]))
|
||||||
break;
|
break;
|
||||||
// Parse the integer when it is the case
|
// Parse the integer when it is the case
|
||||||
if (g == f)
|
if (g == f)
|
||||||
{
|
{
|
||||||
if (f == 1)
|
if (f == 1)
|
||||||
result = _input[i] - '0';
|
result = (*_input)[i] - '0';
|
||||||
else
|
else
|
||||||
result = atoi (_input.substr (i, f).c_str ());
|
result = atoi (_input->substr (i, f).c_str ());
|
||||||
// Update the global cursor before returning
|
// Update the global cursor before returning
|
||||||
i += f;
|
i += f;
|
||||||
return true;
|
return true;
|
||||||
|
@ -814,11 +814,11 @@ bool Nibbler::getDate (const std::string& format, time_t& t)
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'A':
|
case 'A':
|
||||||
if (i + 3 <= _length &&
|
if (i + 3 <= _length &&
|
||||||
! Lexer::isDigit (_input[i + 0]) &&
|
! Lexer::isDigit ((*_input)[i + 0]) &&
|
||||||
! Lexer::isDigit (_input[i + 1]) &&
|
! Lexer::isDigit ((*_input)[i + 1]) &&
|
||||||
! Lexer::isDigit (_input[i + 2]))
|
! Lexer::isDigit ((*_input)[i + 2]))
|
||||||
{
|
{
|
||||||
wday = Date::dayOfWeek (_input.substr (i, 3).c_str ());
|
wday = Date::dayOfWeek (_input->substr (i, 3).c_str ());
|
||||||
i += (format[f] == 'a') ? 3 : Date::dayName (wday).size ();
|
i += (format[f] == 'a') ? 3 : Date::dayName (wday).size ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -828,13 +828,13 @@ bool Nibbler::getDate (const std::string& format, time_t& t)
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'B':
|
case 'B':
|
||||||
if (i + 3 <= _length &&
|
if (i + 3 <= _length &&
|
||||||
! Lexer::isDigit (_input[i + 0]) &&
|
! Lexer::isDigit ((*_input)[i + 0]) &&
|
||||||
! Lexer::isDigit (_input[i + 1]) &&
|
! Lexer::isDigit ((*_input)[i + 1]) &&
|
||||||
! Lexer::isDigit (_input[i + 2]))
|
! Lexer::isDigit ((*_input)[i + 2]))
|
||||||
{
|
{
|
||||||
if (month != -1)
|
if (month != -1)
|
||||||
return false;
|
return false;
|
||||||
month = Date::monthOfYear (_input.substr (i, 3).c_str());
|
month = Date::monthOfYear (_input->substr (i, 3).c_str());
|
||||||
i += (format[f] == 'b') ? 3 : Date::monthName (month).size ();
|
i += (format[f] == 'b') ? 3 : Date::monthName (month).size ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -843,7 +843,7 @@ bool Nibbler::getDate (const std::string& format, time_t& t)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (i + 1 <= _length &&
|
if (i + 1 <= _length &&
|
||||||
_input[i] == format[f])
|
(*_input)[i] == format[f])
|
||||||
++i;
|
++i;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
@ -935,14 +935,14 @@ bool Nibbler::getName (std::string& result)
|
||||||
|
|
||||||
if (i < _length)
|
if (i < _length)
|
||||||
{
|
{
|
||||||
if (! Lexer::isDigit (_input[i]) &&
|
if (! Lexer::isDigit ((*_input)[i]) &&
|
||||||
! ispunct (_input[i]) &&
|
! ispunct ((*_input)[i]) &&
|
||||||
! Lexer::isWhitespace (_input[i]))
|
! Lexer::isWhitespace ((*_input)[i]))
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
while (i < _length &&
|
while (i < _length &&
|
||||||
(_input[i] == '_' || ! ispunct (_input[i])) &&
|
((*_input)[i] == '_' || ! ispunct ((*_input)[i])) &&
|
||||||
! Lexer::isWhitespace (_input[i]))
|
! Lexer::isWhitespace ((*_input)[i]))
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -950,7 +950,7 @@ bool Nibbler::getName (std::string& result)
|
||||||
|
|
||||||
if (i > _cursor)
|
if (i > _cursor)
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor, i - _cursor);
|
result = _input->substr (_cursor, i - _cursor);
|
||||||
_cursor = i;
|
_cursor = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -967,16 +967,16 @@ bool Nibbler::getWord (std::string& result)
|
||||||
|
|
||||||
if (i < _length)
|
if (i < _length)
|
||||||
{
|
{
|
||||||
while (!Lexer::isDigit (_input[i]) &&
|
while (!Lexer::isDigit ((*_input)[i]) &&
|
||||||
!Lexer::isPunctuation (_input[i]) &&
|
!Lexer::isPunctuation ((*_input)[i]) &&
|
||||||
!Lexer::isWhitespace (_input[i]))
|
!Lexer::isWhitespace ((*_input)[i]))
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > _cursor)
|
if (i > _cursor)
|
||||||
{
|
{
|
||||||
result = _input.substr (_cursor, i - _cursor);
|
result = _input->substr (_cursor, i - _cursor);
|
||||||
_cursor = i;
|
_cursor = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1002,7 +1002,7 @@ bool Nibbler::skipN (const int quantity /* = 1 */)
|
||||||
bool Nibbler::skip (char c)
|
bool Nibbler::skip (char c)
|
||||||
{
|
{
|
||||||
if (_cursor < _length &&
|
if (_cursor < _length &&
|
||||||
_input[_cursor] == c)
|
(*_input)[_cursor] == c)
|
||||||
{
|
{
|
||||||
++_cursor;
|
++_cursor;
|
||||||
return true;
|
return true;
|
||||||
|
@ -1016,7 +1016,7 @@ bool Nibbler::skipAll (char c)
|
||||||
{
|
{
|
||||||
if (_cursor < _length)
|
if (_cursor < _length)
|
||||||
{
|
{
|
||||||
auto i = _input.find_first_not_of (c, _cursor);
|
auto i = _input->find_first_not_of (c, _cursor);
|
||||||
if (i == _cursor)
|
if (i == _cursor)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1053,7 +1053,7 @@ bool Nibbler::skipRx (const std::string& regex)
|
||||||
|
|
||||||
RX r (modified_regex, true);
|
RX r (modified_regex, true);
|
||||||
std::vector <std::string> results;
|
std::vector <std::string> results;
|
||||||
if (r.match (results, _input.substr (_cursor)))
|
if (r.match (results, _input->substr (_cursor)))
|
||||||
{
|
{
|
||||||
_cursor += results[0].length ();
|
_cursor += results[0].length ();
|
||||||
return true;
|
return true;
|
||||||
|
@ -1081,7 +1081,7 @@ bool Nibbler::skipAllOneOf (const std::string& chars)
|
||||||
{
|
{
|
||||||
if (_cursor < _length)
|
if (_cursor < _length)
|
||||||
{
|
{
|
||||||
auto i = _input.find_first_not_of (chars, _cursor);
|
auto i = _input->find_first_not_of (chars, _cursor);
|
||||||
if (i == _cursor)
|
if (i == _cursor)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1101,7 +1101,7 @@ bool Nibbler::skipAllOneOf (const std::string& chars)
|
||||||
char Nibbler::next ()
|
char Nibbler::next ()
|
||||||
{
|
{
|
||||||
if (_cursor < _length)
|
if (_cursor < _length)
|
||||||
return _input[_cursor];
|
return (*_input)[_cursor];
|
||||||
|
|
||||||
return '\0';
|
return '\0';
|
||||||
}
|
}
|
||||||
|
@ -1119,7 +1119,7 @@ std::string Nibbler::next (const int quantity)
|
||||||
if ( _cursor < _length &&
|
if ( _cursor < _length &&
|
||||||
(unsigned) quantity <= _length &&
|
(unsigned) quantity <= _length &&
|
||||||
_cursor <= _length - quantity)
|
_cursor <= _length - quantity)
|
||||||
return _input.substr (_cursor, quantity);
|
return _input->substr (_cursor, quantity);
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -1139,7 +1139,7 @@ std::string::size_type Nibbler::restore ()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
const std::string& Nibbler::str () const
|
const std::string& Nibbler::str () const
|
||||||
{
|
{
|
||||||
return _input;
|
return *_input;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1155,7 +1155,7 @@ bool Nibbler::depleted ()
|
||||||
std::string Nibbler::dump ()
|
std::string Nibbler::dump ()
|
||||||
{
|
{
|
||||||
return std::string ("Nibbler ‹")
|
return std::string ("Nibbler ‹")
|
||||||
+ _input.substr (_cursor)
|
+ _input->substr (_cursor)
|
||||||
+ "›";
|
+ "›";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class Nibbler
|
class Nibbler
|
||||||
{
|
{
|
||||||
|
@ -110,7 +111,7 @@ public:
|
||||||
std::string dump ();
|
std::string dump ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _input;
|
std::shared_ptr<std::string> _input;
|
||||||
std::string::size_type _length;
|
std::string::size_type _length;
|
||||||
std::string::size_type _cursor;
|
std::string::size_type _cursor;
|
||||||
std::string::size_type _saved;
|
std::string::size_type _saved;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue