blob: ab50f5e69a3ebb650a7425ad43e12e835e3651ae [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
acleung@google.comcd201b72012-01-24 16:23:41 +000030namespace gwt {
jat@google.com134be542009-08-03 15:30:11 +000031class Value {
32public:
33 enum ValueType {
34 NULL_TYPE = VALUE_TYPE_NULL,
35 BOOLEAN = VALUE_TYPE_BOOLEAN,
36 BYTE = VALUE_TYPE_BYTE,
37 CHAR = VALUE_TYPE_CHAR,
38 SHORT = VALUE_TYPE_SHORT,
39 INT = VALUE_TYPE_INT,
40 LONG = VALUE_TYPE_LONG,
41 FLOAT = VALUE_TYPE_FLOAT,
42 DOUBLE = VALUE_TYPE_DOUBLE,
43 STRING = VALUE_TYPE_STRING,
44 JAVA_OBJECT = VALUE_TYPE_JAVA_OBJECT,
45 JS_OBJECT = VALUE_TYPE_JS_OBJECT,
46 UNDEFINED = VALUE_TYPE_UNDEFINED
47 };
48
49private:
50 ValueType type;
51 union {
52 bool boolValue;
53 unsigned char byteValue;
54 unsigned short charValue;
55 double doubleValue;
56 float floatValue;
57 int32_t intValue;
58 int64_t longValue;
59 short shortValue;
60 std::string* stringValue;
61 } value;
62
63public:
64 Value() {
65 type = UNDEFINED;
66 }
67
68 Value(const Value& other) {
69 copyValue(other);
70 }
71
72 Value& operator=(const Value& other) {
73 clearOldValue();
74 copyValue(other);
75 return *this;
76 }
77
78 ~Value() {
79 clearOldValue();
80 }
81
82 bool getBoolean() const {
83 assertType(BOOLEAN);
84 return value.boolValue;
85 }
86
87 unsigned char getByte() const {
88 assertType(BYTE);
89 return value.byteValue;
90 }
91
92 unsigned short getChar() const {
93 assertType(CHAR);
94 return value.charValue;
95 }
96
97 double getDouble() const {
98 assertType(DOUBLE);
99 return value.doubleValue;
100 }
101
102 float getFloat() const {
103 assertType(FLOAT);
104 return value.floatValue;
105 }
106
107 int getInt() const {
108 assertType(INT);
109 return value.intValue;
110 }
111
112 int getJavaObjectId() const {
113 assertType(JAVA_OBJECT);
114 return value.intValue;
115 }
116
117 int getJsObjectId() const {
118 assertType(JS_OBJECT);
119 return value.intValue;
120 }
121
122 int64_t getLong() const {
123 assertType(LONG);
124 return value.longValue;
125 }
126
127 short getShort() const {
128 assertType(SHORT);
129 return value.shortValue;
130 }
131
132 const std::string getString() const {
133 assertType(STRING);
134 return std::string(*value.stringValue);
135 }
136
137 ValueType getType() const {
138 return type;
139 }
140
141 bool isBoolean() const {
142 return type == BOOLEAN;
143 }
144
145 bool isByte() const {
146 return type == BYTE;
147 }
148
149 bool isChar() const {
150 return type == CHAR;
151 }
152
153 bool isDouble() const {
154 return type == DOUBLE;
155 }
156
157 bool isFloat() const {
158 return type == FLOAT;
159 }
160
161 bool isInt() const {
162 return type == INT;
163 }
164
165 bool isJavaObject() const {
166 return type == JAVA_OBJECT;
167 }
168
169 bool isJsObject() const {
170 return type == JS_OBJECT;
171 }
172
173 bool isLong() const {
174 return type == LONG;
175 }
176
177 bool isNull() const {
178 return type == NULL_TYPE;
179 }
180
181 bool isNumber() const {
182 switch (type) {
183 case BYTE:
184 case CHAR:
185 case DOUBLE:
186 case FLOAT:
187 case INT:
188 case LONG:
189 case SHORT:
190 return true;
191 default:
192 return false;
193 }
194 }
195
196 bool isPrimitive() const {
197 switch (type) {
198 case BOOLEAN:
199 case BYTE:
200 case CHAR:
201 case DOUBLE:
202 case FLOAT:
203 case INT:
204 case LONG:
205 case SHORT:
206 return true;
207 default:
208 return false;
209 }
210 }
211
212 bool isShort() const {
213 return type == SHORT;
214 }
215
216 bool isString() const {
217 return type == STRING;
218 }
219
220 bool isUndefined() const {
221 return type == UNDEFINED;
222 }
223
224 void setBoolean(bool val) {
225 clearOldValue();
226 type = BOOLEAN;
227 value.boolValue = val;
228 }
229
230 void setByte(unsigned char val) {
231 clearOldValue();
232 type = BYTE;
233 value.byteValue = val;
234 }
235
236 void setChar(unsigned short val) {
237 clearOldValue();
238 type = CHAR;
239 value.charValue = val;
240 }
241
242 void setDouble(double val) {
243 clearOldValue();
244 type = DOUBLE;
245 value.doubleValue = val;
246 }
247
jat@google.com2a2909f2010-10-11 18:02:47 +0000248 void setDouble(const double* val) {
249 clearOldValue();
250 type = DOUBLE;
251 value.doubleValue = *val;
252 }
253
jat@google.com134be542009-08-03 15:30:11 +0000254 void setFloat(float val) {
255 clearOldValue();
256 type = FLOAT;
257 value.floatValue = val;
258 }
259
260 void setInt(int val) {
261 clearOldValue();
262 type = INT;
263 value.intValue = val;
264 }
265
266 void setJavaObject(int objectId) {
267 clearOldValue();
268 type = JAVA_OBJECT;
269 value.intValue = objectId;
270 }
271
272 void setJsObjectId(int val) {
273 clearOldValue();
274 type = JS_OBJECT;
275 value.intValue = val;
276 }
277
278 void setLong(int64_t val) {
279 clearOldValue();
280 type = LONG;
281 value.longValue = val;
282 }
283
284 void setNull() {
285 clearOldValue();
286 type = NULL_TYPE;
287 }
288
289 void setShort(short val) {
290 clearOldValue();
291 type = SHORT;
292 value.shortValue = val;
293 }
294
295 void setString(const char* chars, int len) {
296 setString(std::string(chars, len));
297 }
298
299 void setString(const std::string& val) {
300 clearOldValue();
301 type = STRING;
302 value.stringValue = new std::string(val);
303 }
304
305 void setUndefined() {
306 clearOldValue();
307 type = UNDEFINED;
308 }
309
310 std::string toString() const {
scottb@google.com8e71b852009-11-30 22:41:59 +0000311 char buf[64];
jat@google.com134be542009-08-03 15:30:11 +0000312 switch (type) {
313 case NULL_TYPE:
314 return "null";
315 case BOOLEAN:
316 snprintf(buf, sizeof(buf), "boolean(%s)", getBoolean() ? "true"
317 : "false");
318 return std::string(buf);
319 case BYTE:
320 snprintf(buf, sizeof(buf), "byte(%d)", getByte());
321 return std::string(buf);
322 case CHAR:
323 snprintf(buf, sizeof(buf), "char(%d)", getChar());
324 return std::string(buf);
325 case SHORT:
326 snprintf(buf, sizeof(buf), "short(%d)", getShort());
327 return std::string(buf);
328 case INT:
329 snprintf(buf, sizeof(buf), "int(%d)", getInt());
330 return std::string(buf);
331 case LONG:
332 snprintf(buf, sizeof(buf), "long(%lld)",
333 static_cast<long long>(getLong()));
334 return std::string(buf);
335 case FLOAT:
scottb@google.com8e71b852009-11-30 22:41:59 +0000336 snprintf(buf, sizeof(buf), "float(%g)", getFloat());
jat@google.com134be542009-08-03 15:30:11 +0000337 return std::string(buf);
338 case DOUBLE:
scottb@google.com8e71b852009-11-30 22:41:59 +0000339 snprintf(buf, sizeof(buf), "double(%g)", getDouble());
jat@google.com134be542009-08-03 15:30:11 +0000340 return std::string(buf);
341 case STRING:
342 snprintf(buf, sizeof(buf), "string(%.20s)", getString().c_str());
343 return std::string(buf);
344 case JAVA_OBJECT:
345 snprintf(buf, sizeof(buf), "JavaObj(%d)", getJavaObjectId());
346 return std::string(buf);
347 case JS_OBJECT:
348 snprintf(buf, sizeof(buf), "JsObj(%d)", getJsObjectId());
349 return std::string(buf);
350 case UNDEFINED:
351 return "undefined";
352 default:
353 return "Unknown type";
354 }
355 }
356
357private:
358 void assertType(ValueType reqType) const {
359 if (type != reqType) {
360 Debug::log(Debug::Error) << "Value::assertType - expecting type "
361 << int(reqType) << ", was " << int(type) << Debug::flush;
362 // TODO(jat): is this portable? Should we do something else here?
363 abort();
364 }
365 }
366
367 void clearOldValue() {
368 if (type == STRING) {
369 delete value.stringValue;
370 type = UNDEFINED;
371 }
372 }
373
374 // Precondition: existing value, if any, has been cleared
375 void copyValue(const Value& other) {
376 type = other.type;
377 value = other.value;
378 // handle deep copies of value types that need it
379 switch (type) {
380 case STRING:
381 value.stringValue = new std::string(*value.stringValue);
382 break;
383 default:
384 // no other values need deep copies
385 break;
386 }
387 }
388};
389
390inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const Value& val) {
scottb@google.com8e71b852009-11-30 22:41:59 +0000391 if (dbg.isActive()) {
392 dbg << val.toString();
393 }
394 return dbg;
jat@google.com134be542009-08-03 15:30:11 +0000395}
396
acleung@google.comcd201b72012-01-24 16:23:41 +0000397} // namespace gwt
398
jat@google.com134be542009-08-03 15:30:11 +0000399#endif