Made more generic the container base

This commit is contained in:
Felipe Magno de Almeida 2014-09-18 11:40:49 -03:00
parent d0f80c915a
commit 4c0dcfc48a
6 changed files with 176 additions and 127 deletions

View File

@ -19,7 +19,7 @@ lib_eina_js_libeina_js_la_DEPENDENCIES = @EINA_INTERNAL_LIBS@ @DL_INTERNAL_LIBS@
lib_eina_js_libeina_js_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
lib_eina_js_libeina_js_la_SOURCES = \
bindings/eina_js/eina_list.cc
bindings/eina_js/eina_js_container.cc
#installed_einacxxmainheadersdir = $(includedir)/eina-cxx-@VMAJ@
#dist_installed_einacxxmainheaders_DATA = \

View File

@ -24,24 +24,25 @@ struct tag { typedef T type; };
namespace {
v8::UniquePersistent<v8::ObjectTemplate> persistent_instance_template;
v8::Handle<v8::FunctionTemplate> instance_template;
v8::UniquePersistent<v8::ObjectTemplate> instance_persistents[container_type_size];
v8::Handle<v8::FunctionTemplate> instance_templates[container_type_size];
v8::Local<v8::Object> concat(eina_list_base& lhs, v8::Isolate* isolate, v8::Local<v8::Value> other)
v8::Local<v8::Object> concat(eina_container_base& lhs, v8::Isolate* isolate, v8::Local<v8::Value> other)
{
if(other->IsObject())
{
v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(other);
v8::String::Utf8Value constructor_name (obj->GetConstructorName());
if(obj->GetConstructorName()->Equals(v8::String::NewFromUtf8(isolate, "List")))
std::cout << "constructor " << *constructor_name << std::endl;
if(obj->GetConstructorName()->Equals(v8::String::NewFromUtf8(isolate, "eina_list")))
{
eina_list_base& rhs = *static_cast<eina_list_base*>(obj->GetAlignedPointerFromInternalField(0));
eina_container_base& rhs = *static_cast<eina_container_base*>(obj->GetAlignedPointerFromInternalField(0));
std::type_info const& typeinfo_lhs = typeid(lhs)
, &typeinfo_rhs = typeid(rhs);
if(!typeinfo_lhs.before(typeinfo_rhs) && !typeinfo_rhs.before(typeinfo_lhs))
{
v8::Handle<v8::Value> a[] = {v8::External::New(isolate, rhs.concat(lhs))};
v8::Local<v8::Object> result = instance_template->GetFunction()->NewInstance(1, a);
v8::Local<v8::Object> result = instance_templates[lhs.get_container_type()]->GetFunction()->NewInstance(1, a);
return result;
}
else
@ -56,14 +57,15 @@ v8::Local<v8::Object> concat(eina_list_base& lhs, v8::Isolate* isolate, v8::Loca
std::abort();
}
v8::Local<v8::Object> slice(eina_list_base& self, v8::Isolate* isolate, v8::Local<v8::Value> iv
v8::Local<v8::Object> slice(eina_container_base& self, v8::Isolate* isolate, v8::Local<v8::Value> iv
, v8::Local<v8::Value> jv)
{
if((iv->IsUint32() || iv->IsInt32()) && (jv->IsUint32() || jv->IsInt32()))
{
std::int64_t i = iv->IntegerValue(), j = jv->IntegerValue();
v8::Handle<v8::Value> a[] = {v8::External::New(isolate, self.slice(i, j))};
v8::Local<v8::Object> result = instance_template->GetFunction()->NewInstance(1, a);
v8::Local<v8::Object> result = instance_templates[self.get_container_type()]
->GetFunction()->NewInstance(1, a);
return result;
}
else
@ -74,14 +76,14 @@ v8::Local<v8::Object> slice(eina_list_base& self, v8::Isolate* isolate, v8::Loca
void length(v8::Local<v8::String>, v8::PropertyCallbackInfo<v8::Value> const& info)
{
eina_list_base* self = static_cast<eina_list_base*>(info.This()->GetAlignedPointerFromInternalField(0));
eina_container_base* self = static_cast<eina_container_base*>(info.This()->GetAlignedPointerFromInternalField(0));
info.GetReturnValue().Set((uint32_t)self->size());
}
void index_get(uint32_t index, v8::PropertyCallbackInfo<v8::Value>const& info)
{
std::cout << "index_get " << index << std::endl;
eina_list_base* self = static_cast<eina_list_base*>(info.This()->GetAlignedPointerFromInternalField(0));
eina_container_base* self = static_cast<eina_container_base*>(info.This()->GetAlignedPointerFromInternalField(0));
info.GetReturnValue().Set(self->get(info.GetIsolate(), index));
}
@ -91,7 +93,7 @@ void new_eina_list(v8::FunctionCallbackInfo<v8::Value> const& args)
{
if(args.Length() == 0)
{
eina_list_base* p = new range_eina_list<int>;
eina_container_base* p = new range_eina_list<int>;
std::cerr << "called eina list constructor p = " << p << std::endl;
args.This()->SetAlignedPointerInInternalField(0, dynamic_cast<void*>(p));
}
@ -101,7 +103,7 @@ void new_eina_list(v8::FunctionCallbackInfo<v8::Value> const& args)
if(args[0]->IsExternal())
{
std::cout << "Is external" << std::endl;
eina_list_base* base = reinterpret_cast<eina_list_base*>
eina_container_base* base = reinterpret_cast<eina_container_base*>
(v8::External::Cast(*args[0])->Value());
std::cout << "base " << base << std::endl;
args.This()->SetAlignedPointerInInternalField(0, dynamic_cast<void*>(base));
@ -261,12 +263,9 @@ void register_(v8::Isolate* isolate, const char* name, F&& f, v8::Handle<v8::Obj
(isolate, new F(std::forward<F>(f)))));
}
} } }
EAPI void eina_list_register(v8::Handle<v8::ObjectTemplate> global, v8::Isolate* isolate)
v8::Local<v8::ObjectTemplate> register_template(v8::Isolate* isolate, v8::Handle<v8::FunctionTemplate> constructor)
{
v8::Handle<v8::FunctionTemplate> constructor = v8::FunctionTemplate::New(isolate, &efl::js::new_eina_list );
v8::Local<v8::ObjectTemplate> instance_t = constructor->InstanceTemplate();
v8::Handle<v8::ObjectTemplate> instance_t = constructor->InstanceTemplate();
instance_t->SetInternalFieldCount(1);
instance_t->SetIndexedPropertyHandler(& efl::js::index_get);
@ -275,22 +274,42 @@ EAPI void eina_list_register(v8::Handle<v8::ObjectTemplate> global, v8::Isolate*
prototype->SetAccessor(v8::String::NewFromUtf8(isolate, "length"), &efl::js::length);
using namespace std::placeholders;
efl::js::register_<efl::js::eina_list_base>
(isolate, "concat", &efl::js::concat, prototype);
efl::js::register_<efl::js::eina_list_base>
(isolate, "slice", &efl::js::slice, prototype);
efl::js::register_<efl::js::eina_list_base>
(isolate, "toString", std::bind(&efl::js::eina_list_base::to_string, _1, _2), prototype);
efl::js::register_<efl::js::eina_list_base>
(isolate, "join", std::bind(&efl::js::eina_list_base::to_string, _1, _2), prototype);
efl::js::register_<efl::js::eina_list_base, v8::Local<v8::Value> >
(isolate, "indexOf", std::bind(&efl::js::eina_list_base::index_of, _1, _2, _3), prototype);
efl::js::register_<efl::js::eina_list_base, v8::Local<v8::Value> >
(isolate, "lastIndexOf", std::bind(&efl::js::eina_list_base::last_index_of, _1, _2, _3), prototype);
js::register_<js::eina_container_base>
(isolate, "concat", &js::concat, prototype);
js::register_<js::eina_container_base>
(isolate, "slice", &js::slice, prototype);
js::register_<js::eina_container_base>
(isolate, "toString", std::bind(&js::eina_container_base::to_string, _1, _2), prototype);
js::register_<js::eina_container_base>
(isolate, "join", std::bind(&js::eina_container_base::to_string, _1, _2), prototype);
js::register_<js::eina_container_base, v8::Local<v8::Value> >
(isolate, "indexOf", std::bind(&js::eina_container_base::index_of, _1, _2, _3), prototype);
js::register_<js::eina_container_base, v8::Local<v8::Value> >
(isolate, "lastIndexOf", std::bind(&js::eina_container_base::last_index_of, _1, _2, _3), prototype);
efl::js::persistent_instance_template = v8::UniquePersistent<v8::ObjectTemplate> (isolate, instance_t);
efl::js::instance_template = constructor;
global->Set(v8::String::NewFromUtf8(isolate, "List"), constructor);
return instance_t;
}
void register_class(v8::Isolate* isolate, container_type type, const char* class_name
, v8::FunctionCallback callback)
{
v8::Handle<v8::FunctionTemplate> constructor = v8::FunctionTemplate::New(isolate, callback);
constructor->SetClassName(v8::String::NewFromUtf8(isolate, class_name));
v8::Local<v8::ObjectTemplate> instance_t = efl::js::register_template(isolate, constructor);
efl::js::instance_persistents[type] = v8::UniquePersistent<v8::ObjectTemplate> (isolate, instance_t);
efl::js::instance_templates[type] = constructor;
}
} } }
EAPI void eina_container_register(v8::Handle<v8::ObjectTemplate>, v8::Isolate* isolate)
{
efl::js::register_class(isolate, efl::js::list_container_type, "eina_list", &efl::js::new_eina_list);
}
EAPI v8::Handle<v8::FunctionTemplate> get_list_instance_template()
{
return efl::js::instance_templates[efl::js::list_container_type];
}

View File

@ -0,0 +1,89 @@
#ifndef EINA_JS_CONTAINER_HH
#define EINA_JS_CONTAINER_HH
#include <algorithm>
namespace efl { namespace js {
enum container_type
{
list_container_type
, array_container_type
, container_type_size
};
struct eina_container_base
{
virtual ~eina_container_base() {}
virtual std::size_t size() const = 0;
virtual eina_container_base* concat(eina_container_base const& rhs) const = 0;
virtual eina_container_base* slice(std::int64_t i, std::int64_t j) const = 0;
virtual int index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
virtual int last_index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
virtual v8::Local<v8::Value> get(v8::Isolate*, std::size_t) const = 0;
virtual v8::Local<v8::String> to_string(v8::Isolate*) const = 0;
virtual container_type get_container_type() const = 0;
};
template <typename C>
struct eina_container_common;
template <typename C, typename T, typename Enable = void>
struct eina_container_type_specific;
template <typename C, typename T>
struct eina_container_type_specific
<C, T, typename std::enable_if<std::is_integral<T>::value
&& !std::is_same<T, bool>::value
&& !std::is_same<T, char>::value
&& !std::is_same<T, char16_t>::value
&& !std::is_same<T, char32_t>::value
&& !std::is_same<T, wchar_t>::value>::type>
: eina_container_base
{
v8::Local<v8::Value> get(v8::Isolate* isolate, std::size_t index) const
{
return v8::Number::New(isolate, *std::next(container_get().begin(), index));
}
int index_of(v8::Isolate*, v8::Local<v8::Value> v) const
{
std::cout << "index_of" << std::endl;
if(v->IsInt32() || v->IsUint32())
{
int64_t value = v->IntegerValue();
typedef typename C::const_iterator iterator;
iterator first = container_get().begin()
, last = container_get().end()
, found = std::find(first, last, value);
if(found == last)
return -1;
else
return std::distance(first, found);
}
else
return -1;
}
int last_index_of(v8::Isolate*, v8::Local<v8::Value> v) const
{
std::cout << "last_index_of" << std::endl;
if(v->IsInt32() || v->IsUint32())
{
int64_t value = v->IntegerValue();
auto last = container_get().rend()
, found = std::find(container_get().rbegin(), last, value);
if(found == last)
return -1;
else
return std::distance(container_get().begin(), found.base()) -1;
}
else
return -1;
}
C& container_get() { return static_cast<eina_container_common<C>&>(*this)._container; }
C const& container_get() const { return static_cast<eina_container_common<C>const&>(*this)._container; }
};
} }
#endif

View File

@ -1,4 +0,0 @@
void js_foo()
{
}

View File

@ -3,81 +3,18 @@
#include <iostream>
#include <eina_js_container.hh>
#include <Eina.hh>
#include <iterator>
namespace efl { namespace js {
struct eina_list_base
{
virtual ~eina_list_base() {}
virtual std::size_t size() const = 0;
virtual eina_list_base* concat(eina_list_base const& rhs) const = 0;
virtual eina_list_base* slice(std::int64_t i, std::int64_t j) const = 0;
virtual int index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
virtual int last_index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
virtual v8::Local<v8::Value> get(v8::Isolate*, std::size_t) const = 0;
virtual v8::Local<v8::String> to_string(v8::Isolate*) const = 0;
};
template <typename C>
struct eina_list_common;
template <typename C, typename T, typename Enable = void>
struct eina_list_type_specific;
template <typename C>
struct eina_list_type_specific<C, int> : eina_list_base
{
v8::Local<v8::Value> get(v8::Isolate* isolate, std::size_t index) const
{
return v8::Number::New(isolate, *std::next(container_get().begin(), index));
}
int index_of(v8::Isolate*, v8::Local<v8::Value> v) const
{
std::cout << "index_of" << std::endl;
if(v->IsInt32() || v->IsUint32())
{
int64_t value = v->IntegerValue();
typedef typename C::const_iterator iterator;
iterator first = container_get().begin()
, last = container_get().end()
, found = std::find(first, last, value);
if(found == last)
return -1;
else
return std::distance(first, found);
}
else
return -1;
}
int last_index_of(v8::Isolate*, v8::Local<v8::Value> v) const
{
std::cout << "last_index_of" << std::endl;
if(v->IsInt32() || v->IsUint32())
{
int64_t value = v->IntegerValue();
auto last = container_get().rend()
, found = std::find(container_get().rbegin(), last, value);
if(found == last)
return -1;
else
return std::distance(container_get().begin(), found.base()) -1;
}
else
return -1;
}
C& container_get() { return static_cast<eina_list_common<C>&>(*this)._container; }
C const& container_get() const { return static_cast<eina_list_common<C>const&>(*this)._container; }
};
template <typename C>
struct eina_list_common : eina_list_type_specific<C, typename C::value_type>
struct eina_container_common : eina_container_type_specific<C, typename C::value_type>
{
eina_list_common() : _container(0) {}
eina_list_common(Eina_List* raw) : _container(raw) {}
eina_container_common() : _container(0) {}
eina_container_common(Eina_List* raw) : _container(raw) {}
std::size_t size() const { return _container.size(); }
v8::Local<v8::String> to_string(v8::Isolate* isolate) const
@ -104,29 +41,29 @@ struct eina_list_common : eina_list_type_specific<C, typename C::value_type>
namespace detail {
template <typename T>
eina_list_base* concat(T const& self, eina_list_base const& other)
eina_container_base* concat(T const& self, eina_container_base const& other)
{
std::cout << __func__ << std::endl;
T const& rhs = static_cast<T const&>(other);
typedef typename T::container_type container_type;
container_type list(self._container.begin(), self._container.end());
list.insert(list.end(), rhs._container.begin(), rhs._container.end());
return new T(list.release_native_handle());
container_type container(self._container.begin(), self._container.end());
container.insert(container.end(), rhs._container.begin(), rhs._container.end());
return new T(container.release_native_handle());
}
template <typename T>
eina_list_base* slice(T const& self, std::int64_t i, std::int64_t j)
eina_container_base* slice(T const& self, std::int64_t i, std::int64_t j)
{
std::cout << __func__ << std::endl;
typedef typename T::container_type container_type;
container_type list(std::next(self._container.begin(), i), std::next(self._container.begin(), j));
return new T(list.release_native_handle());
container_type container(std::next(self._container.begin(), i), std::next(self._container.begin(), j));
return new T(container.release_native_handle());
}
}
template <typename T>
struct eina_list : eina_list_common<efl::eina::list
struct eina_list : eina_container_common<efl::eina::list
<T
, typename std::conditional
<std::is_base_of<efl::eo::base, T>::value
@ -134,7 +71,7 @@ struct eina_list : eina_list_common<efl::eina::list
, efl::eina::malloc_clone_allocator
>::type> >
{
typedef eina_list_common<efl::eina::list<T
typedef eina_container_common<efl::eina::list<T
, typename std::conditional
<std::is_base_of<efl::eo::base, T>::value
, efl::eina::eo_clone_allocator
@ -143,20 +80,21 @@ struct eina_list : eina_list_common<efl::eina::list
using base_type::base_type;
typedef typename base_type::container_type container_type;
eina_list_base* concat(eina_list_base const& other) const
eina_container_base* concat(eina_container_base const& other) const
{
return detail::concat(*this, other);
}
eina_list_base* slice(std::int64_t i, std::int64_t j) const
eina_container_base* slice(std::int64_t i, std::int64_t j) const
{
return detail::slice(*this, i, j);
}
js::container_type get_container_type() const { return list_container_type; }
};
template <typename T>
struct range_eina_list : eina_list_common<efl::eina::range_list<T> >
struct range_eina_list : eina_container_common<efl::eina::range_list<T> >
{
typedef eina_list_common<efl::eina::range_list<T> > base_type;
typedef eina_container_common<efl::eina::range_list<T> > base_type;
using base_type::base_type;
typedef typename base_type::container_type container_type;
typedef typename std::conditional
@ -165,7 +103,7 @@ struct range_eina_list : eina_list_common<efl::eina::range_list<T> >
, efl::eina::malloc_clone_allocator
>::type clone_allocator_type;
eina_list_base* concat(eina_list_base const& other) const
eina_container_base* concat(eina_container_base const& other) const
{
std::cout << __func__ << std::endl;
range_eina_list<T>const& rhs = static_cast<range_eina_list<T>const&>(other);
@ -174,12 +112,13 @@ struct range_eina_list : eina_list_common<efl::eina::range_list<T> >
list.insert(list.end(), rhs._container.begin(), rhs._container.end());
return new eina_list<T>(list.release_native_handle());
}
eina_list_base* slice(std::int64_t i, std::int64_t j) const
eina_container_base* slice(std::int64_t i, std::int64_t j) const
{
efl::eina::list<T, clone_allocator_type>
list(std::next(this->_container.begin(), i), std::next(this->_container.begin(), j));
return new eina_list<T>(list.release_native_handle());
}
js::container_type get_container_type() const { return list_container_type; }
};
} }

View File

@ -22,10 +22,10 @@ static const char script[] =
" }\n"
"}\n"
"print(\"teste\");\n"
"var l1 = new List(raw_list);\n"
"var l1 = raw_list;\n"
"print (\"l1 \", l1.toString());\n"
"assert (l1.length == 3)\n;\n"
"var l2 = new List(raw_list);\n"
"var l2 = raw_list;\n"
"print (\"l2 \", l2.toString());\n"
"assert (l2.length == 3)\n;\n"
"var c = l1.concat(l2);\n"
@ -123,7 +123,8 @@ void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
fflush(stdout);
}
EAPI void eina_list_register(v8::Handle<v8::ObjectTemplate> global, v8::Isolate* isolate);
EAPI void eina_container_register(v8::Handle<v8::ObjectTemplate> global, v8::Isolate* isolate);
EAPI v8::Handle<v8::FunctionTemplate> get_list_instance_template();
int main(int argc, char* argv[])
{
@ -149,7 +150,7 @@ int main(int argc, char* argv[])
// Bind the global 'print' function to the C++ Print callback.
global->Set(v8::String::NewFromUtf8(isolate, "print"),
v8::FunctionTemplate::New(isolate, Print));
eina_list_register(global, isolate);
eina_container_register(global, isolate);
// // Bind the global 'read' function to the C++ Read callback.
// global->Set(v8::String::NewFromUtf8(isolate, "read"),
// v8::FunctionTemplate::New(isolate, Read));
@ -163,9 +164,9 @@ int main(int argc, char* argv[])
// global->Set(v8::String::NewFromUtf8(isolate, "version"),
// v8::FunctionTemplate::New(isolate, Version));
global->Set(v8::String::NewFromUtf8(isolate, "raw_list")
, v8::External::New(isolate, static_cast<efl::js::eina_list_base*>(&raw_list)));
{
}
context = v8::Context::New(isolate, NULL, global);
}
if (context.IsEmpty()) {
@ -178,6 +179,10 @@ int main(int argc, char* argv[])
v8::Context::Scope context_scope(context);
v8::Local<v8::String> name(v8::String::NewFromUtf8(context->GetIsolate(), "(shell)"));
v8::Handle<v8::Value> a[] = {v8::External::New(isolate, &raw_list)};
context->Global()->Set(v8::String::NewFromUtf8(isolate, "raw_list")
, get_list_instance_template()->GetFunction()->NewInstance(1, a));
v8::HandleScope handle_scope(context->GetIsolate());
ExecuteString(context->GetIsolate(),
v8::String::NewFromUtf8(context->GetIsolate(), script),
@ -185,3 +190,4 @@ int main(int argc, char* argv[])
}
context->Exit();
}