File indexing completed on 2025-02-28 10:10:20
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef GOOGLE_PROTOBUF_JSON_INTERNAL_WRITER_H__
0009 #define GOOGLE_PROTOBUF_JSON_INTERNAL_WRITER_H__
0010
0011 #include <cfloat>
0012 #include <cmath>
0013 #include <cstdint>
0014 #include <iostream>
0015 #include <limits>
0016 #include <ostream>
0017 #include <string>
0018 #include <tuple>
0019 #include <type_traits>
0020 #include <utility>
0021
0022 #include "absl/strings/str_format.h"
0023 #include "absl/strings/string_view.h"
0024 #include "google/protobuf/io/strtod.h"
0025 #include "google/protobuf/io/zero_copy_sink.h"
0026 #include "google/protobuf/io/zero_copy_stream.h"
0027 #include "google/protobuf/stubs/status_macros.h"
0028
0029
0030 #include "google/protobuf/port_def.inc"
0031
0032 namespace google {
0033 namespace protobuf {
0034 namespace json_internal {
0035 struct WriterOptions {
0036
0037
0038 bool add_whitespace = false;
0039
0040
0041
0042
0043 bool always_print_fields_with_no_presence = false;
0044
0045
0046 bool always_print_enums_as_ints = false;
0047
0048 bool preserve_proto_field_names = false;
0049
0050
0051 bool unquote_int64_if_possible = false;
0052
0053
0054
0055
0056
0057
0058 bool allow_legacy_syntax = false;
0059 };
0060
0061 template <typename Tuple, typename F, size_t... i>
0062 void EachInner(const Tuple& value, F f, std::index_sequence<i...>) {
0063 int ignored[] = {
0064 (f(std::get<i>(value)), 0)...};
0065 (void)ignored;
0066 }
0067
0068
0069 template <typename Tuple, typename F>
0070 void Each(const Tuple& value, F f) {
0071 EachInner(value, f,
0072 std::make_index_sequence<std::tuple_size<Tuple>::value>());
0073 }
0074
0075
0076 template <typename... T>
0077 struct Quoted {
0078 std::tuple<T...> value;
0079 };
0080
0081
0082 template <typename... T>
0083 static Quoted<T...> MakeQuoted(T... t) {
0084 return Quoted<T...>{std::make_tuple(t...)};
0085 }
0086
0087 class JsonWriter {
0088 public:
0089 JsonWriter(io::ZeroCopyOutputStream* out, WriterOptions options)
0090 : sink_(out), options_(options) {}
0091
0092 const WriterOptions& options() const { return options_; }
0093
0094 void Push() { ++indent_; }
0095 void Pop() { --indent_; }
0096
0097
0098
0099
0100
0101
0102
0103
0104 void Write(absl::string_view str) { sink_.Append(str.data(), str.size()); }
0105
0106 void Write(char c) { sink_.Append(&c, 1); }
0107
0108
0109
0110 void Write(double val) {
0111 if (!MaybeWriteSpecialFp(val)) {
0112 Write(io::SimpleDtoa(val));
0113 }
0114 }
0115
0116 void Write(float val) {
0117 if (!MaybeWriteSpecialFp(val)) {
0118 Write(io::SimpleFtoa(val));
0119 }
0120 }
0121
0122 void Write(int32_t val) {
0123 char buf[22];
0124 int len = absl::SNPrintF(buf, sizeof(buf), "%d", val);
0125 absl::string_view view(buf, static_cast<size_t>(len));
0126 Write(view);
0127 }
0128
0129 void Write(uint32_t val) {
0130 char buf[22];
0131 int len = absl::SNPrintF(buf, sizeof(buf), "%d", val);
0132 absl::string_view view(buf, static_cast<size_t>(len));
0133 Write(view);
0134 }
0135
0136 void Write(int64_t val) {
0137 char buf[22];
0138 int len = absl::SNPrintF(buf, sizeof(buf), "%d", val);
0139 absl::string_view view(buf, static_cast<size_t>(len));
0140 Write(view);
0141 }
0142
0143 void Write(uint64_t val) {
0144 char buf[22];
0145 int len = absl::SNPrintF(buf, sizeof(buf), "%d", val);
0146 absl::string_view view(buf, static_cast<size_t>(len));
0147 Write(view);
0148 }
0149
0150 template <typename... Ts>
0151 void Write(Quoted<Ts...> val) {
0152 Write('"');
0153 Each(val.value, [this](auto x) { this->WriteQuoted(x); });
0154 Write('"');
0155 }
0156
0157 template <typename... Ts>
0158 auto Write(Ts... args) ->
0159
0160
0161 typename std::enable_if<sizeof...(Ts) != 1, void>::type {
0162 Each(std::make_tuple(args...), [this](auto x) { this->Write(x); });
0163 }
0164
0165 void Whitespace(absl::string_view ws) {
0166 if (options_.add_whitespace) {
0167 Write(ws);
0168 }
0169 }
0170
0171 void NewLine() {
0172 Whitespace("\n");
0173 for (int i = 0; i < indent_; ++i) {
0174 Whitespace(" ");
0175 }
0176 }
0177
0178 void WriteComma(bool& is_first) {
0179 if (is_first) {
0180 is_first = false;
0181 return;
0182 }
0183 Write(",");
0184 }
0185
0186 void WriteBase64(absl::string_view str);
0187
0188
0189
0190 std::string& ScratchBuf() { return scratch_buf_; }
0191
0192 private:
0193 template <typename T>
0194 void WriteQuoted(T val) {
0195 Write(val);
0196 }
0197
0198 void WriteQuoted(absl::string_view val) { WriteEscapedUtf8(val); }
0199
0200
0201
0202 bool MaybeWriteSpecialFp(double val);
0203
0204 void WriteEscapedUtf8(absl::string_view str);
0205 void WriteUEscape(uint16_t val);
0206
0207 io::zc_sink_internal::ZeroCopyStreamByteSink sink_;
0208 WriterOptions options_;
0209 int indent_ = 0;
0210
0211 std::string scratch_buf_;
0212 };
0213 }
0214 }
0215 }
0216
0217 #include "google/protobuf/port_undef.inc"
0218 #endif