#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) { auto ctor = ::efl::eina::js::get_class_constructor(class_name); return new_v8_external_instance(ctor, v, isolate); } inline v8::Local get_value_from_c(const Eo* v, v8::Isolate* isolate, const char* class_name) { // TODO: implement const objects? auto ctor = ::efl::eina::js::get_class_constructor(class_name); return new_v8_external_instance(ctor, const_cast(v), isolate); } template inline v8::Local get_value_from_c(struct_ptr_tag v, v8::Isolate* isolate, const char* class_name) { // TODO: implement const structs? auto ctor = ::efl::eina::js::get_class_constructor(class_name); return new_v8_external_instance(ctor, const_cast::type>(v.value), isolate); } template inline v8::Local get_value_from_c(struct_tag v, v8::Isolate* isolate, const char* class_name) { return get_value_from_c(struct_ptr_tag{new T(v.value)}, 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; auto a = new ::efl::eina::accessor{v.value}; return export_accessor(*a , isolate, K::class_name()); } 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*) { // TODO: use unique_ptr for eina_array to avoid leak ? auto o = new ::efl::eina::js::range_eina_array(v.value); auto ctor = get_array_instance_template(); return new_v8_external_instance(ctor, o, isolate); } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char* class_name) { // TODO: implement const array? 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 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*) { // TODO: ensure eina_list ownership ??? auto o = new ::efl::eina::js::range_eina_list(v.value); auto ctor = get_list_instance_template(); return new_v8_external_instance(ctor, o, isolate); } template inline v8::Local get_value_from_c(efl::eina::js::complex_tag v, v8::Isolate* isolate, const char* class_name) { // TODO: implement const list? return get_value_from_c(efl::eina::js::complex_tag{const_cast(v.value)}, isolate, class_name); } } } } #endif