LCOV - code coverage report
Current view: top level - source/common/json - json_internal.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 166 559 29.7 %
Date: 2024-01-05 06:35:25 Functions: 42 80 52.5 %

          Line data    Source code
       1             : #include "source/common/json/json_internal.h"
       2             : 
       3             : #include <cstdint>
       4             : #include <fstream>
       5             : #include <limits>
       6             : #include <map>
       7             : #include <sstream>
       8             : #include <stack>
       9             : #include <string>
      10             : #include <vector>
      11             : 
      12             : #include "source/common/common/assert.h"
      13             : #include "source/common/common/fmt.h"
      14             : #include "source/common/common/hash.h"
      15             : #include "source/common/common/utility.h"
      16             : #include "source/common/protobuf/utility.h"
      17             : 
      18             : // Do not let nlohmann/json leak outside of this file.
      19             : #include "include/nlohmann/json.hpp"
      20             : 
      21             : #include "absl/strings/match.h"
      22             : 
      23             : namespace Envoy {
      24             : namespace Json {
      25             : namespace Nlohmann {
      26             : 
      27             : namespace {
      28             : 
      29             : /**
      30             :  * Internal representation of Object.
      31             :  */
      32             : class Field;
      33             : using FieldSharedPtr = std::shared_ptr<Field>;
      34             : 
      35             : class Field : public Object {
      36             : public:
      37       57591 :   void setLineNumberStart(uint64_t line_number) { line_number_start_ = line_number; }
      38       25219 :   void setLineNumberEnd(uint64_t line_number) { line_number_end_ = line_number; }
      39             : 
      40             :   // Container factories for handler.
      41       17890 :   static FieldSharedPtr createObject() { return FieldSharedPtr{new Field(Type::Object)}; }
      42        7329 :   static FieldSharedPtr createArray() { return FieldSharedPtr{new Field(Type::Array)}; }
      43           0 :   static FieldSharedPtr createNull() { return FieldSharedPtr{new Field(Type::Null)}; }
      44             : 
      45       51876 :   bool isArray() const override { return type_ == Type::Array; }
      46       82484 :   bool isObject() const override { return type_ == Type::Object; }
      47             : 
      48             :   // Value factory.
      49       32372 :   template <typename T> static FieldSharedPtr createValue(T value) {
      50       32372 :     return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
      51       32372 :   }
      52             : 
      53       17779 :   void append(FieldSharedPtr field_ptr) {
      54       17779 :     checkType(Type::Array);
      55       17779 :     value_.array_value_.push_back(field_ptr);
      56       17779 :   }
      57       39672 :   void insert(const std::string& key, FieldSharedPtr field_ptr) {
      58       39672 :     checkType(Type::Object);
      59       39672 :     value_.object_value_[key] = field_ptr;
      60       39672 :   }
      61             : 
      62             :   uint64_t hash() const override;
      63             : 
      64             :   absl::StatusOr<ValueType> getValue(const std::string& name) const override;
      65             :   bool getBoolean(const std::string& name) const override;
      66             :   bool getBoolean(const std::string& name, bool default_value) const override;
      67             :   double getDouble(const std::string& name) const override;
      68             :   double getDouble(const std::string& name, double default_value) const override;
      69             :   int64_t getInteger(const std::string& name) const override;
      70             :   int64_t getInteger(const std::string& name, int64_t default_value) const override;
      71             :   ObjectSharedPtr getObject(const std::string& name, bool allow_empty) const override;
      72             :   absl::StatusOr<ObjectSharedPtr> getObjectNoThrow(const std::string& name,
      73             :                                                    bool allow_empty) const override;
      74             :   std::vector<ObjectSharedPtr> getObjectArray(const std::string& name,
      75             :                                               bool allow_empty) const override;
      76             :   std::string getString(const std::string& name) const override;
      77             :   std::string getString(const std::string& name, const std::string& default_value) const override;
      78             :   std::vector<std::string> getStringArray(const std::string& name, bool allow_empty) const override;
      79             :   std::vector<ObjectSharedPtr> asObjectArray() const override;
      80         144 :   std::string asString() const override { return stringValue(); }
      81             :   std::string asJsonString() const override;
      82             : 
      83             :   bool empty() const override;
      84             :   bool hasObject(const std::string& name) const override;
      85             :   void iterate(const ObjectCallback& callback) const override;
      86             :   void validateSchema(const std::string&) const override;
      87             : 
      88             : private:
      89             :   enum class Type {
      90             :     Array,
      91             :     Boolean,
      92             :     Double,
      93             :     Integer,
      94             :     Null,
      95             :     Object,
      96             :     String,
      97             :   };
      98           0 :   static const char* typeAsString(Type t) {
      99           0 :     switch (t) {
     100           0 :     case Type::Array:
     101           0 :       return "Array";
     102           0 :     case Type::Boolean:
     103           0 :       return "Boolean";
     104           0 :     case Type::Double:
     105           0 :       return "Double";
     106           0 :     case Type::Integer:
     107           0 :       return "Integer";
     108           0 :     case Type::Null:
     109           0 :       return "Null";
     110           0 :     case Type::Object:
     111           0 :       return "Object";
     112           0 :     case Type::String:
     113           0 :       return "String";
     114           0 :     }
     115             : 
     116           0 :     return "";
     117           0 :   }
     118             : 
     119             :   struct Value {
     120             :     std::vector<FieldSharedPtr> array_value_;
     121             :     bool boolean_value_;
     122             :     double double_value_;
     123             :     int64_t integer_value_;
     124             :     std::map<std::string, FieldSharedPtr> object_value_;
     125             :     std::string string_value_;
     126             :   };
     127             : 
     128       25219 :   explicit Field(Type type) : type_(type) {}
     129       31470 :   explicit Field(const std::string& value) : type_(Type::String) { value_.string_value_ = value; }
     130         712 :   explicit Field(int64_t value) : type_(Type::Integer) { value_.integer_value_ = value; }
     131           0 :   explicit Field(double value) : type_(Type::Double) { value_.double_value_ = value; }
     132         190 :   explicit Field(bool value) : type_(Type::Boolean) { value_.boolean_value_ = value; }
     133             : 
     134       82962 :   bool isType(Type type) const { return type == type_; }
     135       82962 :   void checkType(Type type) const {
     136       82962 :     if (!isType(type)) {
     137           0 :       throwExceptionOrPanic(
     138           0 :           Exception,
     139           0 :           fmt::format(
     140           0 :               "JSON field from line {} accessed with type '{}' does not match actual type '{}'.",
     141           0 :               line_number_start_, typeAsString(type), typeAsString(type_)));
     142           0 :     }
     143       82962 :   }
     144             : 
     145             :   // Value return type functions.
     146         144 :   std::string stringValue() const {
     147         144 :     checkType(Type::String);
     148         144 :     return value_.string_value_;
     149         144 :   }
     150           0 :   std::vector<FieldSharedPtr> arrayValue() const {
     151           0 :     checkType(Type::Array);
     152           0 :     return value_.array_value_;
     153           0 :   }
     154           0 :   bool booleanValue() const {
     155           0 :     checkType(Type::Boolean);
     156           0 :     return value_.boolean_value_;
     157           0 :   }
     158           0 :   double doubleValue() const {
     159           0 :     checkType(Type::Double);
     160           0 :     return value_.double_value_;
     161           0 :   }
     162           0 :   int64_t integerValue() const {
     163           0 :     checkType(Type::Integer);
     164           0 :     return value_.integer_value_;
     165           0 :   }
     166             : 
     167             :   nlohmann::json asJsonDocument() const;
     168             :   static void buildJsonDocument(const Field& field, nlohmann::json& value);
     169             : 
     170             :   uint64_t line_number_start_ = 0;
     171             :   uint64_t line_number_end_ = 0;
     172             :   const Type type_;
     173             :   Value value_;
     174             : };
     175             : 
     176             : /**
     177             :  * Consume events from SAX callbacks to build JSON Field.
     178             :  */
     179             : class ObjectHandler : public nlohmann::json_sax<nlohmann::json> {
     180             : public:
     181         140 :   ObjectHandler() = default;
     182             : 
     183             :   bool start_object(std::size_t) override;
     184             :   bool end_object() override;
     185             :   bool key(std::string& val) override;
     186             :   bool start_array(std::size_t) override;
     187             :   bool end_array() override;
     188         190 :   bool boolean(bool value) override { return handleValueEvent(Field::createValue(value)); }
     189           0 :   bool number_integer(int64_t value) override {
     190           0 :     return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
     191           0 :   }
     192         712 :   bool number_unsigned(uint64_t value) override {
     193         712 :     if (value > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
     194           0 :       throwExceptionOrPanic(
     195           0 :           Exception, fmt::format("JSON value from line {} is larger than int64_t (not supported)",
     196           0 :                                  line_number_));
     197           0 :     }
     198         712 :     return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
     199         712 :   }
     200           0 :   bool number_float(double value, const std::string&) override {
     201           0 :     return handleValueEvent(Field::createValue(value));
     202           0 :   }
     203           0 :   bool null() override { return handleValueEvent(Field::createNull()); }
     204       31470 :   bool string(std::string& value) override { return handleValueEvent(Field::createValue(value)); }
     205           0 :   bool binary(binary_t&) override { return false; }
     206             :   bool parse_error(std::size_t at, const std::string& token,
     207           0 :                    const nlohmann::detail::exception& ex) override {
     208             :     // Parse errors are formatted like "[json.exception.parse_error.101] parse error: explanatory
     209             :     // string." or "[json.exception.parse_error.101] parser error at (position): explanatory
     210             :     // string.". All errors start with "[json.exception.<error_type>.<error_num]" see:
     211             :     // https://json.nlohmann.me/home/exceptions/#parse-errors
     212             :     // The `parse_error` method will be called also for non-parse errors.
     213           0 :     absl::string_view error = ex.what();
     214             : 
     215             :     // Colon will always exist in the parse error. For non-parse error use the
     216             :     // ending ']' as a separator.
     217           0 :     auto end = error.find(": ");
     218           0 :     auto prefix_end = error.find(']');
     219           0 :     if (end != std::string::npos) {
     220             :       // Extract portion after ": " to get error string.
     221           0 :       error_ = std::string(error.substr(end + 2));
     222             :       // Extract position information if present.
     223           0 :       auto start = error.find("at ");
     224           0 :       if (start != std::string::npos && (start + 3) < end) {
     225           0 :         start += 3;
     226           0 :         error_position_ = absl::StrCat(error.substr(start, end - start), ", token ", token);
     227           0 :       }
     228           0 :     } else if ((prefix_end != std::string::npos) && (absl::StartsWith(error, ErrorPrefix))) {
     229             :       // Non-parse error, fetching position from the arguments as it is not
     230             :       // present in the error string.
     231           0 :       error_position_ = absl::StrCat("position: ", at);
     232           0 :       error_ = std::string(error.substr(prefix_end + 1));
     233           0 :     } else {
     234           0 :       IS_ENVOY_BUG("Error string not present. Check nlohmann/json "
     235           0 :                    "documentation in case error string changed.");
     236           0 :     }
     237           0 :     return false;
     238           0 :   }
     239             : 
     240         140 :   bool hasParseError() { return !error_.empty(); }
     241           0 :   std::string getParseError() { return error_; }
     242           0 :   std::string getErrorPosition() { return error_position_; }
     243             : 
     244         140 :   ObjectSharedPtr getRoot() { return root_; }
     245             : 
     246             :   int line_number_{1};
     247             : 
     248             : private:
     249             :   bool handleValueEvent(FieldSharedPtr ptr);
     250             : 
     251             :   enum class State {
     252             :     ExpectRoot,
     253             :     ExpectKeyOrEndObject,
     254             :     ExpectValueOrStartObjectArray,
     255             :     ExpectArrayValueOrEndArray,
     256             :     ExpectFinished,
     257             :   };
     258             :   State state_{State::ExpectRoot};
     259             : 
     260             :   std::stack<FieldSharedPtr> stack_;
     261             :   std::string key_;
     262             : 
     263             :   FieldSharedPtr root_;
     264             : 
     265             :   std::string error_;
     266             :   std::string error_position_;
     267             : 
     268             :   static constexpr absl::string_view ErrorPrefix = "[json.exception.";
     269             : };
     270             : 
     271             : struct JsonContainer {
     272         420 :   JsonContainer(const char* ch, ObjectHandler* handler) : data(ch), handler_(handler) {}
     273             :   const char* data;
     274             :   ObjectHandler* handler_;
     275             : };
     276             : 
     277             : struct JsonIterator {
     278             :   using difference_type = std::ptrdiff_t;            // NOLINT(readability-identifier-naming)
     279             :   using value_type = char;                           // NOLINT(readability-identifier-naming)
     280             :   using pointer = const char*;                       // NOLINT(readability-identifier-naming)
     281             :   using reference = const char&;                     // NOLINT(readability-identifier-naming)
     282             :   using iterator_category = std::input_iterator_tag; // NOLINT(readability-identifier-naming)
     283             : 
     284     2278912 :   JsonIterator& operator++() {
     285     2278912 :     ++ptr.data;
     286     2278912 :     return *this;
     287     2278912 :   }
     288             : 
     289     2279052 :   bool operator!=(const JsonIterator& rhs) const { return rhs.ptr.data != ptr.data; }
     290             : 
     291     2278912 :   reference operator*() {
     292     2278912 :     const char& ch = *(ptr.data);
     293     2278912 :     if (ch == '\n') {
     294       82270 :       ptr.handler_->line_number_++;
     295       82270 :     }
     296     2278912 :     return ch;
     297     2278912 :   }
     298             : 
     299             :   JsonContainer ptr;
     300             : };
     301             : 
     302         140 : JsonIterator begin(const JsonContainer& c) {
     303         140 :   return JsonIterator{JsonContainer(c.data, c.handler_)};
     304         140 : }
     305             : 
     306         140 : JsonIterator end(const JsonContainer& c) {
     307         140 :   return JsonIterator{JsonContainer(c.data + strlen(c.data), c.handler_)};
     308         140 : }
     309             : 
     310           0 : void Field::buildJsonDocument(const Field& field, nlohmann::json& value) {
     311           0 :   switch (field.type_) {
     312           0 :   case Type::Array: {
     313           0 :     for (const auto& element : field.value_.array_value_) {
     314           0 :       switch (element->type_) {
     315           0 :       case Type::Array:
     316           0 :       case Type::Object: {
     317           0 :         nlohmann::json nested_value;
     318           0 :         buildJsonDocument(*element, nested_value);
     319           0 :         value.push_back(nested_value);
     320           0 :         break;
     321           0 :       }
     322           0 :       case Type::Boolean:
     323           0 :         value.push_back(element->value_.boolean_value_);
     324           0 :         break;
     325           0 :       case Type::Double:
     326           0 :         value.push_back(element->value_.double_value_);
     327           0 :         break;
     328           0 :       case Type::Integer:
     329           0 :         value.push_back(element->value_.integer_value_);
     330           0 :         break;
     331           0 :       case Type::Null:
     332           0 :         value.push_back(nlohmann::json::value_t::null);
     333           0 :         break;
     334           0 :       case Type::String:
     335           0 :         value.push_back(element->value_.string_value_);
     336           0 :       }
     337           0 :     }
     338           0 :     break;
     339           0 :   }
     340           0 :   case Type::Object: {
     341           0 :     for (const auto& item : field.value_.object_value_) {
     342           0 :       auto name = std::string(item.first);
     343             : 
     344           0 :       switch (item.second->type_) {
     345           0 :       case Type::Array:
     346           0 :       case Type::Object: {
     347           0 :         nlohmann::json nested_value;
     348           0 :         buildJsonDocument(*item.second, nested_value);
     349           0 :         value.emplace(name, nested_value);
     350           0 :         break;
     351           0 :       }
     352           0 :       case Type::Boolean:
     353           0 :         value.emplace(name, item.second->value_.boolean_value_);
     354           0 :         break;
     355           0 :       case Type::Double:
     356           0 :         value.emplace(name, item.second->value_.double_value_);
     357           0 :         break;
     358           0 :       case Type::Integer:
     359           0 :         value.emplace(name, item.second->value_.integer_value_);
     360           0 :         break;
     361           0 :       case Type::Null:
     362           0 :         value.emplace(name, nlohmann::json::value_t::null);
     363           0 :         break;
     364           0 :       case Type::String:
     365           0 :         value.emplace(name, item.second->value_.string_value_);
     366           0 :         break;
     367           0 :       }
     368           0 :     }
     369           0 :     break;
     370           0 :   }
     371           0 :   case Type::Null: {
     372           0 :     break;
     373           0 :   }
     374           0 :   case Type::Boolean:
     375           0 :     FALLTHRU;
     376           0 :   case Type::Double:
     377           0 :     FALLTHRU;
     378           0 :   case Type::Integer:
     379           0 :     FALLTHRU;
     380           0 :   case Type::String:
     381           0 :     PANIC("not implemented");
     382           0 :   }
     383           0 : }
     384             : 
     385           0 : nlohmann::json Field::asJsonDocument() const {
     386           0 :   nlohmann::json j;
     387           0 :   buildJsonDocument(*this, j);
     388           0 :   return j;
     389           0 : }
     390             : 
     391           0 : uint64_t Field::hash() const { return HashUtil::xxHash64(asJsonString()); }
     392             : 
     393           0 : absl::StatusOr<ValueType> Field::getValue(const std::string& name) const {
     394           0 :   auto value_itr = value_.object_value_.find(name);
     395           0 :   if (value_itr == value_.object_value_.end()) {
     396           0 :     return absl::NotFoundError(fmt::format("key '{}' missing from lines {}-{}", name,
     397           0 :                                            line_number_start_, line_number_end_));
     398           0 :   }
     399           0 :   switch (value_itr->second->type_) {
     400           0 :   case Type::Boolean:
     401           0 :     return value_itr->second->booleanValue();
     402           0 :   case Type::Double:
     403           0 :     return value_itr->second->doubleValue();
     404           0 :   case Type::Integer:
     405           0 :     return value_itr->second->integerValue();
     406           0 :   case Type::String:
     407           0 :     return value_itr->second->stringValue();
     408           0 :   default:
     409           0 :     return absl::InternalError(fmt::format("key '{}' not a value type from lines {}-{}", name,
     410           0 :                                            line_number_start_, line_number_end_));
     411           0 :   }
     412           0 : }
     413             : 
     414           0 : bool Field::getBoolean(const std::string& name) const {
     415           0 :   checkType(Type::Object);
     416           0 :   auto value_itr = value_.object_value_.find(name);
     417           0 :   if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Boolean)) {
     418           0 :     throwExceptionOrPanic(Exception,
     419           0 :                           fmt::format("key '{}' missing or not a boolean from lines {}-{}", name,
     420           0 :                                       line_number_start_, line_number_end_));
     421           0 :   }
     422           0 :   return value_itr->second->booleanValue();
     423           0 : }
     424             : 
     425           0 : bool Field::getBoolean(const std::string& name, bool default_value) const {
     426           0 :   checkType(Type::Object);
     427           0 :   auto value_itr = value_.object_value_.find(name);
     428           0 :   if (value_itr != value_.object_value_.end()) {
     429           0 :     return getBoolean(name);
     430           0 :   }
     431           0 :   return default_value;
     432           0 : }
     433             : 
     434           0 : double Field::getDouble(const std::string& name) const {
     435           0 :   checkType(Type::Object);
     436           0 :   auto value_itr = value_.object_value_.find(name);
     437           0 :   if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Double)) {
     438           0 :     throwExceptionOrPanic(Exception,
     439           0 :                           fmt::format("key '{}' missing or not a double from lines {}-{}", name,
     440           0 :                                       line_number_start_, line_number_end_));
     441           0 :   }
     442           0 :   return value_itr->second->doubleValue();
     443           0 : }
     444             : 
     445           0 : double Field::getDouble(const std::string& name, double default_value) const {
     446           0 :   checkType(Type::Object);
     447           0 :   auto value_itr = value_.object_value_.find(name);
     448           0 :   if (value_itr != value_.object_value_.end()) {
     449           0 :     return getDouble(name);
     450           0 :   }
     451           0 :   return default_value;
     452           0 : }
     453             : 
     454           0 : int64_t Field::getInteger(const std::string& name) const {
     455           0 :   checkType(Type::Object);
     456           0 :   auto value_itr = value_.object_value_.find(name);
     457           0 :   if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Integer)) {
     458           0 :     throwExceptionOrPanic(Exception,
     459           0 :                           fmt::format("key '{}' missing or not an integer from lines {}-{}", name,
     460           0 :                                       line_number_start_, line_number_end_));
     461           0 :   }
     462           0 :   return value_itr->second->integerValue();
     463           0 : }
     464             : 
     465           0 : int64_t Field::getInteger(const std::string& name, int64_t default_value) const {
     466           0 :   checkType(Type::Object);
     467           0 :   auto value_itr = value_.object_value_.find(name);
     468           0 :   if (value_itr != value_.object_value_.end()) {
     469           0 :     return getInteger(name);
     470           0 :   }
     471           0 :   return default_value;
     472           0 : }
     473             : 
     474           0 : ObjectSharedPtr Field::getObject(const std::string& name, bool allow_empty) const {
     475           0 :   auto result = getObjectNoThrow(name, allow_empty);
     476           0 :   if (!result.ok()) {
     477           0 :     throwExceptionOrPanic(Exception, std::string(result.status().message()));
     478           0 :   }
     479             : 
     480           0 :   return result.value();
     481           0 : }
     482             : 
     483             : absl::StatusOr<ObjectSharedPtr> Field::getObjectNoThrow(const std::string& name,
     484           0 :                                                         bool allow_empty) const {
     485           0 :   checkType(Type::Object);
     486           0 :   auto value_itr = value_.object_value_.find(name);
     487           0 :   if (value_itr == value_.object_value_.end()) {
     488           0 :     if (allow_empty) {
     489           0 :       return createObject();
     490           0 :     } else {
     491           0 :       return absl::NotFoundError(fmt::format("key '{}' missing from lines {}-{}", name,
     492           0 :                                              line_number_start_, line_number_end_));
     493           0 :     }
     494           0 :   } else if (!value_itr->second->isType(Type::Object)) {
     495           0 :     return absl::InternalError(fmt::format("key '{}' not an object from line {}", name,
     496           0 :                                            value_itr->second->line_number_start_));
     497           0 :   }
     498             : 
     499           0 :   return value_itr->second;
     500           0 : }
     501             : 
     502             : std::vector<ObjectSharedPtr> Field::getObjectArray(const std::string& name,
     503           0 :                                                    bool allow_empty) const {
     504           0 :   checkType(Type::Object);
     505           0 :   auto value_itr = value_.object_value_.find(name);
     506           0 :   if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Array)) {
     507           0 :     if (allow_empty && value_itr == value_.object_value_.end()) {
     508           0 :       return {};
     509           0 :     }
     510           0 :     throwExceptionOrPanic(Exception,
     511           0 :                           fmt::format("key '{}' missing or not an array from lines {}-{}", name,
     512           0 :                                       line_number_start_, line_number_end_));
     513           0 :   }
     514             : 
     515           0 :   std::vector<FieldSharedPtr> array_value = value_itr->second->arrayValue();
     516           0 :   return {array_value.begin(), array_value.end()};
     517           0 : }
     518             : 
     519           0 : std::string Field::getString(const std::string& name) const {
     520           0 :   checkType(Type::Object);
     521           0 :   auto value_itr = value_.object_value_.find(name);
     522           0 :   if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::String)) {
     523           0 :     throwExceptionOrPanic(Exception,
     524           0 :                           fmt::format("key '{}' missing or not a string from lines {}-{}", name,
     525           0 :                                       line_number_start_, line_number_end_));
     526           0 :   }
     527           0 :   return value_itr->second->stringValue();
     528           0 : }
     529             : 
     530           0 : std::string Field::getString(const std::string& name, const std::string& default_value) const {
     531           0 :   checkType(Type::Object);
     532           0 :   auto value_itr = value_.object_value_.find(name);
     533           0 :   if (value_itr != value_.object_value_.end()) {
     534           0 :     return getString(name);
     535           0 :   }
     536           0 :   return default_value;
     537           0 : }
     538             : 
     539           0 : std::vector<std::string> Field::getStringArray(const std::string& name, bool allow_empty) const {
     540           0 :   checkType(Type::Object);
     541           0 :   std::vector<std::string> string_array;
     542           0 :   auto value_itr = value_.object_value_.find(name);
     543           0 :   if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Array)) {
     544           0 :     if (allow_empty && value_itr == value_.object_value_.end()) {
     545           0 :       return string_array;
     546           0 :     }
     547           0 :     throwExceptionOrPanic(Exception,
     548           0 :                           fmt::format("key '{}' missing or not an array from lines {}-{}", name,
     549           0 :                                       line_number_start_, line_number_end_));
     550           0 :   }
     551             : 
     552           0 :   std::vector<FieldSharedPtr> array = value_itr->second->arrayValue();
     553           0 :   string_array.reserve(array.size());
     554           0 :   for (const auto& element : array) {
     555           0 :     if (!element->isType(Type::String)) {
     556           0 :       throwExceptionOrPanic(Exception,
     557           0 :                             fmt::format("JSON array '{}' from line {} does not contain all strings",
     558           0 :                                         name, line_number_start_));
     559           0 :     }
     560           0 :     string_array.push_back(element->stringValue());
     561           0 :   }
     562             : 
     563           0 :   return string_array;
     564           0 : }
     565             : 
     566        7477 : std::vector<ObjectSharedPtr> Field::asObjectArray() const {
     567        7477 :   checkType(Type::Array);
     568        7477 :   return {value_.array_value_.begin(), value_.array_value_.end()};
     569        7477 : }
     570             : 
     571           0 : std::string Field::asJsonString() const {
     572           0 :   nlohmann::json j = asJsonDocument();
     573           0 :   return j.dump();
     574           0 : }
     575             : 
     576           0 : bool Field::empty() const {
     577           0 :   if (isType(Type::Object)) {
     578           0 :     return value_.object_value_.empty();
     579           0 :   } else if (isType(Type::Array)) {
     580           0 :     return value_.array_value_.empty();
     581           0 :   } else {
     582           0 :     throwExceptionOrPanic(
     583           0 :         Exception,
     584           0 :         fmt::format("Json does not support empty() on types other than array and object"));
     585           0 :   }
     586           0 : }
     587             : 
     588           0 : bool Field::hasObject(const std::string& name) const {
     589           0 :   checkType(Type::Object);
     590           0 :   auto value_itr = value_.object_value_.find(name);
     591           0 :   return value_itr != value_.object_value_.end();
     592           0 : }
     593             : 
     594       17890 : void Field::iterate(const ObjectCallback& callback) const {
     595       17890 :   checkType(Type::Object);
     596       39672 :   for (const auto& item : value_.object_value_) {
     597       39672 :     bool stop_iteration = !callback(item.first, *item.second);
     598       39672 :     if (stop_iteration) {
     599           0 :       break;
     600           0 :     }
     601       39672 :   }
     602       17890 : }
     603             : 
     604           0 : void Field::validateSchema(const std::string&) const {
     605           0 :   throwExceptionOrPanic(Exception, "not implemented");
     606           0 : }
     607             : 
     608       17890 : bool ObjectHandler::start_object(std::size_t) {
     609       17890 :   FieldSharedPtr object = Field::createObject();
     610       17890 :   object->setLineNumberStart(line_number_);
     611             : 
     612       17890 :   switch (state_) {
     613        5431 :   case State::ExpectValueOrStartObjectArray:
     614        5431 :     stack_.top()->insert(key_, object);
     615        5431 :     stack_.push(object);
     616        5431 :     state_ = State::ExpectKeyOrEndObject;
     617        5431 :     return true;
     618       12361 :   case State::ExpectArrayValueOrEndArray:
     619       12361 :     stack_.top()->append(object);
     620       12361 :     stack_.push(object);
     621       12361 :     state_ = State::ExpectKeyOrEndObject;
     622       12361 :     return true;
     623          98 :   case State::ExpectRoot:
     624          98 :     root_ = object;
     625          98 :     stack_.push(object);
     626          98 :     state_ = State::ExpectKeyOrEndObject;
     627          98 :     return true;
     628           0 :   case State::ExpectKeyOrEndObject:
     629           0 :     FALLTHRU;
     630           0 :   case State::ExpectFinished:
     631           0 :     PANIC("not implemented");
     632       17890 :   }
     633           0 :   return false;
     634       17890 : }
     635             : 
     636       17890 : bool ObjectHandler::end_object() {
     637       17890 :   if (state_ == State::ExpectKeyOrEndObject) {
     638       17890 :     stack_.top()->setLineNumberEnd(line_number_);
     639       17890 :     stack_.pop();
     640             : 
     641       17890 :     if (stack_.empty()) {
     642          98 :       state_ = State::ExpectFinished;
     643       17792 :     } else if (stack_.top()->isObject()) {
     644        5431 :       state_ = State::ExpectKeyOrEndObject;
     645       12361 :     } else if (stack_.top()->isArray()) {
     646       12361 :       state_ = State::ExpectArrayValueOrEndArray;
     647       12361 :     }
     648       17890 :     return true;
     649       17890 :   }
     650           0 :   PANIC("parsing error not handled");
     651           0 : }
     652             : 
     653       39672 : bool ObjectHandler::key(std::string& val) {
     654       39672 :   if (state_ == State::ExpectKeyOrEndObject) {
     655       39672 :     key_ = val;
     656       39672 :     state_ = State::ExpectValueOrStartObjectArray;
     657       39672 :     return true;
     658       39672 :   }
     659           0 :   PANIC("parsing error not handled");
     660           0 : }
     661             : 
     662        7329 : bool ObjectHandler::start_array(std::size_t) {
     663        7329 :   FieldSharedPtr array = Field::createArray();
     664        7329 :   array->setLineNumberStart(line_number_);
     665             : 
     666        7329 :   switch (state_) {
     667        7287 :   case State::ExpectValueOrStartObjectArray:
     668        7287 :     stack_.top()->insert(key_, array);
     669        7287 :     stack_.push(array);
     670        7287 :     state_ = State::ExpectArrayValueOrEndArray;
     671        7287 :     return true;
     672           0 :   case State::ExpectArrayValueOrEndArray:
     673           0 :     stack_.top()->append(array);
     674           0 :     stack_.push(array);
     675           0 :     return true;
     676          42 :   case State::ExpectRoot:
     677          42 :     root_ = array;
     678          42 :     stack_.push(array);
     679          42 :     state_ = State::ExpectArrayValueOrEndArray;
     680          42 :     return true;
     681           0 :   default:
     682           0 :     PANIC("parsing error not handled");
     683        7329 :   }
     684        7329 : }
     685             : 
     686        7329 : bool ObjectHandler::end_array() {
     687        7329 :   switch (state_) {
     688        7329 :   case State::ExpectArrayValueOrEndArray:
     689        7329 :     stack_.top()->setLineNumberEnd(line_number_);
     690        7329 :     stack_.pop();
     691             : 
     692        7329 :     if (stack_.empty()) {
     693          42 :       state_ = State::ExpectFinished;
     694        7329 :     } else if (stack_.top()->isObject()) {
     695        7287 :       state_ = State::ExpectKeyOrEndObject;
     696        7287 :     } else if (stack_.top()->isArray()) {
     697           0 :       state_ = State::ExpectArrayValueOrEndArray;
     698           0 :     }
     699             : 
     700        7329 :     return true;
     701           0 :   default:
     702           0 :     PANIC("parsing error not handled");
     703        7329 :   }
     704        7329 : }
     705             : 
     706       32372 : bool ObjectHandler::handleValueEvent(FieldSharedPtr ptr) {
     707       32372 :   ptr->setLineNumberStart(line_number_);
     708             : 
     709       32372 :   switch (state_) {
     710       26954 :   case State::ExpectValueOrStartObjectArray:
     711       26954 :     state_ = State::ExpectKeyOrEndObject;
     712       26954 :     stack_.top()->insert(key_, ptr);
     713       26954 :     return true;
     714        5418 :   case State::ExpectArrayValueOrEndArray:
     715        5418 :     stack_.top()->append(ptr);
     716        5418 :     return true;
     717           0 :   default:
     718           0 :     return true;
     719       32372 :   }
     720       32372 : }
     721             : 
     722             : } // namespace
     723             : 
     724         140 : absl::StatusOr<ObjectSharedPtr> Factory::loadFromStringNoThrow(const std::string& json) {
     725         140 :   ObjectHandler handler;
     726         140 :   auto json_container = JsonContainer(json.c_str(), &handler);
     727             : 
     728         140 :   nlohmann::json::sax_parse(json_container, &handler);
     729             : 
     730         140 :   if (handler.hasParseError()) {
     731           0 :     return absl::InternalError(fmt::format("JSON supplied is not valid. Error({}): {}\n",
     732           0 :                                            handler.getErrorPosition(), handler.getParseError()));
     733           0 :   }
     734         140 :   return handler.getRoot();
     735         140 : }
     736             : 
     737         140 : ObjectSharedPtr Factory::loadFromString(const std::string& json) {
     738         140 :   auto result = loadFromStringNoThrow(json);
     739         140 :   if (!result.ok()) {
     740           0 :     throwExceptionOrPanic(Exception, std::string(result.status().message()));
     741           0 :   }
     742             : 
     743         140 :   return result.value();
     744         140 : }
     745             : 
     746             : FieldSharedPtr loadFromProtobufValueInternal(const ProtobufWkt::Value& protobuf_value);
     747             : FieldSharedPtr loadFromProtobufStructInternal(const ProtobufWkt::Struct& protobuf_struct);
     748             : 
     749           0 : FieldSharedPtr loadFromProtobufValueInternal(const ProtobufWkt::Value& protobuf_value) {
     750           0 :   switch (protobuf_value.kind_case()) {
     751           0 :   case ProtobufWkt::Value::kStringValue:
     752           0 :     return Field::createValue(protobuf_value.string_value());
     753           0 :   case ProtobufWkt::Value::kNumberValue:
     754           0 :     return Field::createValue(protobuf_value.number_value());
     755           0 :   case ProtobufWkt::Value::kBoolValue:
     756           0 :     return Field::createValue(protobuf_value.bool_value());
     757           0 :   case ProtobufWkt::Value::kNullValue:
     758           0 :     return Field::createNull();
     759           0 :   case ProtobufWkt::Value::kListValue: {
     760           0 :     FieldSharedPtr array = Field::createArray();
     761           0 :     for (const auto& list_value : protobuf_value.list_value().values()) {
     762           0 :       array->append(loadFromProtobufValueInternal(list_value));
     763           0 :     }
     764           0 :     return array;
     765           0 :   }
     766           0 :   case ProtobufWkt::Value::kStructValue:
     767           0 :     return loadFromProtobufStructInternal(protobuf_value.struct_value());
     768           0 :   default:
     769           0 :     throwExceptionOrPanic(Exception, "Protobuf value case not implemented");
     770           0 :   }
     771           0 : }
     772             : 
     773           0 : FieldSharedPtr loadFromProtobufStructInternal(const ProtobufWkt::Struct& protobuf_struct) {
     774           0 :   auto root = Field::createObject();
     775           0 :   for (const auto& field : protobuf_struct.fields()) {
     776           0 :     root->insert(field.first, loadFromProtobufValueInternal(field.second));
     777           0 :   }
     778             : 
     779           0 :   return root;
     780           0 : }
     781             : 
     782           0 : ObjectSharedPtr Factory::loadFromProtobufStruct(const ProtobufWkt::Struct& protobuf_struct) {
     783           0 :   return loadFromProtobufStructInternal(protobuf_struct);
     784           0 : }
     785             : 
     786        2934 : std::string Factory::serialize(absl::string_view str) {
     787        2934 :   nlohmann::json j(str);
     788        2934 :   return j.dump();
     789        2934 : }
     790             : 
     791             : } // namespace Nlohmann
     792             : } // namespace Json
     793             : } // namespace Envoy

Generated by: LCOV version 1.15