Skip to content

Commit

Permalink
json: replace literal string to constexpr and force Streamer to use s…
Browse files Browse the repository at this point in the history
…imple output abstraction (#35892)

Continuous work of #35891. This replace the literal string to constexpr
string view to make it's more friendly for dev tools. And this PR also
create a simple wrapper to the Buffer::Instance to force the Streamer
only access the limited abstraction (only provides an add()) to
streaming it's output.

Risk Level: low.
Testing: n/a.
Docs Changes: n/a.
Release Notes: n/a.
Platform Specific Features: n/a.

---------

Signed-off-by: wangbaiping <[email protected]>
  • Loading branch information
wbpcode authored Sep 5, 2024
1 parent 8d04baf commit b0da125
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 10 deletions.
9 changes: 9 additions & 0 deletions source/common/json/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,18 @@ envoy_cc_library(
name = "json_streamer_lib",
hdrs = ["json_streamer.h"],
deps = [
":constants_lib",
":json_sanitizer_lib",
"//envoy/buffer:buffer_interface",
"//source/common/buffer:buffer_util_lib",
"//source/common/common:assert_lib",
],
)

envoy_cc_library(
name = "constants_lib",
hdrs = ["constants.h"],
external_deps = [
"abseil_strings",
],
)
17 changes: 17 additions & 0 deletions source/common/json/constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include "absl/strings/string_view.h"

namespace Envoy {
namespace Json {

class Constants {
public:
// Constants for common JSON values.
static constexpr absl::string_view True = "true";
static constexpr absl::string_view False = "false";
static constexpr absl::string_view Null = "null";
};

} // namespace Json
} // namespace Envoy
40 changes: 30 additions & 10 deletions source/common/json/json_streamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "envoy/buffer/buffer.h"

#include "source/common/buffer/buffer_util.h"
#include "source/common/json/constants.h"
#include "source/common/json/json_sanitizer.h"

#include "absl/strings/string_view.h"
Expand Down Expand Up @@ -38,6 +39,18 @@ namespace Json {
#define ASSERT_LEVELS_EMPTY ASSERT(this->levels_.empty())
#endif

// Simple abstraction that provide a output buffer for streaming JSON output.
class BufferOutput {
public:
void add(absl::string_view a) { buffer_.addFragments({a}); }
void add(absl::string_view a, absl::string_view b, absl::string_view c) {
buffer_.addFragments({a, b, c});
}

explicit BufferOutput(Buffer::Instance& output) : buffer_(output) {}
Buffer::Instance& buffer_;
};

/**
* Provides an API for streaming JSON output, as an alternative to populating a
* JSON structure with an image of what you want to serialize, or using a
Expand Down Expand Up @@ -143,7 +156,7 @@ class Streamer {
void addString(absl::string_view str) {
ASSERT_THIS_IS_TOP_LEVEL;
nextField();
streamer_.addSanitized("\"", str, "\"");
streamer_.addString(str);
}

/**
Expand Down Expand Up @@ -243,7 +256,7 @@ class Streamer {
ASSERT_THIS_IS_TOP_LEVEL;
ASSERT(!expecting_value_);
nextField();
this->streamer_.addSanitized(R"(")", key, R"(":)");
this->streamer_.addSanitized("\"", key, "\":");
expecting_value_ = true;
}

Expand Down Expand Up @@ -331,32 +344,39 @@ class Streamer {
*/
void addSanitized(absl::string_view prefix, absl::string_view token, absl::string_view suffix) {
absl::string_view sanitized = Json::sanitize(sanitize_buffer_, token);
response_.addFragments({prefix, sanitized, suffix});
response_.add(prefix, sanitized, suffix);
}

/**
* Serializes a string to the output stream. The input string value will be sanitized and
* surrounded by quotes.
* @param str the string to be serialized.
*/
void addString(absl::string_view str) { addSanitized("\"", str, "\""); }

/**
* Serializes a number.
*/
void addNumber(double d) {
if (std::isnan(d)) {
response_.addFragments({"null"});
response_.add(Constants::Null);
} else {
Buffer::Util::serializeDouble(d, response_);
Buffer::Util::serializeDouble(d, response_.buffer_);
}
}
void addNumber(uint64_t u) { response_.addFragments({absl::StrCat(u)}); }
void addNumber(int64_t i) { response_.addFragments({absl::StrCat(i)}); }
void addNumber(uint64_t u) { response_.add(absl::StrCat(u)); }
void addNumber(int64_t i) { response_.add(absl::StrCat(i)); }

/**
* Serializes a bool to the output stream.
*/
void addBool(bool b) { response_.addFragments({b ? "true" : "false"}); }
void addBool(bool b) { response_.add(b ? Constants::True : Constants::False); }

/**
* Adds a constant string to the output stream. The string must outlive the
* Streamer object, and is intended for literal strings such as punctuation.
*/
void addConstantString(absl::string_view str) { response_.addFragments({str}); }
void addConstantString(absl::string_view str) { response_.add(str); }

#ifndef NDEBUG
/**
Expand All @@ -379,7 +399,7 @@ class Streamer {

#endif

Buffer::Instance& response_;
BufferOutput response_;
std::string sanitize_buffer_;

#ifndef NDEBUG
Expand Down

0 comments on commit b0da125

Please sign in to comment.