parseUpdate method
Tries to update its fields based on information from the specified
bytes
, which should come from a JSON file. Creates and sends new points
to resultReporter when such fully defined points are detected.
Valid JSON input will have forms like:
- "key": -456
- "key": "123"
- 'key' : '78'
The implementation is very much aimed at specifically the way the Google location history export looks, rather than being a generic JSON parser. This makes it possible to optimize it a lot in terms of speed and memory usage, at the expense of legibility.
Implementation
void parseUpdate(List<int> bytes, int start, int end) {
pos = start;
posStartNextStreamChunk = null; // indicates we haven't parsed anything
var prevLoopStartPos = -1;
while (pos < end) {
// If we're just spinning our wheels, stop.
if (pos == prevLoopStartPos) {
break;
}
prevLoopStartPos = pos;
// Find first key we're interested in.
final index = _getKeyIndex(bytes, end);
if (index == _indexUninterestingKey) {
// Even if the key is not interesting, it is correctly parsed and
// doesn't need to be parsed again if it happens to be towards the
// end of [bytes] and the next chunk will be appended.
posStartNextStreamChunk = pos;
continue;
}
if (index == null) {
continue;
}
// Get the key's value
final valueString = _parseValueString(bytes, end);
if (valueString == null) {
break;
}
// Remember the position, because if we don't find a proper value in the
// next loop, that may be because the stream is split at an unfortunate
// place (e.g. between a key and its value, or in the middle of a key or
// something like that). The part after the current, known correct,
// key-value pair may need to be re-parsed including additional information
// from the next chunk of the stream providing our [bytes].
posStartNextStreamChunk = pos;
final value = int.tryParse(valueString);
if (value == null) {
// Cannot really happen given the parsing method, but just in case.
continue;
}
// If starting the definition of a new point and the current state looks
// like a fully defined point, report the current state.
if (_values[index] != null && !isUndefined) {
toGpsPointAndReset();
}
_setValue(index, value);
}
}