Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/json/json_streamer.cc
Line
Count
Source (jump to first uncovered line)
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
  do {                                                                                             \
21
  } while (0)
22
#define ASSERT_LEVELS_EMPTY                                                                        \
23
  do {                                                                                             \
24
  } while (0)
25
#else
26
0
#define ASSERT_THIS_IS_TOP_LEVEL ASSERT(streamer_.topLevel() == this)
27
0
#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
0
#ifndef NDEBUG
34
0
  streamer_.push(this);
35
0
#endif
36
0
}
37
38
0
Streamer::Level::~Level() {
39
0
  streamer_.addConstantString(closer_);
40
0
#ifndef NDEBUG
41
0
  streamer_.pop(this);
42
0
#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
0
void Streamer::pop(Level* level) {
93
0
  ASSERT(levels_.top() == level);
94
0
  levels_.pop();
95
0
}
96
97
0
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