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

Side by Side Diff: base/values.cc

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