Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-28 10:10:20

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2008 Google Inc.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
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 // Must be included last.
0030 #include "google/protobuf/port_def.inc"
0031 
0032 namespace google {
0033 namespace protobuf {
0034 namespace json_internal {
0035 struct WriterOptions {
0036   // Whether to add spaces, line breaks and indentation to make the JSON output
0037   // easy to read.
0038   bool add_whitespace = false;
0039   // Whether to always print fields which do not support presence if they would
0040   // otherwise be omitted, namely:
0041   // - Implicit presence fields set to their 0 value
0042   // - Empty lists and maps
0043   bool always_print_fields_with_no_presence = false;
0044   // Whether to always print enums as ints. By default they are rendered as
0045   // strings.
0046   bool always_print_enums_as_ints = false;
0047   // Whether to preserve proto field names
0048   bool preserve_proto_field_names = false;
0049   // If set, int64 values that can be represented exactly as a double are
0050   // printed without quotes.
0051   bool unquote_int64_if_possible = false;
0052   // The original parser used by json_util2 accepted a number of non-standard
0053   // options. Setting this flag enables them.
0054   //
0055   // What those extensions were is explicitly not documented, beyond what exists
0056   // in the unit tests; we intend to remove this setting eventually. See
0057   // b/234868512.
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)...};  // NOLINT(readability/braces)
0065   (void)ignored;
0066 }
0067 
0068 // Executes f on each element of value.
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 // See JsonWriter::Write().
0076 template <typename... T>
0077 struct Quoted {
0078   std::tuple<T...> value;
0079 };
0080 
0081 // Because this is not C++17 yet, we cannot add a deduction guide.
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   // The many overloads of Write() will write a value to the underlying stream.
0098   // Some values may want to be quoted; the Quoted<> type will automatically add
0099   // quotes and escape sequences.
0100   //
0101   // Note that Write() is not implemented for 64-bit integers, since they
0102   // cannot be crisply represented without quotes; use MakeQuoted for that.
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   // The precision on this and the following function are completely made-up,
0109   // in an attempt to match the behavior of the ESF parser.
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       // This bit of SFINAE avoids this function being called with one argument,
0160       // so the other overloads of Write() can be picked up instead.
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   // Returns a buffer that can be re-used throughout a writing session as
0189   // variable-length scratch space.
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   // Tries to write a non-finite double if necessary; returns false if
0201   // nothing was written.
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 }  // namespace json_internal
0214 }  // namespace protobuf
0215 }  // namespace google
0216 
0217 #include "google/protobuf/port_undef.inc"
0218 #endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_WRITER_H__