Reranko05 commented on code in PR #51038:
URL: https://github.com/apache/arrow/pull/51038#discussion_r4085296923


##########
cpp/src/arrow/json/parser.cc:
##########
@@ -762,102 +744,204 @@ class HandlerBase : public BlockParser,
   }
 
  protected:
-  template <typename Handler, typename Stream>
-  Status DoParse(Handler& handler, Stream&& json, size_t json_size) {
-    constexpr auto parse_flags = rj::kParseIterativeFlag | 
rj::kParseNanAndInfFlag |
-                                 rj::kParseStopWhenDoneFlag |
-                                 rj::kParseNumbersAsStringsFlag;
-
-    rj::Reader reader;
-    // ensure that the loop can exit when the block too large.
-    for (; num_rows_ < std::numeric_limits<int32_t>::max(); ++num_rows_) {
-      auto ok = reader.Parse<parse_flags>(json, handler);
-      switch (ok.Code()) {
-        case rj::kParseErrorNone:
-          // parse the next object
-          continue;
-        case rj::kParseErrorDocumentEmpty:
-          if (json.Tell() < json_size) {
-            return ParseError(rj::GetParseError_En(ok.Code()));
-          }
-          // parsed all objects, finish
-          return Status::OK();
-        case rj::kParseErrorTermination:
-          // handler emitted an error
-          return handler.Error();
-        default:
-          // rj emitted an error
-          return ParseError(rj::GetParseError_En(ok.Code()), " in row ", 
num_rows_);
+  Status Parse(const std::shared_ptr<Buffer>& json) override {
+    RETURN_NOT_OK(ReserveScalarStorage(json->size()));
+
+    const std::string_view input(reinterpret_cast<const char*>(json->data()),
+                                 json->size());
+
+    const int64_t input_size = input.size();
+    if (internal::ConsumeJsonWhitespace(input, /*trailing=*/false) == 
input_size) {
+      return Status::OK();
+    }
+
+    auto parse = [&](const auto& input) -> Status {
+      ARROW_ASSIGN_OR_RAISE(auto stream, 
arrow::internal::ResolveSimdjsonResult(
+                                             parser_.iterate_many(input),
+                                             "Failed to create JSON document 
stream"));
+
+      for (auto document_result : stream) {
+        ARROW_ASSIGN_OR_RAISE(
+            auto document,
+            arrow::internal::ResolveSimdjsonResult(
+                document_result, "Failed to iterate JSON document stream"));
+
+        if (num_rows_ == std::numeric_limits<int32_t>::max()) {
+          return Status::Invalid("Row count overflowed int32_t");
+        }
+
+        ARROW_ASSIGN_OR_RAISE(
+            auto value,
+            arrow::internal::ResolveSimdjsonResult(
+                document.get_value(), "JSON parse error: Failed to get JSON 
value"));
+
+        RETURN_NOT_OK(ParseValue(value));
+
+        ++num_rows_;
+      }
+
+      if (stream.truncated_bytes() != 0) {
+        return ParseError("The document is empty");
       }
+
+      return Status::OK();
+    };
+
+    if (json->capacity() - json->size() >=
+        static_cast<int64_t>(simdjson::SIMDJSON_PADDING)) {
+      const auto padded_json = simdjson::padded_string_view(
+          reinterpret_cast<const char*>(json->data()), json->size(), 
json->capacity());
+      return parse(padded_json);
     }
-    return Status::Invalid("Row count overflowed int32_t");
+
+    // padded_string makes a copy of the input buffer.

Review Comment:
   Addressed.



##########
cpp/src/arrow/json/parser.cc:
##########
@@ -876,25 +960,60 @@ class HandlerBase : public BlockParser,
     return Status::OK();
   }
 
-  Status StartArrayImpl() {
-    constexpr auto kind = Kind::kArray;
-    if (ARROW_PREDICT_FALSE(builder_.kind != kind)) {
+  Status ParseObjectField(std::string_view key, sj::value value) {
+    bool duplicate_keys = false;
+
+    if (SetFieldBuilder(key, &duplicate_keys)) {
+      return ParseValue(value);
+    }
+
+    if (duplicate_keys) {
+      return status_;
+    }
+
+    return HandleUnexpectedField(key, value);
+  }
+
+  template <Kind::type kind>
+  Status AppendScalar(BuilderPtr builder, std::string_view scalar) {
+    if (ARROW_PREDICT_FALSE(builder.kind != kind)) {
       return IllegallyChangedTo(kind);
     }
-    StartNested();
-    // append to the list builder in EndArrayImpl
-    builder_ = Cast<kind>(builder_)->value_builder();
+    auto index = static_cast<int32_t>(scalar_values_builder_.length());
+    auto value_length = static_cast<int32_t>(scalar.size());
+    RETURN_NOT_OK(Cast<kind>(builder)->Append(index, value_length));
+    RETURN_NOT_OK(scalar_values_builder_.Reserve(1));
+    scalar_values_builder_.UnsafeAppend(scalar);
     return Status::OK();
   }
 
-  Status EndArrayImpl(rj::SizeType size) {
-    EndNested();
-    // append to list_builder here
-    auto list_builder = Cast<Kind::kArray>(builder_);
-    return list_builder->Append(size);
+  /// \brief helper for parsing object fields.
+  ///
+  /// Sets the field builder with the given name, or returns false if
+  /// there is no such field or the field was already specified.
+  bool SetFieldBuilder(std::string_view key, bool* duplicate_keys) {
+    auto parent = Cast<Kind::kObject>(builder_stack_.back());
+    field_index_ = parent->GetFieldIndex(key);
+    if (ARROW_PREDICT_FALSE(field_index_ == -1)) {
+      return false;
+    }
+    if (field_index_ < absent_fields_stack_.TopSize()) {
+      *duplicate_keys = !absent_fields_stack_[field_index_];
+    } else {
+      // When field_index is beyond the range of absent_fields_stack_ we have 
a duplicated
+      // field that wasn't declared in schema or previous records.
+      *duplicate_keys = true;
+    }
+    if (*duplicate_keys) {
+      status_ = ParseError("Column(", Path(), ") was specified twice in row ", 
num_rows_);

Review Comment:
   Addressed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to