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

Side by Side Diff: base/values.cc

Issue 2558023002: Inline FundamentalValue into base::Value (Closed)
Patch Set: Value(Type) initializes with the default value Created 3 years, 12 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/values.h ('k') | base/values_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
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/values.h" 5 #include "base/values.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cmath> 10 #include <cmath>
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 return CopyDictionaryWithoutEmptyChildren( 68 return CopyDictionaryWithoutEmptyChildren(
69 static_cast<const DictionaryValue&>(node)); 69 static_cast<const DictionaryValue&>(node));
70 70
71 default: 71 default:
72 return node.CreateDeepCopy(); 72 return node.CreateDeepCopy();
73 } 73 }
74 } 74 }
75 75
76 } // namespace 76 } // namespace
77 77
78 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {}
79
80 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {}
81
82 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) {
83 if (!std::isfinite(double_value_)) {
84 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
85 << "values cannot be represented in JSON";
86 double_value_ = 0.0;
87 }
88 }
89
78 Value::~Value() { 90 Value::~Value() {
79 } 91 }
80 92
93 void Value::InternalCopyFrom(const Value& that) {
94 type_ = that.type_;
95 switch (type_) {
96 case Type::NONE:
97 // Nothing to do
98 return;
99
100 case Type::BOOLEAN:
101 bool_value_ = that.bool_value_;
102 return;
103 case Type::INTEGER:
104 int_value_ = that.int_value_;
105 return;
106 case Type::DOUBLE:
107 double_value_ = that.double_value_;
108 return;
109
110 // TODO(crbug.com/646113): Implement these once the corresponding derived
111 // classes are removed.
112 case Type::STRING:
113 case Type::BINARY:
114 case Type::LIST:
115 case Type::DICTIONARY:
116 return;
117 }
118 }
119
81 // static 120 // static
82 std::unique_ptr<Value> Value::CreateNullValue() { 121 std::unique_ptr<Value> Value::CreateNullValue() {
83 return WrapUnique(new Value(Type::NONE)); 122 return WrapUnique(new Value(Type::NONE));
84 } 123 }
85 124
86 // static 125 // static
87 const char* Value::GetTypeName(Value::Type type) { 126 const char* Value::GetTypeName(Value::Type type) {
88 DCHECK_GE(static_cast<int>(type), 0); 127 DCHECK_GE(static_cast<int>(type), 0);
89 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames)); 128 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames));
90 return kTypeNames[static_cast<size_t>(type)]; 129 return kTypeNames[static_cast<size_t>(type)];
91 } 130 }
92 131
132 bool Value::GetBool() const {
133 CHECK(is_bool());
134 return bool_value_;
135 }
136
137 int Value::GetInt() const {
138 CHECK(is_int());
139 return int_value_;
140 }
141
142 double Value::GetDouble() const {
143 if (is_double())
144 return double_value_;
145 if (is_int())
146 return int_value_;
147 CHECK(false);
148 return 0.0;
149 }
150
93 bool Value::GetAsBinary(const BinaryValue** out_value) const { 151 bool Value::GetAsBinary(const BinaryValue** out_value) const {
94 return false; 152 return false;
95 } 153 }
96 154
97 bool Value::GetAsBoolean(bool* out_value) const { 155 bool Value::GetAsBoolean(bool* out_value) const {
98 return false; 156 if (out_value && is_bool()) {
157 *out_value = bool_value_;
158 return true;
159 }
160 return is_bool();
99 } 161 }
100 162
101 bool Value::GetAsInteger(int* out_value) const { 163 bool Value::GetAsInteger(int* out_value) const {
102 return false; 164 if (out_value && is_int()) {
165 *out_value = int_value_;
166 return true;
167 }
168 return is_int();
103 } 169 }
104 170
105 bool Value::GetAsDouble(double* out_value) const { 171 bool Value::GetAsDouble(double* out_value) const {
106 return false; 172 if (out_value && is_double()) {
173 *out_value = double_value_;
174 return true;
175 } else if (out_value && is_int()) {
176 // Allow promotion from int to double.
177 *out_value = int_value_;
178 return true;
179 }
180 return is_double() || is_int();
107 } 181 }
108 182
109 bool Value::GetAsString(std::string* out_value) const { 183 bool Value::GetAsString(std::string* out_value) const {
110 return false; 184 return false;
111 } 185 }
112 186
113 bool Value::GetAsString(string16* out_value) const { 187 bool Value::GetAsString(string16* out_value) const {
114 return false; 188 return false;
115 } 189 }
116 190
(...skipping 17 matching lines...) Expand all
134 return false; 208 return false;
135 } 209 }
136 210
137 bool Value::GetAsDictionary(const DictionaryValue** out_value) const { 211 bool Value::GetAsDictionary(const DictionaryValue** out_value) const {
138 return false; 212 return false;
139 } 213 }
140 214
141 Value* Value::DeepCopy() const { 215 Value* Value::DeepCopy() const {
142 // This method should only be getting called for null Values--all subclasses 216 // This method should only be getting called for null Values--all subclasses
143 // need to provide their own implementation;. 217 // need to provide their own implementation;.
144 DCHECK(IsType(Type::NONE)); 218 switch (type()) {
145 return CreateNullValue().release(); 219 case Type::NONE:
220 return CreateNullValue().release();
221
222 // For now, make FundamentalValues for backward-compatibility. Convert to
223 // Value when that code is deleted.
224 case Type::BOOLEAN:
225 return new FundamentalValue(bool_value_);
226 case Type::INTEGER:
227 return new FundamentalValue(int_value_);
228 case Type::DOUBLE:
229 return new FundamentalValue(double_value_);
230
231 default:
232 // All other types should be handled by subclasses.
233 NOTREACHED();
234 return nullptr;
235 }
146 } 236 }
147 237
148 std::unique_ptr<Value> Value::CreateDeepCopy() const { 238 std::unique_ptr<Value> Value::CreateDeepCopy() const {
149 return WrapUnique(DeepCopy()); 239 return WrapUnique(DeepCopy());
150 } 240 }
151 241
152 bool Value::Equals(const Value* other) const { 242 bool Value::Equals(const Value* other) const {
153 // This method should only be getting called for null Values--all subclasses 243 if (other->type() != type())
154 // need to provide their own implementation;. 244 return false;
155 DCHECK(IsType(Type::NONE)); 245
156 return other->IsType(Type::NONE); 246 switch (type()) {
247 case Type::NONE:
248 return true;
249 case Type::BOOLEAN:
250 return bool_value_ == other->bool_value_;
251 case Type::INTEGER:
252 return int_value_ == other->int_value_;
253 case Type::DOUBLE:
254 return double_value_ == other->double_value_;
255 default:
256 // This method should only be getting called for the above types -- all
257 // subclasses need to provide their own implementation;.
258 NOTREACHED();
259 return false;
260 }
157 } 261 }
158 262
159 // static 263 // static
160 bool Value::Equals(const Value* a, const Value* b) { 264 bool Value::Equals(const Value* a, const Value* b) {
161 if ((a == NULL) && (b == NULL)) return true; 265 if ((a == NULL) && (b == NULL)) return true;
162 if ((a == NULL) ^ (b == NULL)) return false; 266 if ((a == NULL) ^ (b == NULL)) return false;
163 return a->Equals(b); 267 return a->Equals(b);
164 } 268 }
165 269
166 Value::Value(Type type) : type_(type) {} 270 Value::Value(Type type) : type_(type) {
271 // Initialize with the default value.
272 switch (type_) {
273 case Type::NONE:
274 return;
167 275
168 Value::Value(const Value& that) : type_(that.type_) {} 276 case Type::BOOLEAN:
277 bool_value_ = bool();
278 return;
279 case Type::INTEGER:
280 int_value_ = int();
281 return;
282 case Type::DOUBLE:
283 double_value_ = double();
284 return;
285
286 // TODO(crbug.com/646113): Implement these once the corresponding derived
287 // classes are removed.
288 case Type::STRING:
289 case Type::BINARY:
290 case Type::LIST:
291 case Type::DICTIONARY:
292 return;
293 }
294 NOTREACHED();
295 return;
jdoerrie 2017/01/02 09:55:10 Since the compiler already enforces that we cover
296 }
297
298 Value::Value(const Value& that) {
299 InternalCopyFrom(that);
300 }
301
302 Value::Value(Value&& that) {
303 // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving
304 // and copying differ.
305 InternalCopyFrom(that);
306 }
169 307
170 Value& Value::operator=(const Value& that) { 308 Value& Value::operator=(const Value& that) {
171 type_ = that.type_; 309 if (this != &that)
310 InternalCopyFrom(that);
311
312 return *this;
313 }
314
315 Value& Value::operator=(Value&& that) {
316 if (this != &that) {
317 // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving
318 // and copying differ.
319 InternalCopyFrom(that);
320 }
321
172 return *this; 322 return *this;
173 } 323 }
174 324
175 ///////////////////// FundamentalValue //////////////////// 325 ///////////////////// FundamentalValue ////////////////////
176 326
177 FundamentalValue::FundamentalValue(bool in_value) 327 FundamentalValue::FundamentalValue(bool in_value) : Value(in_value) {}
178 : Value(Type::BOOLEAN), boolean_value_(in_value) {}
179 328
180 FundamentalValue::FundamentalValue(int in_value) 329 FundamentalValue::FundamentalValue(int in_value) : Value(in_value) {}
181 : Value(Type::INTEGER), integer_value_(in_value) {}
182 330
183 FundamentalValue::FundamentalValue(double in_value) 331 FundamentalValue::FundamentalValue(double in_value) : Value(in_value) {}
184 : Value(Type::DOUBLE), double_value_(in_value) {
185 if (!std::isfinite(double_value_)) {
186 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
187 << "values cannot be represented in JSON";
188 double_value_ = 0.0;
189 }
190 }
191 332
192 FundamentalValue::~FundamentalValue() { 333 FundamentalValue::~FundamentalValue() {}
193 }
194
195 bool FundamentalValue::GetAsBoolean(bool* out_value) const {
196 if (out_value && IsType(Type::BOOLEAN))
197 *out_value = boolean_value_;
198 return (IsType(Type::BOOLEAN));
199 }
200
201 bool FundamentalValue::GetAsInteger(int* out_value) const {
202 if (out_value && IsType(Type::INTEGER))
203 *out_value = integer_value_;
204 return (IsType(Type::INTEGER));
205 }
206
207 bool FundamentalValue::GetAsDouble(double* out_value) const {
208 if (out_value && IsType(Type::DOUBLE))
209 *out_value = double_value_;
210 else if (out_value && IsType(Type::INTEGER))
211 *out_value = integer_value_;
212 return (IsType(Type::DOUBLE) || IsType(Type::INTEGER));
213 }
214
215 FundamentalValue* FundamentalValue::DeepCopy() const {
216 switch (GetType()) {
217 case Type::BOOLEAN:
218 return new FundamentalValue(boolean_value_);
219
220 case Type::INTEGER:
221 return new FundamentalValue(integer_value_);
222
223 case Type::DOUBLE:
224 return new FundamentalValue(double_value_);
225
226 default:
227 NOTREACHED();
228 return NULL;
229 }
230 }
231
232 bool FundamentalValue::Equals(const Value* other) const {
233 if (other->GetType() != GetType())
234 return false;
235
236 switch (GetType()) {
237 case Type::BOOLEAN: {
238 bool lhs, rhs;
239 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
240 }
241 case Type::INTEGER: {
242 int lhs, rhs;
243 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
244 }
245 case Type::DOUBLE: {
246 double lhs, rhs;
247 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
248 }
249 default:
250 NOTREACHED();
251 return false;
252 }
253 }
254 334
255 ///////////////////// StringValue //////////////////// 335 ///////////////////// StringValue ////////////////////
256 336
257 StringValue::StringValue(StringPiece in_value) 337 StringValue::StringValue(StringPiece in_value)
258 : Value(Type::STRING), value_(in_value.as_string()) { 338 : Value(Type::STRING), value_(in_value.as_string()) {
259 DCHECK(IsStringUTF8(in_value)); 339 DCHECK(IsStringUTF8(in_value));
260 } 340 }
261 341
262 StringValue::StringValue(const string16& in_value) 342 StringValue::StringValue(const string16& in_value)
263 : Value(Type::STRING), value_(UTF16ToUTF8(in_value)) {} 343 : Value(Type::STRING), value_(UTF16ToUTF8(in_value)) {}
(...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after
1175 } 1255 }
1176 1256
1177 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { 1257 std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1178 if (static_cast<int>(type) < 0 || 1258 if (static_cast<int>(type) < 0 ||
1179 static_cast<size_t>(type) >= arraysize(kTypeNames)) 1259 static_cast<size_t>(type) >= arraysize(kTypeNames))
1180 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; 1260 return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1181 return out << Value::GetTypeName(type); 1261 return out << Value::GetTypeName(type);
1182 } 1262 }
1183 1263
1184 } // namespace base 1264 } // namespace base
OLDNEW
« no previous file with comments | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698