#ifndef EFL_EINA_JS_GET_VALUE_FROM_C_HH #define EFL_EINA_JS_GET_VALUE_FROM_C_HH #include #include #include #include #include namespace efl { namespace eina { namespace js { template struct print_tag {}; template inline v8::Local get_value_from_c(T v, v8::Isolate* isolate, const char* , typename std::enable_if::type>::value && !std::is_same::value>::type* = 0) { return eina::js::compatibility_new(isolate, v); } template inline v8::Local get_value_from_c(T v, v8::Isolate* isolate, const char* , typename std::enable_if::type>::value>::type* = 0) { return eina::js::compatibility_new(isolate, v); } template inline v8::Local get_value_from_c(T v, v8::Isolate* isolate, const char* , typename std::enable_if::type, Eina_Bool>::value>::type* = 0) { return eina::js::compatibility_new(isolate, v); } template inline v8::Local get_value_from_c(v8::Local v, v8::Isolate*, const char*) { return v; } template inline v8::Local get_value_from_c(T v, v8::Isolate* isolate, const char* , typename std::enable_if::type>::value>::type* = 0) { return eina::js::compatibility_new(isolate, v); } inline v8::Local get_value_from_c(const char* v, v8::Isolate* isolate, const char*) { if (!v) return v8::Null(isolate); return eina::js::compatibility_new(isolate, v); } inline v8::Local get_value_from_c(char* v, v8::Isolate* isolate, const char* class_name) { return js::get_value_from_c(const_cast(v), isolate, class_name); } inline v8::Local get_value_from_c(void*, v8::Isolate*, const char*) { // TODO: create Extern? std::cerr << "aborting because we don't know the type void*" << std::endl; std::abort(); } inline v8::Local get_value_from_c(const void*, v8::Isolate*, const char*) { // TODO: create Extern? std::cerr << "aborting because we don't know the type void*" << std::endl; std::abort(); } // For function pointer types template inline v8::Local get_value_from_c(T, v8::Isolate*, const char* , typename std::enable_if ::type>::value && std::is_function::type>::type>::value >::type* = 0) { // TODO: create Extern? std::cerr << "aborting because we don't know the type " << typeid(print_tag).name() << std::endl; std::abort(); } // For all non-pointer types that are not handled template inline v8::Local get_value_from_c(T, v8::Isolate*, const char* , typename std::enable_if ::type>::value && !std::is_integral::type>::value && !std::is_floating_point::type>::value && !std::is_enum::type>::value && !std::is_same::type, Eina_Bool>::value && !js::is_struct_tag::type>::value && !js::is_struct_ptr_tag::type>::value && !js::is_complex_tag::type>::value >::type* = 0) { std::cerr << "aborting because we don't know the type " << typeid(print_tag).name() << std::endl; std::abort(); } // For all non-handled pointer types (which are not function pointers): // - we try to dereference it in the SFINAE // - if it matches we call get_value_from_c for the dereferenced type // - if it fails (probably because it is opaque) the void* or const void* // overload will take place (implicit conversion) template inline auto get_value_from_c(T object, v8::Isolate* isolate, const char* class_name , typename std::enable_if< (std::is_pointer::type>::value && !std::is_function::type>::type>::value ) && !(std::is_same::type, char*>::value || std::is_same::type, const char*>::value || std::is_same::type, void*>::value || std::is_same::type, const void*>::value || std::is_same::type, Eo*>::value || std::is_same::type, const Eo*>::value )>::type* = 0) -> decltype(get_value_from_c(*object, isolate, class_name)) { std::cerr << "dereferencing " << typeid(print_tag).name() << std::endl; return get_value_from_c(*object, isolate, class_name); } inline v8::Local get_value_from_c(Eo* v, v8::Isolate* isolate, const char* class_name) { try { auto ctor = ::efl::eina::js::get_class_constructor(class_name); auto obj = new_v8_external_instance(ctor, ::efl_ref(v), isolate); efl::eina::js::make_weak(isolate, obj, [v]{ ::efl_unref(v); }); return obj; } catch (std::runtime_error const& error) { eina::js::compatibility_throw (isolate, v8::Exception::TypeError (eina::js::compatibility_new(isolate, error.what()))); return v8::Null(isolate); } } inline v8::Local get_value_from_c(const Eo* v, v8::Isolate* isolate, const char* class_name) { // TODO: implement const objects? try { auto ctor = ::efl::eina::js::get_class_constructor(class_name); auto obj = new_v8_external_instance(ctor, ::efl_ref(v), isolate); efl::eina::js::make_weak(isolate, obj, [v]{ ::efl_unref(v); }); return obj; } catch (std::runtime_error const& error) { eina::js::compatibility_throw (isolate, v8::Exception::TypeError (eina::js::compatibility_new(isolate, error.what()))); return v8::Null(isolate); } } template inline v8::Local get_value_from_c(struct_ptr_tag v, v8::Isolate* isolate, const char* class_name) { try { using nonconst_type = typename std::remove_const::type; bool own = false; // TODO: handle ownership auto ptr = const_cast(v.value); auto ctor = ::efl::eina::js::get_class_constructor(class_name); auto obj = new_v8_external_instance(ctor, ptr, isolate); if (own) efl::eina::js::make_weak(isolate, obj, [ptr]{ free(ptr); }); return obj; } catch (std::runtime_error const& error) { eina::js::compatibility_throw (isolate, v8::Exception::TypeError (eina::js::compatibility_new(isolate, error.what()))); return v8::Null(isolate); } } template inline v8::Local get_value_from_c(struct_tag v, v8::Isolate* isolate, const char* class_name) { T* s = static_cast(malloc(sizeof(T))); *s = v.value; return get_value_from_c(struct_ptr_tag{s}, isolate, class_name); } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char*) { using wrapped_type = typename container_wrapper::type; bool own = false; // TODO: handle ownership auto a = new ::efl::eina::accessor{v.value}; auto obj = export_accessor(*a , isolate, K::class_name()); efl::eina::js::make_weak(isolate, obj, [a, own] { if (!own) a->release_native_handle(); delete a; }); return obj; } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag, v8::Isolate*, const char*) { throw std::logic_error(""); } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char* class_name) { // TODO implement const accessor? return get_value_from_c(efl::eina::js::complex_tag{const_cast(v.value)}, isolate, class_name); } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char*) { bool own = false; // TODO: handle ownership auto o = new ::efl::eina::js::eina_array(v.value); auto ctor = get_array_instance_template(); auto obj = new_v8_external_instance(ctor, o, isolate); efl::eina::js::make_weak(isolate, obj, [o, own] { if (!own) o->release_native_handle(); delete o; }); return obj; } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char*) { bool own = false; // TODO: handle ownership auto o = new ::efl::eina::js::range_eina_array(const_cast(v.value)); auto ctor = get_array_instance_template(); auto obj = new_v8_external_instance(ctor, o, isolate); efl::eina::js::make_weak(isolate, obj, [o, own] { if (!own) o->release_native_handle(); delete o; }); return obj; } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char*) { bool own = false; // TODO: handle ownership auto ptr = v.value; auto obj = export_iterator(ptr , isolate, K::class_name()); if (own && ptr) efl::eina::js::make_weak(isolate, obj, [ptr]{ ::eina_iterator_free(ptr); }); return obj; } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char* class_name) { // TODO: implement const iterators? return get_value_from_c(efl::eina::js::complex_tag{const_cast(v.value)}, isolate, class_name); } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag, v8::Isolate*, const char*) { std::cerr << "get_value_from_c for Eina_Hash not implemented. Aborting..." << std::endl; std::abort(); } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag, v8::Isolate*, const char*) { std::cerr << "get_value_from_c for Eina_Hash not implemented. Aborting..." << std::endl; std::abort(); } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char*) { bool own = false; // TODO: handle ownership auto o = new ::efl::eina::js::eina_list(v.value); auto ctor = get_list_instance_template(); auto obj = new_v8_external_instance(ctor, o, isolate); efl::eina::js::make_weak(isolate, obj, [o, own] { if (!own) o->release_native_handle(); delete o; }); return obj; } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char*) { bool own = false; // TODO: handle ownership auto o = new ::efl::eina::js::range_eina_list(const_cast(v.value)); auto ctor = get_list_instance_template(); auto obj = new_v8_external_instance(ctor, o, isolate); efl::eina::js::make_weak(isolate, obj, [o, own] { if (!own) o->release_native_handle(); delete o; }); return obj; } } } } #endif