FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
NPVariantUtil.h
1 /**********************************************************\
2  Original Author: Georg Fritzsche
3 
4  Created: Nov 6, 2010
5  License: Dual license model; choose one of two:
6  New BSD License
7  http://www.opensource.org/licenses/bsd-license.php
8  - or -
9  GNU Lesser General Public License, version 2.1
10  http://www.gnu.org/licenses/lgpl-2.1.html
11 
12  Copyright 20100 Georg Fritzsche, Firebreath development team
13  \**********************************************************/
14 
15 #pragma once
16 #ifndef FB_H_NPVARIANTUTIL
17 #define FB_H_NPVARIANTUTIL
18 
19 #include <map>
20 #include <string>
21 #include <typeinfo>
22 
23 #include <boost/type_traits/is_arithmetic.hpp>
24 #include <boost/type_traits/is_integral.hpp>
25 #include <boost/type_traits/is_same.hpp>
26 #include <boost/type_traits/is_floating_point.hpp>
27 #include <boost/integer_traits.hpp>
28 
29 #include "NpapiTypes.h"
30 #include "APITypes.h"
31 #include "NpapiPluginModule.h"
32 #include "NPJavascriptObject.h"
33 #include "NPObjectAPI.h"
34 #include "DOM/Document.h"
35 #include "DOM/Window.h"
36 #include "variant_list.h"
37 #include "NpapiBrowserHost.h"
38 
39 
40 namespace FB { namespace Npapi
41 {
42  struct type_info_less
43  {
44  bool operator() (const std::type_info* const lhs, const std::type_info* const rhs) const
45  {
46  return lhs->before(*rhs) ? true : false;
47  }
48  };
49 
50  typedef NPVariant (*NPVariantBuilder)(const NpapiBrowserHostPtr&, const FB::variant&);
51  typedef std::map<std::type_info const*, NPVariantBuilder, type_info_less> NPVariantBuilderMap;
52 
53  template<class T>
54  NPVariant makeNPVariant(const NpapiBrowserHostPtr& host, const FB::variant& var)
55  {
56  BOOST_STATIC_ASSERT((false && sizeof(T)==0));
57  NPVariant npv;
58  npv.type = NPVariantType_Null;
59  return npv;
60  }
61 
62  template<> inline
63  NPVariant makeNPVariant<double>(const NpapiBrowserHostPtr& host, const FB::variant& var)
64  {
65  NPVariant npv;
66  npv.type = NPVariantType_Double;
67  npv.value.doubleValue = var.convert_cast<double>();
68  return npv;
69  }
70 
71  template<> inline
72  NPVariant makeNPVariant<int32_t>(const NpapiBrowserHostPtr& host, const FB::variant& var)
73  {
74  NPVariant npv;
75  npv.type = NPVariantType_Int32;
76  npv.value.intValue = var.convert_cast<int32_t>();
77  return npv;
78  }
79 
80  template<> inline
81  NPVariant makeNPVariant<bool>(const NpapiBrowserHostPtr& host, const FB::variant& var)
82  {
83  NPVariant npv;
84  npv.type = NPVariantType_Bool;
85  npv.value.boolValue = var.convert_cast<bool>();
86  return npv;
87  }
88 
89  template<> inline
90  NPVariant makeNPVariant<std::string>(const NpapiBrowserHostPtr& host, const FB::variant& var)
91  {
92  NPVariant npv;
93 
94  std::string str = var.convert_cast<std::string>();
95  char *outStr = (char*)host->MemAlloc(str.size() + 1);
96  memcpy(outStr, str.c_str(), str.size() + 1);
97  npv.type = NPVariantType_String;
98  npv.value.stringValue.UTF8Characters = outStr;
99  npv.value.stringValue.UTF8Length = str.size();
100 
101  return npv;
102  }
103 
104  template<> inline
105  NPVariant makeNPVariant<std::wstring>(const NpapiBrowserHostPtr& host, const FB::variant& var)
106  {
107  NPVariant npv;
108 
109  // This is not a typo; the std::string gets the UTF8 representation
110  // and we pass that back to the browser
111  std::string str = var.convert_cast<std::string>();
112  char *outStr = (char*)host->MemAlloc(str.size() + 1);
113  memcpy(outStr, str.c_str(), str.size() + 1);
114  npv.type = NPVariantType_String;
115  npv.value.stringValue.UTF8Characters = outStr;
116  npv.value.stringValue.UTF8Length = str.size();
117 
118  return npv;
119  }
120 
121  template<> inline
122  NPVariant makeNPVariant<FB::FBVoid>(const NpapiBrowserHostPtr& host, const FB::variant& var)
123  {
124  NPVariant npv;
125  npv.type = NPVariantType_Void;
126  return npv;
127  }
128 
129  template<> inline
130  NPVariant makeNPVariant<FB::FBNull>(const NpapiBrowserHostPtr& host, const FB::variant& var)
131  {
132  NPVariant npv;
133  npv.type = NPVariantType_Null;
134  return npv;
135  }
136 
137  template<> inline
138  NPVariant makeNPVariant<FB::VariantList>(const NpapiBrowserHostPtr& host, const FB::variant& var)
139  {
140  NPVariant npv;
141 
142  FB::JSObjectPtr outArr = host->getDOMWindow()->createArray();
143  FB::VariantList inArr = var.cast<FB::VariantList>();
144 
145  for (FB::VariantList::iterator it = inArr.begin(); it != inArr.end(); ++it) {
146  outArr->Invoke("push", FB::variant_list_of(*it));
147  }
148 
149  if (NPObjectAPIPtr api = FB::ptr_cast<NPObjectAPI>(outArr)) {
150  npv.type = NPVariantType_Object;
151  npv.value.objectValue = api->getNPObject();
152  host->RetainObject(npv.value.objectValue);
153  }
154 
155  return npv;
156  }
157 
158  template<> inline
159  NPVariant makeNPVariant<FB::VariantMap>(const NpapiBrowserHostPtr& host, const FB::variant& var)
160  {
161  NPVariant npv;
162 
163  FB::JSObjectPtr out = host->getDOMWindow()->createMap();
164  FB::VariantMap inMap = var.cast<FB::VariantMap>();
165 
166  for (FB::VariantMap::iterator it = inMap.begin(); it != inMap.end(); ++it) {
167  out->SetProperty(it->first, it->second);
168  }
169 
170  if (NPObjectAPIPtr api = FB::ptr_cast<NPObjectAPI>(out)) {
171  npv.type = NPVariantType_Object;
172  npv.value.objectValue = api->getNPObject();
173  host->RetainObject(npv.value.objectValue);
174  }
175 
176  return npv;
177  }
178 
179 // template<> inline
180 // NPVariant makeNPVariant<FB::FBDateString>(const NpapiBrowserHostPtr& host, const FB::variant& var)
181 // {
182 // NPVariant npv;
183 //
184 // FB::FBDateString date = var.cast<FB::FBDateString>();
185 // FB::JSObjectPtr out = host->getDOMWindow()->createDate(date.getValue());;
186 //
187 // if (NPObjectAPIPtr api = FB::ptr_cast<NPObjectAPI>(out)) {
188 // npv.type = NPVariantType_Object;
189 // npv.value.objectValue = api->getNPObject();
190 // host->RetainObject(npv.value.objectValue);
191 // } else {
192 // return makeNPVariant<std::string>(host, date.getValue());
193 // }
194 //
195 // return npv;
196 // }
197 
198  template<> inline
199  NPVariant makeNPVariant<FB::JSAPIPtr>(const NpapiBrowserHostPtr& host, const FB::variant& var)
200  {
201  NPVariant npv;
202 
203  if (FB::JSAPIPtr obj = var.cast<FB::JSAPIPtr>())
204  {
205  NPObject *outObj = NULL;
206 
207  if (NPObjectAPIPtr tmpObj = FB::ptr_cast<NPObjectAPI>(obj)) {
208  outObj = tmpObj->getNPObject();
209  host->RetainObject(outObj);
210  } else {
211  outObj = host->getJSAPIWrapper(var.cast<FB::JSAPIPtr>(), true);
212  }
213  if (outObj) {
214  npv.type = NPVariantType_Object;
215  npv.value.objectValue = outObj;
216  } else {
217  npv.type = NPVariantType_Null;
218  }
219  }
220  else
221  {
222  npv.type = NPVariantType_Null;
223  }
224 
225  return npv;
226  }
227  template<> inline
228  NPVariant makeNPVariant<FB::JSAPIWeakPtr>(const NpapiBrowserHostPtr& host, const FB::variant& var)
229  {
230  NPVariant npv;
231 
232  // convert_cast will automatically make a shared_ptr out of the weak_ptr; if the weak_ptr
233  // is expired it'll be a NULL ptr
234  if (FB::JSAPIPtr obj = var.convert_cast<FB::JSAPIPtr>())
235  {
236  NPObject *outObj = NULL;
237 
238  if (NPObjectAPIPtr tmpObj = FB::ptr_cast<NPObjectAPI>(obj)) {
239  outObj = tmpObj->getNPObject();
240  host->RetainObject(outObj);
241  } else {
242  // The big difference between returning a weak_ptr instead of a shared_ptr is
243  // that we don't have the browser object retain the weak_ptr
244  outObj = host->getJSAPIWrapper(var.cast<FB::JSAPIWeakPtr>());
245  }
246 
247  npv.type = NPVariantType_Object;
248  npv.value.objectValue = outObj;
249  }
250  else
251  {
252  npv.type = NPVariantType_Null;
253  }
254 
255  return npv;
256  }
257 
258  template<> inline
259  NPVariant makeNPVariant<FB::JSObjectPtr>(const NpapiBrowserHostPtr& host, const FB::variant& var)
260  {
261  NPVariant npv;
262 
263  if (FB::JSObjectPtr obj = var.cast<FB::JSObjectPtr>())
264  {
265  NPObject *outObj = NULL;
266 
267  if (NPObjectAPIPtr tmpObj = FB::ptr_cast<NPObjectAPI>(obj)) {
268  outObj = tmpObj->getNPObject();
269  host->RetainObject(outObj);
270  } else {
271  outObj = NPJavascriptObject::NewObject(host, obj, true);
272  }
273 
274  npv.type = NPVariantType_Object;
275  npv.value.objectValue = outObj;
276  }
277  else
278  {
279  npv.type = NPVariantType_Null;
280  }
281 
282  return npv;
283  }
284 
285  namespace select_npvariant_builder
286  {
287  template<class T>
288  NPVariantBuilder isIntegral(const boost::true_type& /* is_integral */)
289  {
290  if (boost::is_same<T, bool>::value) {
291  return &makeNPVariant<bool>;
292  }
293 
294  if ((boost::is_signed<T>::value && (sizeof(T) <= sizeof(int32_t))) || (boost::is_unsigned<T>::value && (sizeof(T) <= sizeof(int32_t)/2))) {
295  // max value of T fits into int32_t
296  return &makeNPVariant<int32_t>;
297  }
298 
299  // max value of T doesn't fit into int32_t, use string instead
300  return &makeNPVariant<std::string>;
301  }
302 
303  template<class T>
304  NPVariantBuilder isIntegral(const boost::false_type& /* is_integral */)
305  {
306  BOOST_STATIC_ASSERT((boost::is_floating_point<T>::value));
307  return &makeNPVariant<double>;
308  }
309 
310  template<class T>
311  NPVariantBuilder isArithmetic(const boost::true_type& /* is_arithmetic */)
312  {
313  return isIntegral<T>(boost::is_integral<T>());
314  }
315 
316  template<class T>
317  NPVariantBuilder isArithmetic(const boost::false_type& /* is_arithmetic */)
318  {
319  return &makeNPVariant<T>;
320  }
321 
322  template<class T>
323  NPVariantBuilder select()
324  {
325  return isArithmetic<T>(boost::is_arithmetic<T>());
326  }
327  }
328 } }
329 
330 #endif
331 
boost::shared_ptr< FB::JSObject > JSObjectPtr
Defines an alias representing a JSObject shared_ptr (you should never use a JSObject* directly) ...
Definition: APITypes.h:109
const T convert_cast() const
Converts the stored value to the requested type if possible and returns the resulting value...
Definition: variant.h:667
FB::detail::VariantListInserter variant_list_of(FB::variant v)
Allows convenient creation of an FB::VariantList.
Definition: variant_list.h:122
Accepts any datatype, used in all interactions with javascript. Provides tools for getting back out t...
Definition: variant.h:198
std::vector< variant > VariantList
Defines an alias representing list of variants.
Definition: APITypes.h:64
boost::weak_ptr< FB::JSAPI > JSAPIWeakPtr
Defines an alias for a JSAPI weak_ptr (you should never use a JSAPI* directly)
Definition: APITypes.h:88
boost::shared_ptr< FB::JSAPI > JSAPIPtr
Defines an alias for a JSAPI shared_ptr (you should never use a JSAPI* directly)
Definition: APITypes.h:94
std::map< std::string, variant > VariantMap
Defines an alias representing a string -> variant map.
Definition: APITypes.h:72
T cast() const
returns the value cast as the given type; throws bad_variant_type if that type is not the type of the...
Definition: variant.h:370