| 86 | |
| 87 | template <class Scanner> |
| 88 | Status JsonParser<Scanner>::Parse(int max_rows, int* num_rows) { |
| 89 | while (*num_rows < max_rows) { |
| 90 | constexpr auto parse_flags = |
| 91 | kParseNumbersAsStringsFlag | kParseStopWhenDoneFlag | kParseNanAndInfFlag; |
| 92 | // Reads characters from the stream, parses them and publishes events to this |
| 93 | // handler (JsonParser). |
| 94 | reader_.Parse<parse_flags>(stream_, *this); |
| 95 | |
| 96 | if (UNLIKELY(reader_.HasParseError())) { |
| 97 | if (reader_.GetParseErrorCode() == kParseErrorDocumentEmpty) { |
| 98 | // When the parser encounters the first non-empty character as '\0' during once |
| 99 | // parsing, it assumes the end of the stream and throws the error code |
| 100 | // "kParseErrorDocumentEmpty". If the stream has indeed reached its end, we can |
| 101 | // return normally. However, if a file corruption causes a '\0' to be inserted |
| 102 | // between JSON objects, the stream hasn't actually ended, and we should |
| 103 | // continue scanning. |
| 104 | if (UNLIKELY(!stream_.Eos())) { |
| 105 | DCHECK_EQ(stream_.Peek(), '\0'); |
| 106 | stream_.Take(); |
| 107 | continue; |
| 108 | } |
| 109 | DCHECK(IsTidy()); |
| 110 | return Status::OK(); |
| 111 | } |
| 112 | // Call the scanner to handling error. If the error is successfully handled, |
| 113 | // continue parsing. Since parsing have been interrupted and we may be stopped in |
| 114 | // the middle of a JSON object, we need to move to the starting position of the |
| 115 | // next object and reset the parser status before starting the next parse. |
| 116 | // But there is a special case where the error code reported by the parser is |
| 117 | // kParseErrorObjectMissCommaOrCurlyBracket, indicating that the current JSON |
| 118 | // object is missing a closing curly bracket. In this case, we should already be |
| 119 | // stopped at the end of this JSON object and there is no need to move to the |
| 120 | // starting position of the next object. If MoveToNextJson() is still called in |
| 121 | // this case, it is highly likely to cause us to miss a complete row. |
| 122 | RETURN_IF_ERROR(scanner_->HandleError(reader_.GetParseErrorCode(), |
| 123 | reader_.GetErrorOffset())); |
| 124 | if (row_initialized_) FinishRow(); |
| 125 | if (reader_.GetParseErrorCode() != kParseErrorObjectMissCommaOrCurlyBracket) { |
| 126 | MoveToNextJson(); |
| 127 | } |
| 128 | ResetParser(); |
| 129 | } |
| 130 | |
| 131 | ++(*num_rows); |
| 132 | if (UNLIKELY(scanner_->BreakParse())) break; |
| 133 | } |
| 134 | |
| 135 | return Status::OK(); |
| 136 | } |
| 137 | |
| 138 | template <class Scanner> |
| 139 | Status JsonParser<Scanner>::CountJsonObjects(int max_rows, int* num_rows) { |
no test coverage detected