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#ifndef TOOLS_GN_VALUE_H_
6#define TOOLS_GN_VALUE_H_
7
8#include <map>
9
10#include "base/basictypes.h"
11#include "base/logging.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/strings/string_piece.h"
14#include "tools/gn/err.h"
15
16class ParseNode;
17class Scope;
18
19// Represents a variable value in the interpreter.
20class Value {
21 public:
22  enum Type {
23    NONE = 0,
24    BOOLEAN,
25    INTEGER,
26    STRING,
27    LIST,
28    SCOPE,
29  };
30
31  Value();
32  Value(const ParseNode* origin, Type t);
33  Value(const ParseNode* origin, bool bool_val);
34  Value(const ParseNode* origin, int64 int_val);
35  Value(const ParseNode* origin, std::string str_val);
36  Value(const ParseNode* origin, const char* str_val);
37  // Values "shouldn't" have null scopes when type == Scope, so be sure to
38  // always set one. However, this is not asserted since there are some
39  // use-cases for creating values and immediately setting the scope on it. So
40  // you can pass a null scope here if you promise to set it before any other
41  // code gets it (code will generally assume the scope is not null).
42  Value(const ParseNode* origin, scoped_ptr<Scope> scope);
43
44  Value(const Value& other);
45  ~Value();
46
47  Value& operator=(const Value& other);
48
49  Type type() const { return type_; }
50
51  // Returns a string describing the given type.
52  static const char* DescribeType(Type t);
53
54  // Returns the node that made this. May be NULL.
55  const ParseNode* origin() const { return origin_; }
56  void set_origin(const ParseNode* o) { origin_ = o; }
57
58  bool& boolean_value() {
59    DCHECK(type_ == BOOLEAN);
60    return boolean_value_;
61  }
62  const bool& boolean_value() const {
63    DCHECK(type_ == BOOLEAN);
64    return boolean_value_;
65  }
66
67  int64& int_value() {
68    DCHECK(type_ == INTEGER);
69    return int_value_;
70  }
71  const int64& int_value() const {
72    DCHECK(type_ == INTEGER);
73    return int_value_;
74  }
75
76  std::string& string_value() {
77    DCHECK(type_ == STRING);
78    return string_value_;
79  }
80  const std::string& string_value() const {
81    DCHECK(type_ == STRING);
82    return string_value_;
83  }
84
85  std::vector<Value>& list_value() {
86    DCHECK(type_ == LIST);
87    return list_value_;
88  }
89  const std::vector<Value>& list_value() const {
90    DCHECK(type_ == LIST);
91    return list_value_;
92  }
93
94  Scope* scope_value() {
95    DCHECK(type_ == SCOPE);
96    return scope_value_.get();
97  }
98  const Scope* scope_value() const {
99    DCHECK(type_ == SCOPE);
100    return scope_value_.get();
101  }
102  void SetScopeValue(scoped_ptr<Scope> scope);
103
104  // Converts the given value to a string. Returns true if strings should be
105  // quoted or the ToString of a string should be the string itself. If the
106  // string is quoted, it will also enable escaping.
107  std::string ToString(bool quote_strings) const;
108
109  // Verifies that the value is of the given type. If it isn't, returns
110  // false and sets the error.
111  bool VerifyTypeIs(Type t, Err* err) const;
112
113  // Compares values. Only the "value" is compared, not the origin.
114  bool operator==(const Value& other) const;
115  bool operator!=(const Value& other) const;
116
117 private:
118  // This are a lot of objects associated with every Value that need
119  // initialization and tear down every time. It might be more efficient to
120  // create a union of ManualConstructor objects (see SmallMap) and only
121  // use the one we care about.
122  Type type_;
123  std::string string_value_;
124  bool boolean_value_;
125  int64 int_value_;
126  std::vector<Value> list_value_;
127  scoped_ptr<Scope> scope_value_;
128
129  const ParseNode* origin_;
130};
131
132#endif  // TOOLS_GN_VALUE_H_
133