summaryrefslogtreecommitdiffstats
path: root/ppapi/cpp/var.h
blob: a79f3c4f3e2e3d34a6f52aa228916e1b38b42688 (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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
// Copyright (c) 2012 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_var.h"
#include "ppapi/cpp/pass_ref.h"
#include "ppapi/cpp/resource.h"

/// @file
/// This file defines the API for handling the passing of data types between
/// your module and the page.
namespace pp {

/// A generic type used for passing data types between the module and the page.
class Var {
 public:
  /// Special value passed to constructor to make <code>NULL</code>.
  struct Null {};

  /// Default constructor. Creates a <code>Var</code> of type
  /// <code>Undefined</code>.
  Var();

  /// A constructor used to create a <code>Var</code> of type <code>Null</code>.
  Var(Null);

  /// A constructor used to create a <code>Var</code> of type <code>Bool</code>.
  ///
  /// @param[in] b A boolean value.
  Var(bool b);

  /// A constructor used to create a 32 bit integer <code>Var</code>.
  ///
  /// @param[in] i A 32 bit integer value.
  Var(int32_t i);

  /// A constructor used to create a double value <code>Var</code>.
  ///
  /// @param[in] d A double value.
  Var(double d);

  /// A constructor used to create a UTF-8 character <code>Var</code>.
  Var(const char* utf8_str);  // Must be encoded in UTF-8.

  /// A constructor used to create a UTF-8 character <code>Var</code>.
  Var(const std::string& utf8_str);  // Must be encoded in UTF-8.

  /// A constructor used to create a resource <code>Var</code>.
  explicit Var(const pp::Resource& resource);

  /// A constructor used when you have received a <code>Var</code> as a return
  /// value that has had its reference count incremented for you.
  ///
  /// You will not normally need to use this constructor because
  /// the reference count will not normally be incremented for you.
  Var(PassRef, const PP_Var& var) {
    var_ = var;
    is_managed_ = true;
  }

  /// A constructor that increments the reference count.
  explicit Var(const PP_Var& var);

  struct DontManage {};

  /// This constructor is used when we've given a <code>PP_Var</code> as an
  /// input argument from somewhere and that reference is managing the
  /// reference count for us. The object will not have its reference count
  /// increased or decreased by this class instance.
  ///
  /// @param[in] var A <code>Var</code>.
  Var(DontManage, const PP_Var& var) {
    var_ = var;
    is_managed_ = false;
  }

  /// A constructor for copying a <code>Var</code>.
  Var(const Var& other);

  /// Destructor.
  virtual ~Var();

  /// This function assigns one <code>Var</code> to another <code>Var</code>.
  ///
  /// @param[in] other The <code>Var</code> to be assigned.
  ///
  /// @return A resulting <code>Var</code>.
  virtual Var& operator=(const Var& other);

  /// This function compares object identity (rather than value identity) for
  /// objects, dictionaries, and arrays
  ///
  /// @param[in] other The <code>Var</code> to be compared to this Var.
  ///
  /// @return true if the <code>other</code> <code>Var</code> is the same as
  /// this <code>Var</code>, otherwise false.
  bool operator==(const Var& other) const;

  /// This function determines if this <code>Var</code> is an undefined value.
  ///
  /// @return true if this <code>Var</code> is undefined, otherwise false.
  bool is_undefined() const { return var_.type == PP_VARTYPE_UNDEFINED; }

  /// This function determines if this <code>Var</code> is a null value.
  ///
  /// @return true if this <code>Var</code> is null, otherwise false.
  bool is_null() const { return var_.type == PP_VARTYPE_NULL; }

  /// This function determines if this <code>Var</code> is a bool value.
  ///
  /// @return true if this <code>Var</code> is a bool, otherwise false.
  bool is_bool() const { return var_.type == PP_VARTYPE_BOOL; }

  /// This function determines if this <code>Var</code> is a string value.
  ///
  /// @return true if this <code>Var</code> is a string, otherwise false.
  bool is_string() const { return var_.type == PP_VARTYPE_STRING; }

  /// This function determines if this <code>Var</code> is an object.
  ///
  /// @return true if this <code>Var</code> is an object, otherwise false.
  bool is_object() const { return var_.type == PP_VARTYPE_OBJECT; }

  /// This function determines if this <code>Var</code> is an array.
  ///
  /// @return true if this <code>Var</code> is an array, otherwise false.
  bool is_array() const { return var_.type == PP_VARTYPE_ARRAY; }

  /// This function determines if this <code>Var</code> is a dictionary.
  ///
  /// @return true if this <code>Var</code> is a dictionary, otherwise false.
  bool is_dictionary() const { return var_.type == PP_VARTYPE_DICTIONARY; }

  /// This function determines if this <code>Var</code> is a resource.
  ///
  /// @return true if this <code>Var</code> is a resource, otherwise false.
  bool is_resource() const { return var_.type == PP_VARTYPE_RESOURCE; }

  /// This function determines if this <code>Var</code> is an integer value.
  /// The <code>is_int</code> function returns 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 is_number().
  ///
  /// @return true if this <code>Var</code> is an integer, otherwise false.
  bool is_int() const { return var_.type == PP_VARTYPE_INT32; }

  /// This function determines if this <code>Var</code> is a double value.
  /// The <code>is_double</code> function returns 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 is_number().
  ///
  /// @return true if this <code>Var</code> is a double, otherwise false.
  bool is_double() const { return var_.type == PP_VARTYPE_DOUBLE; }

  /// This function determines if this <code>Var</code> is a number.
  ///
  /// @return true if this <code>Var</code> is an int32 or double number,
  /// otherwise false.
  bool is_number() const {
    return var_.type == PP_VARTYPE_INT32 ||
           var_.type == PP_VARTYPE_DOUBLE;
  }

  /// This function determines if this <code>Var</code> is an ArrayBuffer.
  bool is_array_buffer() const { return var_.type == PP_VARTYPE_ARRAY_BUFFER; }

  /// AsBool() converts this <code>Var</code> to a bool. Assumes the
  /// internal representation is_bool(). If it's not, it will assert in debug
  /// mode, and return false.
  ///
  /// @return A bool version of this <code>Var</code>.
  bool AsBool() const;

  /// AsInt() converts this <code>Var</code> to an int32_t. This function
  /// is required 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
  /// !is_double() before calling AsInt().
  ///
  /// These functions will assert in debug mode and return 0 if the internal
  /// representation is not is_number().
  ///
  /// @return An int32_t version of this <code>Var</code>.
  int32_t AsInt() const;

  /// AsDouble() converts this <code>Var</code> to a double. This function is
  /// necessary 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
  /// !is_double() before calling AsInt().
  ///
  /// These functions will assert in debug mode and return 0 if the internal
  /// representation is not is_number().
  ///
  /// @return An double version of this <code>Var</code>.
  double AsDouble() const;

  /// AsString() converts this <code>Var</code> to a string. If this object is
  /// not a string, it will assert in debug mode, and return an empty string.
  ///
  /// @return A string version of this <code>Var</code>.
  std::string AsString() const;

  /// Gets the resource contained in the var. If this object is not a resource,
  /// it will assert in debug mode, and return a null resource.
  ///
  /// @return The <code>pp::Resource</code> that is contained in the var.
  pp::Resource AsResource() const;

  /// This function returns the internal <code>PP_Var</code>
  /// managed by this <code>Var</code> object.
  ///
  /// @return A const reference to a <code>PP_Var</code>.
  const PP_Var& pp_var() const {
    return var_;
  }

  /// Detach() detaches from the internal <code>PP_Var</code> of this
  /// object, keeping the reference count the same. This is used when returning
  /// a <code>PP_Var</code> from an API function where the caller expects the
  /// return value to have the reference count incremented for it.
  ///
  /// @return A detached version of this object without affecting the reference
  /// count.
  PP_Var Detach() {
    PP_Var ret = var_;
    var_ = PP_MakeUndefined();
    is_managed_ = true;
    return ret;
  }

  /// DebugString() returns 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.
  ///
  /// @return A string displaying the value of this <code>Var</code>. This
  /// function is used for debugging.
  std::string DebugString() const;

  /// This class is used when calling the raw C PPAPI when using the C++
  /// <code>Var</code> as a possible NULL exception. This class will handle
  /// getting the address of the internal value out if it's non-NULL and
  /// fixing up the reference count.
  ///
  /// <strong>Warning:</strong> 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:
    /// A constructor.
    OutException(Var* v)
        : output_(v),
          originally_had_exception_(v && !v->is_undefined()) {
      if (output_) {
        temp_ = output_->var_;
      } else {
        temp_.padding = 0;
        temp_.type = PP_VARTYPE_UNDEFINED;
      }
    }

    /// Destructor.
    ~OutException() {
      if (output_ && !originally_had_exception_)
        *output_ = Var(PASS_REF, temp_);
    }

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

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

 protected:
  PP_Var var_;

  // |is_managed_| indicates if the instance manages |var_|.
  // You need to check if |var_| is refcounted to call Release().
  bool is_managed_;

 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);
};

}  // namespace pp

#endif  // PPAPI_CPP_VAR_H_