Initial checkin of OOPHM plugins into trunk.  Testing of non-XPCOM plugins
is still required, and more platforms need to be built.


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5868 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/plugins/common/Value.h b/plugins/common/Value.h
new file mode 100644
index 0000000..4401893
--- /dev/null
+++ b/plugins/common/Value.h
@@ -0,0 +1,387 @@
+#ifndef _H_Value
+#define _H_Value
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#ifndef _WINDOWS
+// TODO(jat): remove; for abort() which should probably go away
+#include <stdlib.h>
+#endif
+
+#include <string>
+
+#include "Debug.h"
+
+#include "BrowserChannel.h"
+
+class Value {
+public:
+  enum ValueType {
+    NULL_TYPE = VALUE_TYPE_NULL,
+    BOOLEAN = VALUE_TYPE_BOOLEAN,
+    BYTE = VALUE_TYPE_BYTE,
+    CHAR = VALUE_TYPE_CHAR,
+    SHORT = VALUE_TYPE_SHORT,
+    INT = VALUE_TYPE_INT,
+    LONG = VALUE_TYPE_LONG,
+    FLOAT = VALUE_TYPE_FLOAT,
+    DOUBLE = VALUE_TYPE_DOUBLE,
+    STRING = VALUE_TYPE_STRING,
+    JAVA_OBJECT = VALUE_TYPE_JAVA_OBJECT,
+    JS_OBJECT = VALUE_TYPE_JS_OBJECT,
+    UNDEFINED = VALUE_TYPE_UNDEFINED
+  };
+
+private:
+  ValueType type;
+  union {
+    bool  boolValue;
+    unsigned char byteValue;
+    unsigned short charValue;
+    double doubleValue;
+    float floatValue;
+    int32_t intValue;
+    int64_t longValue;
+    short shortValue;
+    std::string* stringValue;
+  } value;
+
+public:
+  Value() {
+    type = UNDEFINED;
+  }
+
+  Value(const Value& other) {
+    copyValue(other);
+  }
+
+  Value& operator=(const Value& other) {
+    clearOldValue();
+    copyValue(other);
+    return *this;
+  }
+
+  ~Value() {
+    clearOldValue();
+  }
+
+  bool getBoolean() const {
+    assertType(BOOLEAN);
+    return value.boolValue;
+  }
+
+  unsigned char getByte() const {
+    assertType(BYTE);
+    return value.byteValue;
+  }
+
+  unsigned short getChar() const {
+    assertType(CHAR);
+    return value.charValue;
+  }
+
+  double getDouble() const {
+    assertType(DOUBLE);
+    return value.doubleValue;
+  }
+
+  float getFloat() const {
+    assertType(FLOAT);
+    return value.floatValue;
+  }
+
+  int getInt() const {
+    assertType(INT);
+    return value.intValue;
+  }
+
+  int getJavaObjectId() const {
+    assertType(JAVA_OBJECT);
+    return value.intValue;
+  }
+
+  int getJsObjectId() const {
+    assertType(JS_OBJECT);
+    return value.intValue;
+  }
+
+  int64_t getLong() const {
+    assertType(LONG);
+    return value.longValue;
+  }
+
+  short getShort() const {
+    assertType(SHORT);
+    return value.shortValue;
+  }
+
+  const std::string getString() const {
+    assertType(STRING);
+    return std::string(*value.stringValue);
+  }
+
+  ValueType getType() const {
+    return type;
+  }
+
+  bool isBoolean() const {
+    return type == BOOLEAN;
+  }
+
+  bool isByte() const {
+    return type == BYTE;
+  }
+
+  bool isChar() const {
+    return type == CHAR;
+  }
+
+  bool isDouble() const {
+    return type == DOUBLE;
+  }
+
+  bool isFloat() const {
+    return type == FLOAT;
+  }
+
+  bool isInt() const {
+    return type == INT;
+  }
+
+  bool isJavaObject() const {
+    return type == JAVA_OBJECT;
+  }
+
+  bool isJsObject() const {
+    return type == JS_OBJECT;
+  }
+
+  bool isLong() const {
+    return type == LONG;
+  }
+
+  bool isNull() const {
+    return type == NULL_TYPE;
+  }
+
+  bool isNumber() const {
+    switch (type) {
+      case BYTE:
+      case CHAR:
+      case DOUBLE:
+      case FLOAT:
+      case INT:
+      case LONG:
+      case SHORT:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  bool isPrimitive() const {
+    switch (type) {
+      case BOOLEAN:
+      case BYTE:
+      case CHAR:
+      case DOUBLE:
+      case FLOAT:
+      case INT:
+      case LONG:
+      case SHORT:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  bool isShort() const {
+    return type == SHORT;
+  }
+
+  bool isString() const {
+    return type == STRING;
+  }
+
+  bool isUndefined() const {
+    return type == UNDEFINED;
+  }
+
+  void setBoolean(bool val) {
+    clearOldValue();
+    type = BOOLEAN;
+    value.boolValue = val;
+  }
+
+  void setByte(unsigned char val) {
+    clearOldValue();
+    type = BYTE;
+    value.byteValue = val;
+  }
+
+  void setChar(unsigned short val) {
+    clearOldValue();
+    type = CHAR;
+    value.charValue = val;
+  }
+
+  void setDouble(double val) {
+    clearOldValue();
+    type = DOUBLE;
+    value.doubleValue = val;
+  }
+
+  void setFloat(float val) {
+    clearOldValue();
+    type = FLOAT;
+    value.floatValue = val;
+  }
+
+  void setInt(int val) {
+    clearOldValue();
+    type = INT;
+    value.intValue = val;
+  }
+
+  void setJavaObject(int objectId) {
+    clearOldValue();
+    type = JAVA_OBJECT;
+    value.intValue = objectId;
+  }
+
+  void setJsObjectId(int val) {
+    clearOldValue();
+    type = JS_OBJECT;
+    value.intValue = val;
+  }
+
+  void setLong(int64_t val) {
+    clearOldValue();
+    type = LONG;
+    value.longValue = val;
+  }
+
+  void setNull() {
+    clearOldValue();
+    type = NULL_TYPE;
+  }
+
+  void setShort(short val) {
+    clearOldValue();
+    type = SHORT;
+    value.shortValue = val;
+  }
+
+  void setString(const char* chars, int len) {
+    setString(std::string(chars, len));
+  }
+
+  void setString(const std::string& val) {
+    clearOldValue();
+    type = STRING;
+    value.stringValue = new std::string(val);
+  }
+
+  void setUndefined() {
+    clearOldValue();
+    type = UNDEFINED;
+  }
+
+  std::string toString() const {
+    char buf[30];
+    switch (type) {
+      case NULL_TYPE:
+        return "null";
+      case BOOLEAN:
+        snprintf(buf, sizeof(buf), "boolean(%s)", getBoolean() ? "true"
+            : "false");
+        return std::string(buf);
+      case BYTE:
+        snprintf(buf, sizeof(buf), "byte(%d)", getByte());
+        return std::string(buf);
+      case CHAR:
+        snprintf(buf, sizeof(buf), "char(%d)", getChar());
+        return std::string(buf);
+      case SHORT:
+        snprintf(buf, sizeof(buf), "short(%d)", getShort());
+        return std::string(buf);
+      case INT:
+        snprintf(buf, sizeof(buf), "int(%d)", getInt());
+        return std::string(buf);
+      case LONG:
+        snprintf(buf, sizeof(buf), "long(%lld)",
+            static_cast<long long>(getLong()));
+        return std::string(buf);
+      case FLOAT:
+        snprintf(buf, sizeof(buf), "float(%f)", getFloat());
+        return std::string(buf);
+      case DOUBLE:
+        snprintf(buf, sizeof(buf), "double(%lf)", getDouble());
+        return std::string(buf);
+      case STRING:
+        snprintf(buf, sizeof(buf), "string(%.20s)", getString().c_str());
+        return std::string(buf);
+      case JAVA_OBJECT:
+        snprintf(buf, sizeof(buf), "JavaObj(%d)", getJavaObjectId());
+        return std::string(buf);
+      case JS_OBJECT:
+        snprintf(buf, sizeof(buf), "JsObj(%d)", getJsObjectId());
+        return std::string(buf);
+      case UNDEFINED:
+        return "undefined";
+      default:
+        return "Unknown type";
+    }
+  }
+
+private:
+  void assertType(ValueType reqType) const {
+    if (type != reqType) {
+      Debug::log(Debug::Error) << "Value::assertType - expecting type "
+          << int(reqType) << ", was " << int(type) << Debug::flush;
+      // TODO(jat): is this portable?  Should we do something else here?
+      abort();
+    }
+  }
+
+  void clearOldValue() {
+    if (type == STRING) {
+      delete value.stringValue;
+      type = UNDEFINED;
+    }
+  }
+
+  // Precondition: existing value, if any, has been cleared
+  void copyValue(const Value& other) {
+    type = other.type;
+    value = other.value;
+    // handle deep copies of value types that need it
+    switch (type) {
+      case STRING:
+        value.stringValue = new std::string(*value.stringValue);
+        break;
+      default:
+        // no other values need deep copies
+        break;
+    }
+  }
+};
+
+inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const Value& val) {
+  return dbg << val.toString();
+}
+
+#endif