Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1073)

Side by Side Diff: base/json/json_writer.cc

Issue 1647803004: Move base to DEPS (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/json/json_writer.h ('k') | base/json/json_writer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/json/json_writer.h"
6
7 #include <cmath>
8
9 #include "base/json/string_escape.h"
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14
15 namespace base {
16
17 #if defined(OS_WIN)
18 const char kPrettyPrintLineEnding[] = "\r\n";
19 #else
20 const char kPrettyPrintLineEnding[] = "\n";
21 #endif
22
23 // static
24 bool JSONWriter::Write(const Value& node, std::string* json) {
25 return WriteWithOptions(node, 0, json);
26 }
27
28 // static
29 bool JSONWriter::WriteWithOptions(const Value& node,
30 int options,
31 std::string* json) {
32 json->clear();
33 // Is there a better way to estimate the size of the output?
34 json->reserve(1024);
35
36 JSONWriter writer(options, json);
37 bool result = writer.BuildJSONString(node, 0U);
38
39 if (options & OPTIONS_PRETTY_PRINT)
40 json->append(kPrettyPrintLineEnding);
41
42 return result;
43 }
44
45 JSONWriter::JSONWriter(int options, std::string* json)
46 : omit_binary_values_((options & OPTIONS_OMIT_BINARY_VALUES) != 0),
47 omit_double_type_preservation_(
48 (options & OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION) != 0),
49 pretty_print_((options & OPTIONS_PRETTY_PRINT) != 0),
50 json_string_(json) {
51 DCHECK(json);
52 }
53
54 bool JSONWriter::BuildJSONString(const Value& node, size_t depth) {
55 switch (node.GetType()) {
56 case Value::TYPE_NULL: {
57 json_string_->append("null");
58 return true;
59 }
60
61 case Value::TYPE_BOOLEAN: {
62 bool value;
63 bool result = node.GetAsBoolean(&value);
64 DCHECK(result);
65 json_string_->append(value ? "true" : "false");
66 return result;
67 }
68
69 case Value::TYPE_INTEGER: {
70 int value;
71 bool result = node.GetAsInteger(&value);
72 DCHECK(result);
73 json_string_->append(IntToString(value));
74 return result;
75 }
76
77 case Value::TYPE_DOUBLE: {
78 double value;
79 bool result = node.GetAsDouble(&value);
80 DCHECK(result);
81 if (omit_double_type_preservation_ &&
82 value <= kint64max &&
83 value >= kint64min &&
84 std::floor(value) == value) {
85 json_string_->append(Int64ToString(static_cast<int64>(value)));
86 return result;
87 }
88 std::string real = DoubleToString(value);
89 // Ensure that the number has a .0 if there's no decimal or 'e'. This
90 // makes sure that when we read the JSON back, it's interpreted as a
91 // real rather than an int.
92 if (real.find('.') == std::string::npos &&
93 real.find('e') == std::string::npos &&
94 real.find('E') == std::string::npos) {
95 real.append(".0");
96 }
97 // The JSON spec requires that non-integer values in the range (-1,1)
98 // have a zero before the decimal point - ".52" is not valid, "0.52" is.
99 if (real[0] == '.') {
100 real.insert(static_cast<size_t>(0), static_cast<size_t>(1), '0');
101 } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
102 // "-.1" bad "-0.1" good
103 real.insert(static_cast<size_t>(1), static_cast<size_t>(1), '0');
104 }
105 json_string_->append(real);
106 return result;
107 }
108
109 case Value::TYPE_STRING: {
110 std::string value;
111 bool result = node.GetAsString(&value);
112 DCHECK(result);
113 EscapeJSONString(value, true, json_string_);
114 return result;
115 }
116
117 case Value::TYPE_LIST: {
118 json_string_->push_back('[');
119 if (pretty_print_)
120 json_string_->push_back(' ');
121
122 const ListValue* list = NULL;
123 bool first_value_has_been_output = false;
124 bool result = node.GetAsList(&list);
125 DCHECK(result);
126 for (ListValue::const_iterator it = list->begin(); it != list->end();
127 ++it) {
128 const Value* value = *it;
129 if (omit_binary_values_ && value->GetType() == Value::TYPE_BINARY)
130 continue;
131
132 if (first_value_has_been_output) {
133 json_string_->push_back(',');
134 if (pretty_print_)
135 json_string_->push_back(' ');
136 }
137
138 if (!BuildJSONString(*value, depth))
139 result = false;
140
141 first_value_has_been_output = true;
142 }
143
144 if (pretty_print_)
145 json_string_->push_back(' ');
146 json_string_->push_back(']');
147 return result;
148 }
149
150 case Value::TYPE_DICTIONARY: {
151 json_string_->push_back('{');
152 if (pretty_print_)
153 json_string_->append(kPrettyPrintLineEnding);
154
155 const DictionaryValue* dict = NULL;
156 bool first_value_has_been_output = false;
157 bool result = node.GetAsDictionary(&dict);
158 DCHECK(result);
159 for (DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd();
160 itr.Advance()) {
161 if (omit_binary_values_ &&
162 itr.value().GetType() == Value::TYPE_BINARY) {
163 continue;
164 }
165
166 if (first_value_has_been_output) {
167 json_string_->push_back(',');
168 if (pretty_print_)
169 json_string_->append(kPrettyPrintLineEnding);
170 }
171
172 if (pretty_print_)
173 IndentLine(depth + 1U);
174
175 EscapeJSONString(itr.key(), true, json_string_);
176 json_string_->push_back(':');
177 if (pretty_print_)
178 json_string_->push_back(' ');
179
180 if (!BuildJSONString(itr.value(), depth + 1U))
181 result = false;
182
183 first_value_has_been_output = true;
184 }
185
186 if (pretty_print_) {
187 json_string_->append(kPrettyPrintLineEnding);
188 IndentLine(depth);
189 }
190
191 json_string_->push_back('}');
192 return result;
193 }
194
195 case Value::TYPE_BINARY:
196 // Successful only if we're allowed to omit it.
197 DLOG_IF(ERROR, !omit_binary_values_) << "Cannot serialize binary value.";
198 return omit_binary_values_;
199 }
200 NOTREACHED();
201 return false;
202 }
203
204 void JSONWriter::IndentLine(size_t depth) {
205 json_string_->append(depth * 3U, ' ');
206 }
207
208 } // namespace base
OLDNEW
« no previous file with comments | « base/json/json_writer.h ('k') | base/json/json_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698