"Fossies" - the Fresh Open Source Software Archive

Member "google-gadgets-for-linux-0.11.2/ggadget/variant.cc" (6 Jan 2010, 14752 Bytes) of package /linux/misc/old/google-gadgets-for-linux-0.11.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2   Copyright 2008 Google Inc.
    3 
    4   Licensed under the Apache License, Version 2.0 (the "License");
    5   you may not use this file except in compliance with the License.
    6   You may obtain a copy of the License at
    7 
    8        http://www.apache.org/licenses/LICENSE-2.0
    9 
   10   Unless required by applicable law or agreed to in writing, software
   11   distributed under the License is distributed on an "AS IS" BASIS,
   12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13   See the License for the specific language governing permissions and
   14   limitations under the License.
   15 */
   16 
   17 #include <cmath>
   18 #include <cstring>
   19 #include <cstdlib>
   20 #include "variant.h"
   21 #include "logger.h"
   22 #include "scriptable_interface.h"
   23 #include "signals.h"
   24 #include "slot.h"
   25 #include "string_utils.h"
   26 
   27 namespace ggadget {
   28 
   29 // The values doesn't matter, because we only use their c_str() result to
   30 // check if a string is constructed from these "NULL" strings.
   31 // We choose the value "(nil)" to ease printing (see Print()).
   32 // Don't use blank value, because all strings with blank values are shared
   33 // in the standard impl of C++ library.
   34 const std::string Variant::kNullString("(nil)");
   35 static const UTF16Char kNullUTF16StringValue[] =
   36     { '(', 'n', 'i', 'l', ')', 0 };
   37 const UTF16String Variant::kNullUTF16String(kNullUTF16StringValue);
   38 
   39 Variant::Variant() : type_(TYPE_VOID) {
   40   memset(&v_, 0, sizeof(v_));
   41 }
   42 
   43 Variant::Variant(const Variant &source) : type_(TYPE_VOID) {
   44   memset(&v_, 0, sizeof(v_));
   45   operator=(source);
   46 }
   47 
   48 Variant::Variant(const ResultVariant &source) : type_(TYPE_VOID) {
   49   memset(&v_, 0, sizeof(v_));
   50   operator=(source.v());
   51 }
   52 
   53 Variant::Variant(Type type) : type_(type) {
   54   if (type_ == TYPE_STRING || type_ == TYPE_JSON) {
   55     new (&v_.string_place_) std::string(kNullString);
   56   } else if (type_ == TYPE_UTF16STRING) {
   57     new (&v_.utf16_string_place_) UTF16String(kNullUTF16String);
   58   } else {
   59     memset(&v_, 0, sizeof(v_));
   60   }
   61 }
   62 
   63 Variant::~Variant() {
   64   if (type_ == TYPE_STRING || type_ == TYPE_JSON) {
   65     // This typedef is required because ...~std::string() may cause error.
   66     typedef std::string String;
   67     // Don't delete because the pointer is allocated in place.
   68     void *data = v_.string_place_;
   69     reinterpret_cast<String *>(data)->~String();
   70   } else if (type_ == TYPE_UTF16STRING) {
   71     // Don't delete because the pointer is allocated in place.
   72     void *data = v_.utf16_string_place_;
   73     reinterpret_cast<UTF16String *>(data)->~UTF16String();
   74   }
   75 }
   76 
   77 Variant &Variant::operator=(const Variant &source) {
   78   if (&source == this)
   79     return *this;
   80 
   81   if (type_ == TYPE_STRING || type_ == TYPE_JSON) {
   82     // This typedef is required because ...~std::string() may cause error.
   83     typedef std::string String;
   84     // Don't delete because the pointer is allocated in place.
   85     void *data = v_.string_place_;
   86     reinterpret_cast<String *>(data)->~String();
   87   } else if (type_ == TYPE_UTF16STRING) {
   88     // Don't delete because the pointer is allocated in place.
   89     void *data = v_.utf16_string_place_;
   90     reinterpret_cast<UTF16String *>(data)->~UTF16String();
   91   }
   92 
   93   type_ = source.type_;
   94   const void *data = source.v_.string_place_;
   95   switch (type_) {
   96     case TYPE_VOID:
   97       break;
   98     case TYPE_BOOL:
   99       v_.bool_value_ = source.v_.bool_value_;
  100       break;
  101     case TYPE_INT64:
  102       v_.int64_value_ = source.v_.int64_value_;
  103       break;
  104     case TYPE_DOUBLE:
  105       v_.double_value_ = source.v_.double_value_;
  106       break;
  107     case TYPE_STRING:
  108     case TYPE_JSON:
  109       new (&v_.string_place_) std::string(
  110           *reinterpret_cast<const std::string *>(data));
  111       break;
  112     case TYPE_UTF16STRING:
  113       new (&v_.utf16_string_place_) UTF16String(
  114        *reinterpret_cast<const UTF16String *>(data));
  115       break;
  116     case TYPE_SCRIPTABLE:
  117       v_.scriptable_value_ = source.v_.scriptable_value_;
  118       break;
  119     case TYPE_SLOT:
  120       v_.slot_value_ = source.v_.slot_value_;
  121       break;
  122     case TYPE_DATE:
  123       v_.int64_value_ = source.v_.int64_value_;
  124       break;
  125     case TYPE_ANY:
  126       v_.any_value_ = source.v_.any_value_;
  127       break;
  128     case TYPE_CONST_ANY:
  129       v_.const_any_value_ = source.v_.const_any_value_;
  130       break;
  131     case TYPE_VARIANT:
  132       // A Variant of type TYPE_VARIANT is only used as a prototype.
  133       break;
  134     default:
  135       break;
  136   }
  137   return *this;
  138 }
  139 
  140 bool Variant::operator==(const Variant &another) const {
  141   if (type_ != another.type_)
  142     return false;
  143 
  144   switch (type_) {
  145     case TYPE_VOID:
  146       return true;
  147     case TYPE_BOOL:
  148       return v_.bool_value_ == another.v_.bool_value_;
  149     case TYPE_INT64:
  150       return v_.int64_value_ == another.v_.int64_value_;
  151     case TYPE_DOUBLE:
  152       return v_.double_value_ == another.v_.double_value_;
  153     case TYPE_STRING: {
  154       const char *s1 = VariantValue<const char *>()(*this);
  155       const char *s2 = VariantValue<const char *>()(another);
  156       return (s1 == s2 || (s1 && s2 && strcmp(s1, s2) == 0));
  157     }
  158     case TYPE_JSON:
  159       return VariantValue<JSONString>()(*this) ==
  160              VariantValue<JSONString>()(another);
  161     case TYPE_UTF16STRING: {
  162       const UTF16Char *s1 = VariantValue<const UTF16Char *>()(*this);
  163       const UTF16Char *s2 = VariantValue<const UTF16Char *>()(another);
  164       return (s1 == s2 || (s1 && s2 && VariantValue<UTF16String>()(*this) ==
  165                                        VariantValue<UTF16String>()(another)));
  166     }
  167     case TYPE_SCRIPTABLE:
  168       return v_.scriptable_value_ == another.v_.scriptable_value_;
  169     case TYPE_SLOT: {
  170       Slot *slot1 = v_.slot_value_;
  171       Slot *slot2 = another.v_.slot_value_;
  172       return slot1 == slot2 || (slot1 && slot2 && *slot1 == *slot2);
  173     }
  174     case TYPE_DATE:
  175       return v_.int64_value_ == another.v_.int64_value_;
  176     case TYPE_ANY:
  177       return v_.any_value_ == another.v_.any_value_;
  178     case TYPE_CONST_ANY:
  179       return v_.const_any_value_ == another.v_.const_any_value_;
  180     case TYPE_VARIANT:
  181       // A Variant of type TYPE_VARIANT is only used as a prototype,
  182       // so they are all equal.
  183       return true;
  184     default:
  185       return false;
  186   }
  187 }
  188 
  189 static std::string FitString(const std::string &input) {
  190   return input.size() > 70 ? input.substr(0, 70) + "..." : input;
  191 }
  192 
  193 // Used in unittests.
  194 std::string Variant::Print() const {
  195   const void *data = v_.string_place_;
  196   switch (type_) {
  197     case TYPE_VOID:
  198       return "VOID";
  199     case TYPE_BOOL:
  200       return std::string("BOOL:") + (v_.bool_value_ ? "true" : "false");
  201     case TYPE_INT64:
  202       return "INT64:" + StringPrintf("%jd", v_.int64_value_);
  203     case TYPE_DOUBLE:
  204       return "DOUBLE:" + StringPrintf("%g", v_.double_value_);
  205     case TYPE_STRING:
  206       return std::string("STRING:") +
  207          // Print "(nil)" for NULL string pointer.
  208          FitString(*reinterpret_cast<const std::string *>(data));
  209     case TYPE_JSON:
  210       return std::string("JSON:") +
  211              FitString(VariantValue<JSONString>()(*this).value);
  212     case TYPE_UTF16STRING: {
  213       std::string utf8_string;
  214       ConvertStringUTF16ToUTF8(
  215           // Print "(nil)" for NULL string pointer.
  216           *reinterpret_cast<const UTF16String *>(data),
  217           &utf8_string);
  218       return "UTF16STRING:" + FitString(utf8_string);
  219     }
  220     case TYPE_SCRIPTABLE:
  221       return StringPrintf("SCRIPTABLE:%p(CLASS_ID=%jx)",
  222                           v_.scriptable_value_,
  223                           v_.scriptable_value_ ?
  224                               v_.scriptable_value_->GetClassId() : 0);
  225     case TYPE_SLOT:
  226       return StringPrintf("SLOT:%p", v_.slot_value_);
  227     case TYPE_DATE:
  228       return StringPrintf("DATE:%ju", v_.int64_value_);
  229     case TYPE_ANY:
  230       return StringPrintf("ANY:%p", v_.any_value_);
  231     case TYPE_CONST_ANY:
  232       return StringPrintf("ANY:%p", v_.const_any_value_);
  233     case TYPE_VARIANT:
  234       return "VARIANT";
  235     default:
  236       return "INVALID";
  237   }
  238 }
  239 
  240 bool Variant::ConvertToString(std::string *result) const {
  241   ASSERT(result);
  242   switch (type_) {
  243     case TYPE_VOID:
  244       *result = "";
  245       return true;
  246     case TYPE_BOOL:
  247       *result = v_.bool_value_ ? "true" : "false";
  248       return true;
  249     case TYPE_INT64:
  250       *result = StringPrintf("%jd", v_.int64_value_);
  251       return true;
  252     case TYPE_DOUBLE:
  253       *result = StringPrintf("%g", v_.double_value_);
  254       return true;
  255     case TYPE_STRING:
  256       *result = VariantValue<std::string>()(*this);
  257       return true;
  258     case TYPE_JSON:
  259       return false;
  260     case TYPE_UTF16STRING:
  261       ConvertStringUTF16ToUTF8(VariantValue<UTF16String>()(*this), result);
  262       return true;
  263     case TYPE_SCRIPTABLE:
  264     case TYPE_SLOT:
  265     case TYPE_DATE:
  266     case TYPE_ANY:
  267     case TYPE_CONST_ANY:
  268     case TYPE_VARIANT:
  269     default:
  270       return false;
  271   }
  272 }
  273 
  274 static bool ParseStringToBool(const char *str_value, bool *result) {
  275   if (!*str_value || GadgetStrCmp(str_value, "false") == 0) {
  276     *result = false;
  277     return true;
  278   }
  279   if (GadgetStrCmp(str_value, "true") == 0) {
  280     *result = true;
  281     return true;
  282   }
  283   return false;
  284 }
  285 
  286 bool Variant::ConvertToBool(bool *result) const {
  287   ASSERT(result);
  288   switch (type_) {
  289     case TYPE_VOID:
  290       *result = false;
  291       return true;
  292     case TYPE_BOOL:
  293       *result = v_.bool_value_;
  294       return true;
  295     case TYPE_INT64:
  296       *result = v_.int64_value_ != 0;
  297       return true;
  298     case TYPE_DOUBLE:
  299       *result = v_.double_value_ != 0;
  300       return true;
  301     case TYPE_STRING:
  302       return ParseStringToBool(VariantValue<std::string>()(*this).c_str(),
  303                                result);
  304     case TYPE_JSON:
  305       return false;
  306     case TYPE_UTF16STRING: {
  307       std::string s;
  308       ConvertStringUTF16ToUTF8(VariantValue<UTF16String>()(*this), &s);
  309       return ParseStringToBool(s.c_str(), result);
  310     }
  311     case TYPE_SCRIPTABLE:
  312       *result = v_.scriptable_value_ != NULL;
  313       return true;
  314     case TYPE_SLOT:
  315       *result = v_.slot_value_ != NULL;
  316       return true;
  317     case TYPE_DATE:
  318       *result = true;
  319       return true;
  320     case TYPE_ANY:
  321       *result = v_.any_value_ != NULL;
  322       return true;
  323     case TYPE_CONST_ANY:
  324       *result = v_.const_any_value_ != NULL;
  325       return true;
  326     case TYPE_VARIANT:
  327     default:
  328       return false;
  329   }
  330 }
  331 
  332 bool Variant::ConvertToInt(int *result) const {
  333   int64_t i;
  334   if (ConvertToInt64(&i)) {
  335     *result = static_cast<int>(i);
  336     return true;
  337   }
  338   return false;
  339 }
  340 
  341 static bool ParseStringToDouble(const char *str_value, double *result) {
  342   char *end_ptr;
  343   // We don't allow hexidecimal floating-point numbers or INFINITY or NAN.
  344   if (strchr(str_value, 'x') || strchr(str_value, 'X') ||
  345       strchr(str_value, 'n') || strchr(str_value, 'N'))
  346     return false;
  347 
  348   double d = strtod(str_value, &end_ptr);
  349   // Allow space after double number.
  350   while(*end_ptr == ' ') ++end_ptr;
  351   if (*end_ptr == '\0') {
  352     *result = d;
  353     return true;
  354   }
  355   return false;
  356 }
  357 
  358 static bool ParseStringToInt64(const char *str_value, int64_t *result) {
  359   char *end_ptr;
  360   // TODO: Check if strtoll is available
  361   int64_t i = static_cast<int64_t>(strtoll(str_value, &end_ptr, 10));
  362   // Allow space after int64 number.
  363   while(*end_ptr == ' ') ++end_ptr;
  364   if (*end_ptr == '\0') {
  365     *result = i;
  366     return true;
  367   }
  368   // Then try to parse double.
  369   double d;
  370   if (ParseStringToDouble(str_value, &d)) {
  371     *result = static_cast<int64_t>(round(d));
  372     return true;
  373   }
  374   return false;
  375 }
  376 
  377 bool Variant::ConvertToInt64(int64_t *result) const {
  378   ASSERT(result);
  379   switch (type_) {
  380     case TYPE_VOID:
  381       return false;
  382     case TYPE_BOOL:
  383       *result = v_.bool_value_ ? 1 : 0;
  384       return true;
  385     case TYPE_INT64:
  386       *result = v_.int64_value_;
  387       return true;
  388     case TYPE_DOUBLE:
  389       *result = static_cast<int64_t>(v_.double_value_);
  390       return true;
  391     case TYPE_STRING:
  392       return ParseStringToInt64(VariantValue<std::string>()(*this).c_str(),
  393                                 result);
  394     case TYPE_JSON:
  395       return false;
  396     case TYPE_UTF16STRING: {
  397       std::string s;
  398       ConvertStringUTF16ToUTF8(VariantValue<UTF16String>()(*this), &s);
  399       return ParseStringToInt64(s.c_str(), result);
  400     }
  401     case TYPE_SCRIPTABLE:
  402     case TYPE_SLOT:
  403     case TYPE_DATE:
  404     case TYPE_ANY:
  405     case TYPE_CONST_ANY:
  406     case TYPE_VARIANT:
  407     default:
  408       return false;
  409   }
  410 }
  411 
  412 bool Variant::ConvertToDouble(double *result) const {
  413   ASSERT(result);
  414   switch (type_) {
  415     case TYPE_VOID:
  416       return false;
  417     case TYPE_BOOL:
  418       *result = v_.bool_value_ ? 1 : 0;
  419       return true;
  420     case TYPE_INT64:
  421       *result = static_cast<double>(v_.int64_value_);
  422       return true;
  423     case TYPE_DOUBLE:
  424       *result = v_.double_value_;
  425       return true;
  426     case TYPE_STRING:
  427       return ParseStringToDouble(VariantValue<std::string>()(*this).c_str(),
  428                                  result);
  429     case TYPE_JSON:
  430       return false;
  431     case TYPE_UTF16STRING: {
  432       std::string s;
  433       ConvertStringUTF16ToUTF8(VariantValue<UTF16String>()(*this), &s);
  434       return ParseStringToDouble(s.c_str(), result);
  435     }
  436     case TYPE_SCRIPTABLE:
  437     case TYPE_SLOT:
  438     case TYPE_DATE:
  439     case TYPE_ANY:
  440     case TYPE_CONST_ANY:
  441     case TYPE_VARIANT:
  442     default:
  443       return false;
  444   }
  445 }
  446 
  447 bool Variant::CheckScriptableType(uint64_t class_id) const {
  448   ASSERT(type_ == TYPE_SCRIPTABLE);
  449   if (v_.scriptable_value_ &&
  450       !v_.scriptable_value_->IsInstanceOf(class_id)) {
  451     LOG("The parameter is not an instance pointer of 0x%jx", class_id);
  452     return false;
  453   }
  454   return true;
  455 }
  456 
  457 ResultVariant::ResultVariant(const Variant &v)
  458     : v_(v) {
  459   if (v_.type() == Variant::TYPE_SCRIPTABLE) {
  460     ScriptableInterface *scriptable =
  461         VariantValue<ScriptableInterface *>()(v_);
  462     if (scriptable)
  463       scriptable->Ref();
  464   }
  465 }
  466 
  467 ResultVariant::ResultVariant(const ResultVariant &v)
  468     : v_(v.v_) {
  469   if (v_.type() == Variant::TYPE_SCRIPTABLE) {
  470     ScriptableInterface *scriptable =
  471         VariantValue<ScriptableInterface *>()(v_);
  472     if (scriptable)
  473       scriptable->Ref();
  474   }
  475 }
  476 
  477 ResultVariant::~ResultVariant() {
  478   if (v_.type() == Variant::TYPE_SCRIPTABLE) {
  479     ScriptableInterface *scriptable =
  480         VariantValue<ScriptableInterface *>()(v_);
  481     if (scriptable)
  482       scriptable->Unref();
  483   }
  484 }
  485 
  486 ResultVariant &ResultVariant::operator=(const ResultVariant &v) {
  487   if (&v == this)
  488     return *this;
  489 
  490   if (v_.type() == Variant::TYPE_SCRIPTABLE) {
  491     ScriptableInterface *scriptable =
  492         VariantValue<ScriptableInterface *>()(v_);
  493     if (scriptable)
  494       scriptable->Unref();
  495   }
  496   v_ = v.v_;
  497   if (v_.type() == Variant::TYPE_SCRIPTABLE) {
  498     ScriptableInterface *scriptable =
  499         VariantValue<ScriptableInterface *>()(v_);
  500     if (scriptable)
  501       scriptable->Ref();
  502   }
  503   return *this;
  504 }
  505 
  506 } // namespace ggadget