1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31#include <google/protobuf/util/internal/json_objectwriter.h> 32 33#include <math.h> 34 35#include <google/protobuf/stubs/casts.h> 36#include <google/protobuf/stubs/logging.h> 37#include <google/protobuf/stubs/common.h> 38#include <google/protobuf/util/internal/utility.h> 39#include <google/protobuf/util/internal/json_escaping.h> 40#include <google/protobuf/stubs/strutil.h> 41#include <google/protobuf/stubs/mathlimits.h> 42 43namespace google { 44namespace protobuf { 45namespace util { 46namespace converter { 47 48using strings::ArrayByteSource; 49; 50 51JsonObjectWriter::~JsonObjectWriter() { 52 if (!element_->is_root()) { 53 GOOGLE_LOG(WARNING) << "JsonObjectWriter was not fully closed."; 54 } 55} 56 57JsonObjectWriter* JsonObjectWriter::StartObject(StringPiece name) { 58 WritePrefix(name); 59 WriteChar('{'); 60 Push(); 61 return this; 62} 63 64JsonObjectWriter* JsonObjectWriter::EndObject() { 65 Pop(); 66 WriteChar('}'); 67 if (element()->is_root()) NewLine(); 68 return this; 69} 70 71JsonObjectWriter* JsonObjectWriter::StartList(StringPiece name) { 72 WritePrefix(name); 73 WriteChar('['); 74 Push(); 75 return this; 76} 77 78JsonObjectWriter* JsonObjectWriter::EndList() { 79 Pop(); 80 WriteChar(']'); 81 if (element()->is_root()) NewLine(); 82 return this; 83} 84 85JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, bool value) { 86 return RenderSimple(name, value ? "true" : "false"); 87} 88 89JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, int32 value) { 90 return RenderSimple(name, SimpleItoa(value)); 91} 92 93JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name, 94 uint32 value) { 95 return RenderSimple(name, SimpleItoa(value)); 96} 97 98JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, int64 value) { 99 WritePrefix(name); 100 WriteChar('"'); 101 stream_->WriteString(SimpleItoa(value)); 102 WriteChar('"'); 103 return this; 104} 105 106JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name, 107 uint64 value) { 108 WritePrefix(name); 109 WriteChar('"'); 110 stream_->WriteString(SimpleItoa(value)); 111 WriteChar('"'); 112 return this; 113} 114 115JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name, 116 double value) { 117 if (MathLimits<double>::IsFinite(value)) { 118 return RenderSimple(name, SimpleDtoa(value)); 119 } 120 121 // Render quoted with NaN/Infinity-aware DoubleAsString. 122 return RenderString(name, DoubleAsString(value)); 123} 124 125JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, float value) { 126 if (MathLimits<float>::IsFinite(value)) { 127 return RenderSimple(name, SimpleFtoa(value)); 128 } 129 130 // Render quoted with NaN/Infinity-aware FloatAsString. 131 return RenderString(name, FloatAsString(value)); 132} 133 134JsonObjectWriter* JsonObjectWriter::RenderString(StringPiece name, 135 StringPiece value) { 136 WritePrefix(name); 137 WriteChar('"'); 138 ArrayByteSource source(value); 139 JsonEscaping::Escape(&source, &sink_); 140 WriteChar('"'); 141 return this; 142} 143 144JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name, 145 StringPiece value) { 146 WritePrefix(name); 147 string base64; 148 149 if (use_websafe_base64_for_bytes_) 150 WebSafeBase64Escape(value.ToString(), &base64); 151 else 152 Base64Escape(value, &base64); 153 154 WriteChar('"'); 155 // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes 156 // directly to the stream, rather than first putting them 157 // into a string and then writing them to the stream. 158 stream_->WriteRaw(base64.data(), base64.size()); 159 WriteChar('"'); 160 return this; 161} 162 163JsonObjectWriter* JsonObjectWriter::RenderNull(StringPiece name) { 164 return RenderSimple(name, "null"); 165} 166 167void JsonObjectWriter::WritePrefix(StringPiece name) { 168 bool not_first = !element()->is_first(); 169 if (not_first) WriteChar(','); 170 if (not_first || !element()->is_root()) NewLine(); 171 if (!name.empty()) { 172 WriteChar('"'); 173 ArrayByteSource source(name); 174 JsonEscaping::Escape(&source, &sink_); 175 stream_->WriteString("\":"); 176 if (!indent_string_.empty()) WriteChar(' '); 177 } 178} 179 180} // namespace converter 181} // namespace util 182} // namespace protobuf 183} // namespace google 184