summaryrefslogtreecommitdiffstats
path: root/ppapi/cpp/var.h
blob: 0fdd5f542f9c65beff539fd30de7800d8f4ef7d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef PPAPI_CPP_VAR_H_
#define PPAPI_CPP_VAR_H_

#include <string>
#include <vector>

#include "ppapi/c/pp_module.h"
#include "ppapi/c/pp_var.h"

namespace pp {

class Instance;

namespace deprecated {
class ScriptableObject;
}

class Var {
 public:
  struct Null {};  // Special value passed to constructor to make NULL.

  Var();  // PP_Var of type Undefined.
  Var(Null);  // PP_Var of type Null.
  Var(bool b);
  Var(int32_t i);
  Var(double d);
  Var(const char* utf8_str);  // Must be encoded in UTF-8.
  Var(const std::string& utf8_str);  // Must be encoded in UTF-8.

  // This magic constructor is used when we've gotten a PP_Var as a return
  // value that has already been addref'ed for us.
  struct PassRef {};
  Var(PassRef, PP_Var var) {
    var_ = var;
    needs_release_ = true;
  }

  // TODO(brettw): remove DontManage when this bug is fixed
  //               http://code.google.com/p/chromium/issues/detail?id=52105
  // This magic constructor is used when we've given a PP_Var as an input
  // argument from somewhere and that reference is managing the reference
  // count for us. The object will not be AddRef'ed or Release'd by this
  // class instance..
  struct DontManage {};
  Var(DontManage, PP_Var var) {
    var_ = var;
    needs_release_ = false;
  }

  // Takes ownership of the given pointer.
  Var(Instance* instance, deprecated::ScriptableObject* object);

  // TODO(brettw) erase this! This is a temporary hack to keep the build
  // going while we land the nacl side of this change. Calling this function
  // will crash rather than break the compile.
  Var(deprecated::ScriptableObject* /* object */) {
    *(int*)0 = 3;
  }

  Var(const Var& other);

  virtual ~Var();

  Var& operator=(const Var& other);

  bool operator==(const Var& other) const;

  bool is_undefined() const { return var_.type == PP_VARTYPE_UNDEFINED; }
  bool is_null() const { return var_.type == PP_VARTYPE_NULL; }
  bool is_bool() const { return var_.type == PP_VARTYPE_BOOL; }
  bool is_string() const { return var_.type == PP_VARTYPE_STRING; }
  bool is_object() const { return var_.type == PP_VARTYPE_OBJECT; }

  // IsInt and IsDouble return the internal representation. The JavaScript
  // runtime may convert between the two as needed, so the distinction may
  // not be relevant in all cases (int is really an optimization inside the
  // runtime). So most of the time, you will want to check IsNumber.
  bool is_int() const { return var_.type == PP_VARTYPE_INT32; }
  bool is_double() const { return var_.type == PP_VARTYPE_DOUBLE; }
  bool is_number() const {
    return var_.type == PP_VARTYPE_INT32 ||
           var_.type == PP_VARTYPE_DOUBLE;
  }

  // Assumes the internal representation IsBool. If it's not, it will assert
  // in debug mode, and return false.
  bool AsBool() const;

  // AsInt and AsDouble implicitly convert between ints and doubles. This is
  // because JavaScript doesn't have a concept of ints and doubles, only
  // numbers. The distinction between the two is an optimization inside the
  // compiler. Since converting from a double to an int may be lossy, if you
  // care about the distinction, either always work in doubles, or check
  // !IsDouble() before calling AsInt().
  //
  // These functions will assert in debug mode and return 0 if the internal
  // representation is not IsNumber().
  int32_t AsInt() const;
  double AsDouble() const;

  // This assumes the object is of type string. If it's not, it will assert
  // in debug mode, and return an empty string.
  std::string AsString() const;

  // This assumes the object is of type object. If it's not, it will assert in
  // debug mode. If it is not an object or not a ScriptableObject type, returns
  // NULL.
  deprecated::ScriptableObject* AsScriptableObject() const;

  bool HasProperty(const Var& name, Var* exception = NULL) const;
  bool HasMethod(const Var& name, Var* exception = NULL) const;
  Var GetProperty(const Var& name, Var* exception = NULL) const;
  void GetAllPropertyNames(std::vector<Var>* properties,
                           Var* exception = NULL) const;
  void SetProperty(const Var& name, const Var& value, Var* exception = NULL);
  void RemoveProperty(const Var& name, Var* exception = NULL);
  Var Call(const Var& method_name, uint32_t argc, Var* argv,
           Var* exception = NULL);
  Var Construct(uint32_t argc, Var* argv, Var* exception = NULL) const;

  // Convenience functions for calling functions with small # of args.
  Var Call(const Var& method_name, Var* exception = NULL);
  Var Call(const Var& method_name, const Var& arg1, Var* exception = NULL);
  Var Call(const Var& method_name, const Var& arg1, const Var& arg2,
           Var* exception = NULL);
  Var Call(const Var& method_name, const Var& arg1, const Var& arg2,
           const Var& arg3, Var* exception = NULL);
  Var Call(const Var& method_name, const Var& arg1, const Var& arg2,
           const Var& arg3, const Var& arg4, Var* exception = NULL);

  // Returns a const reference to the PP_Var managed by this Var object.
  const PP_Var& pp_var() const {
    return var_;
  }

  // Detaches from the internal PP_Var of this object, keeping the reference
  // count the same. This is used when returning a PP_Var from an API function
  // where the caller expects the return value to be AddRef'ed for it.
  PP_Var Detach() {
    PP_Var ret = var_;
    var_ = PP_MakeUndefined();
    needs_release_ = false;
    return ret;
  }

  // Prints a short description "Var<X>" that can be used for logging, where
  // "X" is the underlying scalar or "UNDEFINED" or "OBJ" as it does not call
  // into the browser to get the object description.
  std::string DebugString() const;

  // For use when calling the raw C PPAPI when using the C++ Var as a possibly
  // NULL exception. This will handle getting the address of the internal value
  // out if it's non-NULL and fixing up the reference count.
  //
  // Danger: this will only work for things with exception semantics, i.e. that
  // the value will not be changed if it's a non-undefined exception. Otherwise,
  // this class will mess up the refcounting.
  //
  // This is a bit subtle:
  // - If NULL is passed, we return NULL from get() and do nothing.
  //
  // - If a undefined value is passed, we return the address of a undefined var
  //   from get and have the output value take ownership of that var.
  //
  // - If a non-undefined value is passed, we return the address of that var
  //   from get, and nothing else should change.
  //
  // Example:
  //   void FooBar(a, b, Var* exception = NULL) {
  //     foo_interface->Bar(a, b, Var::OutException(exception).get());
  //   }
  class OutException {
   public:
    OutException(Var* v)
        : output_(v),
          originally_had_exception_(v && v->is_null()) {
      if (output_)
        temp_ = output_->var_;
      else
        temp_.type = PP_VARTYPE_UNDEFINED;
    }
    ~OutException() {
      if (output_ && !originally_had_exception_)
        *output_ = Var(PassRef(), temp_);
    }

    PP_Var* get() {
      if (output_)
        return &temp_;
      return NULL;
    }

   private:
    Var* output_;
    bool originally_had_exception_;
    PP_Var temp_;
  };

 private:
  // Prevent an arbitrary pointer argument from being implicitly converted to
  // a bool at Var construction. If somebody makes such a mistake, (s)he will
  // get a compilation error.
  Var(void* non_scriptable_object_pointer);

  PP_Var var_;
  bool needs_release_;
};

}  // namespace pp

#endif  // PPAPI_CPP_VAR_H_