]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
Trying a strategy with the stream parser.
authorJesse F. Williamson <jfw@ibm.com>
Fri, 13 Feb 2026 07:20:07 +0000 (23:20 -0800)
committerJesse F. Williamson <jfw@ibm.com>
Fri, 13 Feb 2026 20:26:02 +0000 (12:26 -0800)
Signed-off-by: Jesse F. Williamson <jfw@ibm.com>
src/common/ceph_json.cc
src/common/ceph_json.h

index 83fa8bdec34b79de59acb6dbe44f4620b140535e..40526e957c5c4e9473b543976cc5d41d59cb988a 100644 (file)
@@ -311,7 +311,9 @@ int JSONFormattable::set(const string& name, const string& val)
 
   JSONParser jp;
 
+fmt::println("JFW: about to parse \"{}\" => \"{}\"", name, val);
   bool is_valid_json = jp.parse(val);
+fmt::println("JFW: kk");
 
   for (const auto& i : tok) {
     vector<field_entity> v;
@@ -341,12 +343,14 @@ int JSONFormattable::set(const string& name, const string& val)
         if (vi.append) {
           index = f->arr.size();
         } else if (index < 0) {
+fmt::println("JFW: index < 0");
           index = f->arr.size() + index;
           if (index < 0) {
             return -EINVAL; /* out of bounds */
           }
         }
         if ((size_t)index >= f->arr.size()) {
+fmt::println("JFW: index resize");
           f->arr.resize(index + 1);
         }
         f = &f->arr[index];
index 2452ef6b208b61295fa82765c9b672b22ab7bcc8..b2dd233d5664663f0ca9b5788372aa9e98b77ec8 100644 (file)
@@ -189,15 +189,49 @@ protected:
   void handle_value(boost::json::value v);
 
 protected:
-  // Although the error_code contains useful information, the API constraints require
-  // that we throw it out:
-  static bool parse_json(std::string_view input, boost::json::value& data_out)
-  {
+  /* While basic parsing is straightforward:
        data_out = boost::json::parse(input, boost::json::storage_ptr(), 
                                     { .allow_invalid_utf8 = true });
+   ...we need to fit in with the previous parser, which was frankly more tolerant of
+   invalid data than boost.json is out of the box. Therefore, we employ the stream
+   parser, which is slightly more complicated but more flexible; we also try to reinterpret
+   certain kinds of failures as strings, which IMO is fairly naughty... */
+   static bool parse_json(std::string_view input, boost::json::value& data_out)
+   {
+    boost::json::stream_parser p;
+    boost::system::error_code ec;
+
+    std::size_t bytes_written = p.write_some(input, ec);
+
+    if (!ec) {
+      p.finish(ec);
+      data_out = p.release();
+
+      return true;
+    }
 
-       return true;
-  }
+fmt::println("JFW: JSON stream parsing failed: {}", ec.message());
+
+   if (boost::json::error::extra_data == ec || bytes_written < input.size()) {
+      // As the failure case is expected to be rare, and originates from
+      // malformed input, we'll try to convert to a string (as some extant
+      // unit tests appear to expect!) and see what's fixable and what's not:
+
+      // ...try again:
+      boost::system::result<std::string> r = boost::json::try_value_to<std::string>(data_out);
+
+      // ...a big fib, but tolerate the questionable input:
+      if(r) {
+       data_out = *r;
+       return true; 
+      }
+    }
+
+    throw std::runtime_error(fmt::format(
+           "JSON error at (position {}): {}\n{}\n---", bytes_written, ec.message(), input));
+
+    return false;
+   }
 
 public:
   JSONObj() = default;
@@ -306,7 +340,9 @@ public:
   }
 
   bool parse(ceph::buffer::list& bl) {
-       return parse(bl.c_str(), bl.length());
+       // return parse(bl.c_str(), bl.length());
+       auto ptr = bl.c_str(); // possibly cause compaction, be sure to sequence FIRST
+       return parse(ptr, bl.length());
   }
 
   [[deprecated("this may not be reliable")]] bool parse_file(const std::filesystem::path file_name);