Line data Source code
1 : #include "source/common/json/json_streamer.h" 2 : 3 : #include "source/common/buffer/buffer_util.h" 4 : #include "source/common/json/json_sanitizer.h" 5 : 6 : namespace Envoy { 7 : namespace Json { 8 : 9 : // To ensure the streamer is being used correctly, we use assertions to enforce 10 : // that only the topmost map/array in the stack is being written to. To make 11 : // this easier to do from the Level classes, we provider Streamer::topLevel() as 12 : // a member function, but this is only needed when compiled for debug. 13 : // 14 : // We only compile Streamer::topLevel in debug to avoid having it be a coverage 15 : // gap. However, assertions fail to compile in release mode if they reference 16 : // non-existent functions or member variables, so we only compile the assertions 17 : // in debug mode. 18 : #ifdef NDEBUG 19 : #define ASSERT_THIS_IS_TOP_LEVEL \ 20 0 : do { \ 21 0 : } while (0) 22 : #define ASSERT_LEVELS_EMPTY \ 23 0 : do { \ 24 0 : } while (0) 25 : #else 26 : #define ASSERT_THIS_IS_TOP_LEVEL ASSERT(streamer_.topLevel() == this) 27 : #define ASSERT_LEVELS_EMPTY ASSERT(levels_.empty()) 28 : #endif 29 : 30 : Streamer::Level::Level(Streamer& streamer, absl::string_view opener, absl::string_view closer) 31 0 : : streamer_(streamer), closer_(closer) { 32 0 : streamer_.addConstantString(opener); 33 : #ifndef NDEBUG 34 : streamer_.push(this); 35 : #endif 36 0 : } 37 : 38 0 : Streamer::Level::~Level() { 39 0 : streamer_.addConstantString(closer_); 40 : #ifndef NDEBUG 41 : streamer_.pop(this); 42 : #endif 43 0 : } 44 : 45 0 : Streamer::MapPtr Streamer::makeRootMap() { 46 0 : ASSERT_LEVELS_EMPTY; 47 0 : return std::make_unique<Map>(*this); 48 0 : } 49 : 50 0 : Streamer::ArrayPtr Streamer::makeRootArray() { 51 0 : ASSERT_LEVELS_EMPTY; 52 0 : return std::make_unique<Array>(*this); 53 0 : } 54 : 55 0 : Streamer::MapPtr Streamer::Level::addMap() { 56 0 : ASSERT_THIS_IS_TOP_LEVEL; 57 0 : nextField(); 58 0 : return std::make_unique<Map>(streamer_); 59 0 : } 60 : 61 0 : Streamer::ArrayPtr Streamer::Level::addArray() { 62 0 : ASSERT_THIS_IS_TOP_LEVEL; 63 0 : nextField(); 64 0 : return std::make_unique<Array>(streamer_); 65 0 : } 66 : 67 0 : void Streamer::Level::addNumber(double number) { 68 0 : ASSERT_THIS_IS_TOP_LEVEL; 69 0 : nextField(); 70 0 : streamer_.addNumber(number); 71 0 : } 72 : 73 0 : void Streamer::Level::addNumber(uint64_t number) { 74 0 : ASSERT_THIS_IS_TOP_LEVEL; 75 0 : nextField(); 76 0 : streamer_.addNumber(number); 77 0 : } 78 : 79 0 : void Streamer::Level::addNumber(int64_t number) { 80 0 : ASSERT_THIS_IS_TOP_LEVEL; 81 0 : nextField(); 82 0 : streamer_.addNumber(number); 83 0 : } 84 : 85 0 : void Streamer::Level::addString(absl::string_view str) { 86 0 : ASSERT_THIS_IS_TOP_LEVEL; 87 0 : nextField(); 88 0 : streamer_.addSanitized("\"", str, "\""); 89 0 : } 90 : 91 : #ifndef NDEBUG 92 : void Streamer::pop(Level* level) { 93 : ASSERT(levels_.top() == level); 94 : levels_.pop(); 95 : } 96 : 97 : void Streamer::push(Level* level) { levels_.push(level); } 98 : #endif 99 : 100 0 : void Streamer::Level::nextField() { 101 0 : if (is_first_) { 102 0 : is_first_ = false; 103 0 : } else { 104 0 : streamer_.addConstantString(","); 105 0 : } 106 0 : } 107 : 108 0 : void Streamer::Map::nextField() { 109 0 : if (expecting_value_) { 110 0 : expecting_value_ = false; 111 0 : } else { 112 0 : Level::nextField(); 113 0 : } 114 0 : } 115 : 116 0 : void Streamer::Map::addKey(absl::string_view key) { 117 0 : ASSERT_THIS_IS_TOP_LEVEL; 118 0 : ASSERT(!expecting_value_); 119 0 : nextField(); 120 0 : streamer_.addSanitized("\"", key, "\":"); 121 0 : expecting_value_ = true; 122 0 : } 123 : 124 0 : void Streamer::Map::addEntries(const Entries& entries) { 125 0 : for (const NameValue& entry : entries) { 126 0 : addKey(entry.first); 127 0 : addValue(entry.second); 128 0 : } 129 0 : } 130 : 131 0 : void Streamer::Level::addValue(const Value& value) { 132 0 : switch (value.index()) { 133 0 : case 0: 134 0 : addString(absl::get<absl::string_view>(value)); 135 0 : break; 136 0 : case 1: 137 0 : addNumber(absl::get<double>(value)); 138 0 : break; 139 0 : case 2: 140 0 : addNumber(absl::get<uint64_t>(value)); 141 0 : break; 142 0 : case 3: 143 0 : addNumber(absl::get<int64_t>(value)); 144 0 : break; 145 0 : default: 146 0 : IS_ENVOY_BUG(absl::StrCat("addValue invalid index: ", value.index())); 147 0 : break; 148 0 : } 149 0 : } 150 : 151 0 : void Streamer::Array::addEntries(const Entries& values) { 152 0 : for (const Value& value : values) { 153 0 : addValue(value); 154 0 : } 155 0 : } 156 : 157 0 : void Streamer::addNumber(double number) { 158 0 : if (std::isnan(number)) { 159 0 : response_.addFragments({"null"}); 160 0 : } else { 161 0 : Buffer::Util::serializeDouble(number, response_); 162 0 : } 163 0 : } 164 : 165 0 : void Streamer::addNumber(uint64_t number) { response_.addFragments({absl::StrCat(number)}); } 166 : 167 0 : void Streamer::addNumber(int64_t number) { response_.addFragments({absl::StrCat(number)}); } 168 : 169 : void Streamer::addSanitized(absl::string_view prefix, absl::string_view str, 170 0 : absl::string_view suffix) { 171 0 : absl::string_view sanitized = Json::sanitize(sanitize_buffer_, str); 172 0 : response_.addFragments({prefix, sanitized, suffix}); 173 0 : } 174 : 175 : } // namespace Json 176 : } // namespace Envoy