blob: bcea639b6f13efe1ad907c2e4c17012d5ef12550 [file] [log] [blame]
jat@google.com134be542009-08-03 15:30:11 +00001#ifndef _H_Value
2#define _H_Value
3/*
4 * Copyright 2008 Google Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7 * use this file except in compliance with the License. You may obtain a copy of
8 * the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 * License for the specific language governing permissions and limitations under
16 * the License.
17 */
18
19#ifndef _WINDOWS
20// TODO(jat): remove; for abort() which should probably go away
21#include <stdlib.h>
22#endif
23
24#include <string>
25
26#include "Debug.h"
27
28#include "BrowserChannel.h"
29
30class Value {
31public:
32 enum ValueType {
33 NULL_TYPE = VALUE_TYPE_NULL,
34 BOOLEAN = VALUE_TYPE_BOOLEAN,
35 BYTE = VALUE_TYPE_BYTE,
36 CHAR = VALUE_TYPE_CHAR,
37 SHORT = VALUE_TYPE_SHORT,
38 INT = VALUE_TYPE_INT,
39 LONG = VALUE_TYPE_LONG,
40 FLOAT = VALUE_TYPE_FLOAT,
41 DOUBLE = VALUE_TYPE_DOUBLE,
42 STRING = VALUE_TYPE_STRING,
43 JAVA_OBJECT = VALUE_TYPE_JAVA_OBJECT,
44 JS_OBJECT = VALUE_TYPE_JS_OBJECT,
45 UNDEFINED = VALUE_TYPE_UNDEFINED
46 };
47
48private:
49 ValueType type;
50 union {
51 bool boolValue;
52 unsigned char byteValue;
53 unsigned short charValue;
54 double doubleValue;
55 float floatValue;
56 int32_t intValue;
57 int64_t longValue;
58 short shortValue;
59 std::string* stringValue;
60 } value;
61
62public:
63 Value() {
64 type = UNDEFINED;
65 }
66
67 Value(const Value& other) {
68 copyValue(other);
69 }
70
71 Value& operator=(const Value& other) {
72 clearOldValue();
73 copyValue(other);
74 return *this;
75 }
76
77 ~Value() {
78 clearOldValue();
79 }
80
81 bool getBoolean() const {
82 assertType(BOOLEAN);
83 return value.boolValue;
84 }
85
86 unsigned char getByte() const {
87 assertType(BYTE);
88 return value.byteValue;
89 }
90
91 unsigned short getChar() const {
92 assertType(CHAR);
93 return value.charValue;
94 }
95
96 double getDouble() const {
97 assertType(DOUBLE);
98 return value.doubleValue;
99 }
100
101 float getFloat() const {
102 assertType(FLOAT);
103 return value.floatValue;
104 }
105
106 int getInt() const {
107 assertType(INT);
108 return value.intValue;
109 }
110
111 int getJavaObjectId() const {
112 assertType(JAVA_OBJECT);
113 return value.intValue;
114 }
115
116 int getJsObjectId() const {
117 assertType(JS_OBJECT);
118 return value.intValue;
119 }
120
121 int64_t getLong() const {
122 assertType(LONG);
123 return value.longValue;
124 }
125
126 short getShort() const {
127 assertType(SHORT);
128 return value.shortValue;
129 }
130
131 const std::string getString() const {
132 assertType(STRING);
133 return std::string(*value.stringValue);
134 }
135
136 ValueType getType() const {
137 return type;
138 }
139
140 bool isBoolean() const {
141 return type == BOOLEAN;
142 }
143
144 bool isByte() const {
145 return type == BYTE;
146 }
147
148 bool isChar() const {
149 return type == CHAR;
150 }
151
152 bool isDouble() const {
153 return type == DOUBLE;
154 }
155
156 bool isFloat() const {
157 return type == FLOAT;
158 }
159
160 bool isInt() const {
161 return type == INT;
162 }
163
164 bool isJavaObject() const {
165 return type == JAVA_OBJECT;
166 }
167
168 bool isJsObject() const {
169 return type == JS_OBJECT;
170 }
171
172 bool isLong() const {
173 return type == LONG;
174 }
175
176 bool isNull() const {
177 return type == NULL_TYPE;
178 }
179
180 bool isNumber() const {
181 switch (type) {
182 case BYTE:
183 case CHAR:
184 case DOUBLE:
185 case FLOAT:
186 case INT:
187 case LONG:
188 case SHORT:
189 return true;
190 default:
191 return false;
192 }
193 }
194
195 bool isPrimitive() const {
196 switch (type) {
197 case BOOLEAN:
198 case BYTE:
199 case CHAR:
200 case DOUBLE:
201 case FLOAT:
202 case INT:
203 case LONG:
204 case SHORT:
205 return true;
206 default:
207 return false;
208 }
209 }
210
211 bool isShort() const {
212 return type == SHORT;
213 }
214
215 bool isString() const {
216 return type == STRING;
217 }
218
219 bool isUndefined() const {
220 return type == UNDEFINED;
221 }
222
223 void setBoolean(bool val) {
224 clearOldValue();
225 type = BOOLEAN;
226 value.boolValue = val;
227 }
228
229 void setByte(unsigned char val) {
230 clearOldValue();
231 type = BYTE;
232 value.byteValue = val;
233 }
234
235 void setChar(unsigned short val) {
236 clearOldValue();
237 type = CHAR;
238 value.charValue = val;
239 }
240
241 void setDouble(double val) {
242 clearOldValue();
243 type = DOUBLE;
244 value.doubleValue = val;
245 }
246
247 void setFloat(float val) {
248 clearOldValue();
249 type = FLOAT;
250 value.floatValue = val;
251 }
252
253 void setInt(int val) {
254 clearOldValue();
255 type = INT;
256 value.intValue = val;
257 }
258
259 void setJavaObject(int objectId) {
260 clearOldValue();
261 type = JAVA_OBJECT;
262 value.intValue = objectId;
263 }
264
265 void setJsObjectId(int val) {
266 clearOldValue();
267 type = JS_OBJECT;
268 value.intValue = val;
269 }
270
271 void setLong(int64_t val) {
272 clearOldValue();
273 type = LONG;
274 value.longValue = val;
275 }
276
277 void setNull() {
278 clearOldValue();
279 type = NULL_TYPE;
280 }
281
282 void setShort(short val) {
283 clearOldValue();
284 type = SHORT;
285 value.shortValue = val;
286 }
287
288 void setString(const char* chars, int len) {
289 setString(std::string(chars, len));
290 }
291
292 void setString(const std::string& val) {
293 clearOldValue();
294 type = STRING;
295 value.stringValue = new std::string(val);
296 }
297
298 void setUndefined() {
299 clearOldValue();
300 type = UNDEFINED;
301 }
302
303 std::string toString() const {
scottb@google.com8e71b852009-11-30 22:41:59 +0000304 char buf[64];
jat@google.com134be542009-08-03 15:30:11 +0000305 switch (type) {
306 case NULL_TYPE:
307 return "null";
308 case BOOLEAN:
309 snprintf(buf, sizeof(buf), "boolean(%s)", getBoolean() ? "true"
310 : "false");
311 return std::string(buf);
312 case BYTE:
313 snprintf(buf, sizeof(buf), "byte(%d)", getByte());
314 return std::string(buf);
315 case CHAR:
316 snprintf(buf, sizeof(buf), "char(%d)", getChar());
317 return std::string(buf);
318 case SHORT:
319 snprintf(buf, sizeof(buf), "short(%d)", getShort());
320 return std::string(buf);
321 case INT:
322 snprintf(buf, sizeof(buf), "int(%d)", getInt());
323 return std::string(buf);
324 case LONG:
325 snprintf(buf, sizeof(buf), "long(%lld)",
326 static_cast<long long>(getLong()));
327 return std::string(buf);
328 case FLOAT:
scottb@google.com8e71b852009-11-30 22:41:59 +0000329 snprintf(buf, sizeof(buf), "float(%g)", getFloat());
jat@google.com134be542009-08-03 15:30:11 +0000330 return std::string(buf);
331 case DOUBLE:
scottb@google.com8e71b852009-11-30 22:41:59 +0000332 snprintf(buf, sizeof(buf), "double(%g)", getDouble());
jat@google.com134be542009-08-03 15:30:11 +0000333 return std::string(buf);
334 case STRING:
335 snprintf(buf, sizeof(buf), "string(%.20s)", getString().c_str());
336 return std::string(buf);
337 case JAVA_OBJECT:
338 snprintf(buf, sizeof(buf), "JavaObj(%d)", getJavaObjectId());
339 return std::string(buf);
340 case JS_OBJECT:
341 snprintf(buf, sizeof(buf), "JsObj(%d)", getJsObjectId());
342 return std::string(buf);
343 case UNDEFINED:
344 return "undefined";
345 default:
346 return "Unknown type";
347 }
348 }
349
350private:
351 void assertType(ValueType reqType) const {
352 if (type != reqType) {
353 Debug::log(Debug::Error) << "Value::assertType - expecting type "
354 << int(reqType) << ", was " << int(type) << Debug::flush;
355 // TODO(jat): is this portable? Should we do something else here?
356 abort();
357 }
358 }
359
360 void clearOldValue() {
361 if (type == STRING) {
362 delete value.stringValue;
363 type = UNDEFINED;
364 }
365 }
366
367 // Precondition: existing value, if any, has been cleared
368 void copyValue(const Value& other) {
369 type = other.type;
370 value = other.value;
371 // handle deep copies of value types that need it
372 switch (type) {
373 case STRING:
374 value.stringValue = new std::string(*value.stringValue);
375 break;
376 default:
377 // no other values need deep copies
378 break;
379 }
380 }
381};
382
383inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const Value& val) {
scottb@google.com8e71b852009-11-30 22:41:59 +0000384 if (dbg.isActive()) {
385 dbg << val.toString();
386 }
387 return dbg;
jat@google.com134be542009-08-03 15:30:11 +0000388}
389
390#endif