Home | History | Annotate | Download | only in gn
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "tools/gn/value.h"
      6 
      7 #include "base/strings/string_number_conversions.h"
      8 #include "base/strings/string_util.h"
      9 #include "tools/gn/scope.h"
     10 
     11 Value::Value()
     12     : type_(NONE),
     13       boolean_value_(false),
     14       int_value_(0),
     15       origin_(NULL) {
     16 }
     17 
     18 Value::Value(const ParseNode* origin, Type t)
     19     : type_(t),
     20       boolean_value_(false),
     21       int_value_(0),
     22       origin_(origin) {
     23 }
     24 
     25 Value::Value(const ParseNode* origin, bool bool_val)
     26     : type_(BOOLEAN),
     27       boolean_value_(bool_val),
     28       int_value_(0),
     29       origin_(origin) {
     30 }
     31 
     32 Value::Value(const ParseNode* origin, int64 int_val)
     33     : type_(INTEGER),
     34       boolean_value_(false),
     35       int_value_(int_val),
     36       origin_(origin) {
     37 }
     38 
     39 Value::Value(const ParseNode* origin, std::string str_val)
     40     : type_(STRING),
     41       string_value_(),
     42       boolean_value_(false),
     43       int_value_(0),
     44       origin_(origin) {
     45   string_value_.swap(str_val);
     46 }
     47 
     48 Value::Value(const ParseNode* origin, const char* str_val)
     49     : type_(STRING),
     50       string_value_(str_val),
     51       boolean_value_(false),
     52       int_value_(0),
     53       origin_(origin) {
     54 }
     55 
     56 Value::Value(const ParseNode* origin, scoped_ptr<Scope> scope)
     57     : type_(SCOPE),
     58       string_value_(),
     59       boolean_value_(false),
     60       int_value_(0),
     61       scope_value_(scope.Pass()),
     62       origin_(origin) {
     63 }
     64 
     65 Value::Value(const Value& other)
     66     : type_(other.type_),
     67       string_value_(other.string_value_),
     68       boolean_value_(other.boolean_value_),
     69       int_value_(other.int_value_),
     70       list_value_(other.list_value_),
     71       origin_(other.origin_) {
     72   if (type() == SCOPE && other.scope_value_.get())
     73     scope_value_ = other.scope_value_->MakeClosure();
     74 }
     75 
     76 Value::~Value() {
     77 }
     78 
     79 Value& Value::operator=(const Value& other) {
     80   type_ = other.type_;
     81   string_value_ = other.string_value_;
     82   boolean_value_ = other.boolean_value_;
     83   int_value_ = other.int_value_;
     84   list_value_ = other.list_value_;
     85   if (type() == SCOPE && other.scope_value_.get())
     86     scope_value_ = other.scope_value_->MakeClosure();
     87   origin_ = other.origin_;
     88   return *this;
     89 }
     90 
     91 // static
     92 const char* Value::DescribeType(Type t) {
     93   switch (t) {
     94     case NONE:
     95       return "none";
     96     case BOOLEAN:
     97       return "boolean";
     98     case INTEGER:
     99       return "integer";
    100     case STRING:
    101       return "string";
    102     case LIST:
    103       return "list";
    104     case SCOPE:
    105       return "scope";
    106     default:
    107       NOTREACHED();
    108       return "UNKNOWN";
    109   }
    110 }
    111 
    112 void Value::SetScopeValue(scoped_ptr<Scope> scope) {
    113   DCHECK(type_ == SCOPE);
    114   scope_value_ = scope.Pass();
    115 }
    116 
    117 std::string Value::ToString(bool quote_string) const {
    118   switch (type_) {
    119     case NONE:
    120       return "<void>";
    121     case BOOLEAN:
    122       return boolean_value_ ? "true" : "false";
    123     case INTEGER:
    124       return base::Int64ToString(int_value_);
    125     case STRING:
    126       if (quote_string) {
    127         std::string escaped = string_value_;
    128         // First escape all special uses of a backslash.
    129         ReplaceSubstringsAfterOffset(&escaped, 0, "\\$", "\\\\$");
    130         ReplaceSubstringsAfterOffset(&escaped, 0, "\\\"", "\\\\\"");
    131 
    132         // Now escape special chars.
    133         ReplaceSubstringsAfterOffset(&escaped, 0, "$", "\\$");
    134         ReplaceSubstringsAfterOffset(&escaped, 0, "\"", "\\\"");
    135         return "\"" + escaped + "\"";
    136       }
    137       return string_value_;
    138     case LIST: {
    139       std::string result = "[";
    140       for (size_t i = 0; i < list_value_.size(); i++) {
    141         if (i > 0)
    142           result += ", ";
    143         result += list_value_[i].ToString(true);
    144       }
    145       result.push_back(']');
    146       return result;
    147     }
    148     case SCOPE: {
    149       Scope::KeyValueMap scope_values;
    150       scope_value_->GetCurrentScopeValues(&scope_values);
    151       if (scope_values.empty())
    152         return std::string("{ }");
    153 
    154       std::string result = "{\n";
    155       for (Scope::KeyValueMap::const_iterator i = scope_values.begin();
    156            i != scope_values.end(); ++i) {
    157         result += "  " + i->first.as_string() + " = " +
    158                   i->second.ToString(true) + "\n";
    159       }
    160       result += "}";
    161 
    162       return result;
    163     }
    164   }
    165   return std::string();
    166 }
    167 
    168 bool Value::VerifyTypeIs(Type t, Err* err) const {
    169   if (type_ == t)
    170     return true;
    171 
    172   *err = Err(origin(),
    173              std::string("This is not a ") + DescribeType(t) + ".",
    174              std::string("Instead I see a ") + DescribeType(type_) + " = " +
    175              ToString(true));
    176   return false;
    177 }
    178 
    179 bool Value::operator==(const Value& other) const {
    180   if (type_ != other.type_)
    181     return false;
    182 
    183   switch (type_) {
    184     case Value::BOOLEAN:
    185       return boolean_value() == other.boolean_value();
    186     case Value::INTEGER:
    187       return int_value() == other.int_value();
    188     case Value::STRING:
    189       return string_value() == other.string_value();
    190     case Value::LIST:
    191       if (list_value().size() != other.list_value().size())
    192         return false;
    193       for (size_t i = 0; i < list_value().size(); i++) {
    194         if (list_value()[i] != other.list_value()[i])
    195           return false;
    196       }
    197       return true;
    198     case Value::SCOPE:
    199       // Scopes are always considered not equal because there's currently
    200       // no use case for comparing them, and it requires a bunch of complex
    201       // iteration code.
    202       return false;
    203     default:
    204       return false;
    205   }
    206 }
    207 
    208 bool Value::operator!=(const Value& other) const {
    209   return !operator==(other);
    210 }
    211