OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/json/json_writer.h" | 5 #include "base/json/json_writer.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/json/string_escape.h" | 9 #include "base/json/string_escape.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 bool pretty_print = !!(options & OPTIONS_PRETTY_PRINT); | 43 bool pretty_print = !!(options & OPTIONS_PRETTY_PRINT); |
44 | 44 |
45 JSONWriter writer(escape, omit_binary_values, omit_double_type_preservation, | 45 JSONWriter writer(escape, omit_binary_values, omit_double_type_preservation, |
46 pretty_print, json); | 46 pretty_print, json); |
47 writer.BuildJSONString(node, 0); | 47 writer.BuildJSONString(node, 0); |
48 | 48 |
49 if (pretty_print) | 49 if (pretty_print) |
50 json->append(kPrettyPrintLineEnding); | 50 json->append(kPrettyPrintLineEnding); |
51 } | 51 } |
52 | 52 |
| 53 std::string JSONWriter::DoubleToFormattedString(double value, |
| 54 bool omit_double_type_preservation) { |
| 55 if (omit_double_type_preservation && |
| 56 value <= kint64max && |
| 57 value >= kint64min && |
| 58 std::floor(value) == value) { |
| 59 return Int64ToString(static_cast<int64>(value)); |
| 60 } |
| 61 std::string real = DoubleToString(value); |
| 62 // Ensure that the number has a .0 if there's no decimal or 'e'. This |
| 63 // makes sure that when we read the JSON back, it's interpreted as a |
| 64 // real rather than an int. |
| 65 if (real.find('.') == std::string::npos && |
| 66 real.find('e') == std::string::npos && |
| 67 real.find('E') == std::string::npos) { |
| 68 real.append(".0"); |
| 69 } |
| 70 // The JSON spec requires that non-integer values in the range (-1,1) |
| 71 // have a zero before the decimal point - ".52" is not valid, "0.52" is. |
| 72 if (real[0] == '.') { |
| 73 real.insert(0, "0"); |
| 74 } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') { |
| 75 // "-.1" bad "-0.1" good |
| 76 real.insert(1, "0"); |
| 77 } |
| 78 return real; |
| 79 } |
| 80 |
53 JSONWriter::JSONWriter(bool escape, bool omit_binary_values, | 81 JSONWriter::JSONWriter(bool escape, bool omit_binary_values, |
54 bool omit_double_type_preservation, bool pretty_print, | 82 bool omit_double_type_preservation, bool pretty_print, |
55 std::string* json) | 83 std::string* json) |
56 : escape_(escape), | 84 : escape_(escape), |
57 omit_binary_values_(omit_binary_values), | 85 omit_binary_values_(omit_binary_values), |
58 omit_double_type_preservation_(omit_double_type_preservation), | 86 omit_double_type_preservation_(omit_double_type_preservation), |
59 pretty_print_(pretty_print), | 87 pretty_print_(pretty_print), |
60 json_string_(json) { | 88 json_string_(json) { |
61 DCHECK(json); | 89 DCHECK(json); |
62 } | 90 } |
(...skipping 20 matching lines...) Expand all Loading... |
83 DCHECK(result); | 111 DCHECK(result); |
84 base::StringAppendF(json_string_, "%d", value); | 112 base::StringAppendF(json_string_, "%d", value); |
85 break; | 113 break; |
86 } | 114 } |
87 | 115 |
88 case Value::TYPE_DOUBLE: | 116 case Value::TYPE_DOUBLE: |
89 { | 117 { |
90 double value; | 118 double value; |
91 bool result = node->GetAsDouble(&value); | 119 bool result = node->GetAsDouble(&value); |
92 DCHECK(result); | 120 DCHECK(result); |
93 if (omit_double_type_preservation_ && | 121 json_string_->append(DoubleToFormattedString(value, |
94 value <= kint64max && | 122 omit_double_type_preservation_)); |
95 value >= kint64min && | |
96 std::floor(value) == value) { | |
97 json_string_->append(Int64ToString(static_cast<int64>(value))); | |
98 break; | |
99 } | |
100 std::string real = DoubleToString(value); | |
101 // Ensure that the number has a .0 if there's no decimal or 'e'. This | |
102 // makes sure that when we read the JSON back, it's interpreted as a | |
103 // real rather than an int. | |
104 if (real.find('.') == std::string::npos && | |
105 real.find('e') == std::string::npos && | |
106 real.find('E') == std::string::npos) { | |
107 real.append(".0"); | |
108 } | |
109 // The JSON spec requires that non-integer values in the range (-1,1) | |
110 // have a zero before the decimal point - ".52" is not valid, "0.52" is. | |
111 if (real[0] == '.') { | |
112 real.insert(0, "0"); | |
113 } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') { | |
114 // "-.1" bad "-0.1" good | |
115 real.insert(1, "0"); | |
116 } | |
117 json_string_->append(real); | |
118 break; | 123 break; |
119 } | 124 } |
120 | 125 |
121 case Value::TYPE_STRING: | 126 case Value::TYPE_STRING: |
122 { | 127 { |
123 std::string value; | 128 std::string value; |
124 bool result = node->GetAsString(&value); | 129 bool result = node->GetAsString(&value); |
125 DCHECK(result); | 130 DCHECK(result); |
126 if (escape_) { | 131 if (escape_) { |
127 JsonDoubleQuote(UTF8ToUTF16(value), true, json_string_); | 132 JsonDoubleQuote(UTF8ToUTF16(value), true, json_string_); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 JsonDoubleQuote(UTF8ToUTF16(str), true, json_string_); | 229 JsonDoubleQuote(UTF8ToUTF16(str), true, json_string_); |
225 } | 230 } |
226 | 231 |
227 void JSONWriter::IndentLine(int depth) { | 232 void JSONWriter::IndentLine(int depth) { |
228 // It may be faster to keep an indent string so we don't have to keep | 233 // It may be faster to keep an indent string so we don't have to keep |
229 // reallocating. | 234 // reallocating. |
230 json_string_->append(std::string(depth * 3, ' ')); | 235 json_string_->append(std::string(depth * 3, ' ')); |
231 } | 236 } |
232 | 237 |
233 } // namespace base | 238 } // namespace base |
OLD | NEW |