Enable getting scoped_ptr type from v8 value.
authorCheng Zhao <zcbenz@gmail.com>
Thu, 5 Dec 2013 15:25:14 +0000 (23:25 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Thu, 5 Dec 2013 15:25:14 +0000 (23:25 +0800)
God damned C++ template.

atom.gyp
common/swap_or_assign.h [new file with mode: 0644]
common/v8_conversions.h

index bde0baa..e52121e 100644 (file)
--- a/atom.gyp
+++ b/atom.gyp
       'common/platform_util.h',
       'common/platform_util_mac.mm',
       'common/platform_util_win.cc',
+      'common/swap_or_assign.h',
       'common/v8_conversions.h',
       'common/v8_value_converter_impl.cc',
       'common/v8_value_converter_impl.h',
diff --git a/common/swap_or_assign.h b/common/swap_or_assign.h
new file mode 100644 (file)
index 0000000..3953653
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (c) 2013 GitHub, Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_COMMON_SWAP_OR_ASSIGN_H_
+#define ATOM_COMMON_SWAP_OR_ASSIGN_H_
+
+namespace internal {
+
+// Helper to detect whether value has specified method.
+template <typename T>
+class HasSwapMethod {
+  typedef char one;
+  typedef long two;
+  template <typename C> static one test(char[sizeof(&C::swap)]) ;
+  template <typename C> static two test(...);
+ public:
+  enum { value = sizeof(test<T>(0)) == sizeof(char) };
+};
+
+template<bool B, class T = void>
+struct enable_if {};
+
+template<class T>
+struct enable_if<true, T> { typedef T type; };
+
+template<typename T>
+typename enable_if<HasSwapMethod<T>::value>::type SwapOrAssign(
+    T& v1, const T& v2) {
+  v1.swap(const_cast<T&>(v2));
+}
+
+template<typename T>
+typename enable_if<!HasSwapMethod<T>::value>::type SwapOrAssign(
+    T& v1, const T& v2) {
+  v1 = v2;
+}
+
+}  // namespace internal
+
+#endif  // ATOM_COMMON_SWAP_OR_ASSIGN_H_
index 55b7709..a1800ce 100644 (file)
 
 #include "base/files/file_path.h"
 #include "base/string16.h"
+#include "base/template_util.h"
+#include "base/values.h"
 #include "browser/api/atom_api_window.h"
+#include "common/swap_or_assign.h"
+#include "content/public/renderer/v8_value_converter.h"
 #include "googleurl/src/gurl.h"
 #include "ui/gfx/rect.h"
 #include "v8/include/v8.h"
@@ -60,6 +64,13 @@ struct FromV8Value {
                        width->IntegerValue(), height->IntegerValue());
   }
 
+  operator scoped_ptr<base::Value>() {
+    scoped_ptr<content::V8ValueConverter> converter(
+        content::V8ValueConverter::create());
+    return scoped_ptr<base::Value>(
+        converter->FromV8Value(value_, v8::Context::GetCurrent()));
+  }
+
   operator std::vector<std::string>() {
     std::vector<std::string> array;
     v8::Handle<v8::Array> v8_array = v8::Handle<v8::Array>::Cast(value_);
@@ -185,6 +196,12 @@ bool V8ValueCanBeConvertedTo<gfx::Rect>(v8::Handle<v8::Value> value) {
 }
 
 template<> inline
+bool V8ValueCanBeConvertedTo<scoped_ptr<base::Value>>(
+    v8::Handle<v8::Value> value) {
+  return value->IsObject();
+}
+
+template<> inline
 bool V8ValueCanBeConvertedTo<std::vector<std::string>>(
     v8::Handle<v8::Value> value) {
   return value->IsArray();
@@ -218,7 +235,8 @@ template<typename T1> inline
 bool FromV8Arguments(const v8::Arguments& args, T1* value, int index = 0) {
   if (!V8ValueCanBeConvertedTo<T1>(args[index]))
     return false;
-  *value = static_cast<const T1&>(FromV8Value(args[index]));
+  internal::SwapOrAssign(*value,
+                         static_cast<const T1&>(FromV8Value(args[index])));
   return true;
 }