efl js: Finish Eina_Iterator binding

This commit is contained in:
Vitor Sousa 2016-03-16 16:08:45 -03:00
parent 1422e62f30
commit a6025b5d27
8 changed files with 364 additions and 30 deletions

View File

@ -133,6 +133,22 @@ struct container_wrapper
>::type type; >::type type;
}; };
template <typename T>
inline T get_c_container_data(void* ptr, typename std::enable_if<
std::is_pointer<T>::value
>::type* = 0)
{
return static_cast<T>(ptr);
}
template <typename T>
inline T get_c_container_data(void* ptr, typename std::enable_if<
!std::is_pointer<T>::value
>::type* = 0)
{
return *static_cast<T*>(ptr);
}
template <typename T> template <typename T>
T container_wrap(T&& v) T container_wrap(T&& v)
{ {
@ -259,6 +275,12 @@ v8::Local<v8::Object> export_accessor(::efl::eina::accessor<W>&, v8::Isolate*, c
template <typename T> template <typename T>
::efl::eina::accessor<T>& import_accessor(v8::Handle<v8::Object>); ::efl::eina::accessor<T>& import_accessor(v8::Handle<v8::Object>);
// Iterator
template <typename T>
inline v8::Local<v8::Object> export_iterator(Eina_Iterator*, v8::Isolate*, const char*);
inline Eina_Iterator* import_iterator(v8::Handle<v8::Object>);
// Wrap value functions // Wrap value functions
template <typename R, typename T> template <typename R, typename T>
typename std::remove_cv<typename std::remove_reference<R>::type>::type typename std::remove_cv<typename std::remove_reference<R>::type>::type

View File

@ -333,18 +333,24 @@ inline const Eina_Array* get_value_from_javascript(
return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Array *, I...>>{}, throw_js_exception); return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Array *, I...>>{}, throw_js_exception);
} }
template <typename...I> template <typename T, typename K>
inline Eina_Iterator* get_value_from_javascript( inline Eina_Iterator* get_value_from_javascript(
v8::Local<v8::Value>, v8::Local<v8::Value> v,
v8::Isolate* isolate, v8::Isolate* isolate,
const char*, const char*,
value_tag<complex_tag<Eina_Iterator *, I...>> tag, value_tag<complex_tag<Eina_Iterator *, T, K>> /*tag*/,
bool throw_js_exception = true) bool throw_js_exception = true)
{ {
if(v->IsNull())
return nullptr;
else if(v->IsObject())
{
return import_iterator(v->ToObject());
}
if (throw_js_exception) if (throw_js_exception)
eina::js::compatibility_throw eina::js::compatibility_throw
(isolate, v8::Exception::TypeError (isolate, v8::Exception::TypeError
(eina::js::compatibility_new<v8::String>(isolate, "Not implemented yet"))); (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian accessor type")));
throw std::logic_error(""); throw std::logic_error("");
} }

View File

@ -207,18 +207,22 @@ get_value_from_c(efl::eina::js::complex_tag<const Eina_Array *, T, K> v, v8::Iso
template <typename T, typename K> template <typename T, typename K>
inline v8::Local<v8::Value> inline v8::Local<v8::Value>
get_value_from_c(efl::eina::js::complex_tag<Eina_Iterator *, T, K>, v8::Isolate*, const char*) get_value_from_c(efl::eina::js::complex_tag<Eina_Iterator *, T, K> v, v8::Isolate* isolate, const char*)
{ {
std::cerr << "get_value_from_c for Eina_Iterator not implemented. Aborting..." << std::endl; bool own = false; // TODO: handle ownership
std::abort(); auto ptr = v.value;
auto obj = export_iterator<T>(ptr , isolate, K::class_name());
if (own && ptr)
efl::eina::js::make_weak(isolate, obj, [ptr]{ ::eina_iterator_free(ptr); });
return obj;
} }
template <typename T, typename K> template <typename T, typename K>
inline v8::Local<v8::Value> inline v8::Local<v8::Value>
get_value_from_c(efl::eina::js::complex_tag<const Eina_Iterator *, T, K>, v8::Isolate*, const char*) get_value_from_c(efl::eina::js::complex_tag<const Eina_Iterator *, T, K> v, v8::Isolate* isolate, const char* class_name)
{ {
std::cerr << "get_value_from_c for Eina_Iterator not implemented. Aborting..." << std::endl; // TODO: implement const iterators?
std::abort(); return get_value_from_c(efl::eina::js::complex_tag<Eina_Iterator *, T, K>{const_cast<Eina_Iterator*>(v.value)}, isolate, class_name);
} }
template <typename T, typename KT, typename U, typename KU> template <typename T, typename KT, typename U, typename KU>

View File

@ -23,6 +23,7 @@ void register_destroy_iterator(v8::Isolate *isolate,
deleter_t deleter = compatibility_get_pointer_internal_field<deleter_t>(o, 1); deleter_t deleter = compatibility_get_pointer_internal_field<deleter_t>(o, 1);
deleter(compatibility_get_pointer_internal_field<>(o, 0)); deleter(compatibility_get_pointer_internal_field<>(o, 0));
compatibility_set_pointer_internal_field(o, 0, static_cast<void*>(0));
return compatibility_return(); return compatibility_return();
}; };

View File

@ -18,12 +18,12 @@ namespace efl { namespace eina { namespace js {
The iterator will have the `next` function, but the returned object won't The iterator will have the `next` function, but the returned object won't
have a `done` attribute, because the eina_iterator itself doesn't expose this have a `done` attribute, because the eina_iterator itself doesn't expose this
information.*/ information.*/
template<class T> template <typename T>
v8::Local<v8::Object> export_iterator(::efl::eina::iterator<T> *i, inline v8::Local<v8::Object> export_iterator(Eina_Iterator *i,
v8::Isolate *isolate) v8::Isolate *isolate,
const char *class_name)
{ {
typedef ::efl::eina::iterator<T> value_type; using no_tag_type = typename remove_tag<T>::type;
typedef value_type *ptr_type;
typedef void (*deleter_t)(void*); typedef void (*deleter_t)(void*);
auto obj_tpl = compatibility_new<v8::ObjectTemplate>(isolate); auto obj_tpl = compatibility_new<v8::ObjectTemplate>(isolate);
@ -37,20 +37,33 @@ v8::Local<v8::Object> export_iterator(::efl::eina::iterator<T> *i,
return compatibility_return(); return compatibility_return();
void *ptr = compatibility_get_pointer_internal_field(info.This(), 0); void *ptr = compatibility_get_pointer_internal_field(info.This(), 0);
auto &value = *static_cast<ptr_type>(ptr); auto it = static_cast<Eina_Iterator*>(ptr);
void *value = nullptr;
auto done = !::eina_iterator_next(it, &value);
v8::Local<v8::Object> o = compatibility_new<v8::Object>(info.GetIsolate()); v8::Local<v8::Object> o = compatibility_new<v8::Object>(info.GetIsolate());
o->Set(compatibility_new<v8::String>(info.GetIsolate(), "value"), o->Set(compatibility_new<v8::String>(info.GetIsolate(), "done"),
value_cast<v8::Local<v8::Value>>(*value, info.GetIsolate())); compatibility_new<v8::Boolean>(info.GetIsolate(), done));
++value; if (!done)
{
std::string obj_class_name;
if (info.Data()->IsString())
{
v8::String::Utf8Value str(info.Data());
obj_class_name = *str;
}
o->Set(compatibility_new<v8::String>(info.GetIsolate(), "value"),
get_value_from_c(js::wrap_value<T>(get_c_container_data<no_tag_type>(value), js::value_tag<T>{}),
info.GetIsolate(), obj_class_name.c_str()));
}
return compatibility_return(o, info); return compatibility_return(o, info);
}; };
ret->Set(compatibility_new<v8::String>(isolate, "next"), ret->Set(compatibility_new<v8::String>(isolate, "next"),
compatibility_new<v8::FunctionTemplate>(isolate, next)->GetFunction()); compatibility_new<v8::FunctionTemplate>(isolate, next, js::compatibility_new<v8::String>(isolate, class_name))->GetFunction());
{ {
deleter_t deleter = [](void *i) { deleter_t deleter = [](void *i) {
delete static_cast<ptr_type>(i); ::eina_iterator_free(static_cast<Eina_Iterator*>(i));
}; };
compatibility_set_pointer_internal_field(ret, 0, i); compatibility_set_pointer_internal_field(ret, 0, i);
compatibility_set_pointer_internal_field compatibility_set_pointer_internal_field
@ -62,15 +75,12 @@ v8::Local<v8::Object> export_iterator(::efl::eina::iterator<T> *i,
/* Extracts and returns a copy from the internal iterator object from the JS /* Extracts and returns a copy from the internal iterator object from the JS
object. */ object. */
template<class T> inline
::efl::eina::iterator<T> *import_iterator(v8::Handle<v8::Object> o) Eina_Iterator* import_iterator(v8::Handle<v8::Object> o)
; {
// { void* ptr = compatibility_get_pointer_internal_field(o, 0);
// typedef ::efl::eina::iterator<T> value_type; return static_cast<Eina_Iterator*>(ptr);
// typedef value_type *ptr_type; }
// return reinterpret_cast<ptr_type>(o->GetAlignedPointerFromInternalField(0));
// }
void register_destroy_iterator(v8::Isolate *isolate, void register_destroy_iterator(v8::Isolate *isolate,
v8::Handle<v8::Object> global, v8::Handle<v8::Object> global,

View File

@ -252,6 +252,8 @@ startTest("struct_values", function() {
assert(ret.valueEnum === suite.Test.EnumEx.FOURTH); assert(ret.valueEnum === suite.Test.EnumEx.FOURTH);
}); });
// Events //
startTest("event_simple", function() { startTest("event_simple", function() {
var v = false; var v = false;
var obj = new TestObject(null); var obj = new TestObject(null);
@ -332,6 +334,8 @@ startTest("event_stringarg", function() {
assert(v); assert(v);
}); });
// Array //
// // TODO: disabled. Not implemented yet // // TODO: disabled. Not implemented yet
// startTest("integral_array", function() { // startTest("integral_array", function() {
// var obj = new TestObject(null); // var obj = new TestObject(null);
@ -431,6 +435,8 @@ startTest("method_array_of_structs", function() {
assert(s.valueEnum === suite.Test.EnumEx.THIRD); assert(s.valueEnum === suite.Test.EnumEx.THIRD);
}); });
// List //
startTest("list_in_list_out", function() { startTest("list_in_list_out", function() {
var obj = new TestObject(null); var obj = new TestObject(null);
var newList = obj.checkMethodListWith42(); var newList = obj.checkMethodListWith42();
@ -524,6 +530,8 @@ startTest("method_list_of_structs", function() {
assert(s.valueEnum === suite.Test.EnumEx.THIRD); assert(s.valueEnum === suite.Test.EnumEx.THIRD);
}); });
// Accessor //
startTest("method_accessor_of_objects", function() { startTest("method_accessor_of_objects", function() {
var obj = new TestObject(null); var obj = new TestObject(null);
var acc = obj.checkMethodAccessorOfObjects(null); var acc = obj.checkMethodAccessorOfObjects(null);
@ -606,6 +614,125 @@ startTest("method_accessor_of_structs", function() {
assert(s.valueEnum === suite.Test.EnumEx.THIRD); assert(s.valueEnum === suite.Test.EnumEx.THIRD);
}); });
// Iterator //
startTest("method_iterator_of_objects", function() {
var obj = new TestObject(null);
var it = obj.checkMethodIteratorOfObjects(null);
assert(it != null);
it = obj.checkMethodIteratorOfObjects(it);
assert(it != null);
var idx = 0;
for (var n = it.next(); !n.done; n = it.next()) {
var v = n.value;
assert(v != null);
var expectedValue = 1234;
v.checkMethodIntegralInA(expectedValue);
var actualValue = v.checkMethodIntegralOutA();
assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
idx++;
}
assert(idx == 2, idx + " == 2");
});
startTest("method_iterator_of_strings", function() {
var obj = new TestObject(null);
var it = obj.checkMethodIteratorOfStrings(null);
assert(it != null);
it = obj.checkMethodIteratorOfStrings(it);
assert(it != null);
var cmp = ["foo", "bar"];
var idx = 0;
for (var n = it.next(); !n.done; n = it.next()) {
var v = n.value;
assert(v === cmp[idx], idx+": "+v+" === "+cmp[idx]);
idx++;
}
assert(idx == 2, idx + " == 2");
});
startTest("method_iterator_of_ints", function() {
var obj = new TestObject(null);
var it = obj.checkMethodIteratorOfInts(null);
assert(it != null);
it = obj.checkMethodIteratorOfInts(it);
assert(it != null);
var cmp = [42, 24];
var idx = 0;
for (var n = it.next(); !n.done; n = it.next()) {
var v = n.value;
assert(v === cmp[idx], idx+": "+v+" === "+cmp[idx]);
idx++;
}
assert(idx == 2, idx + " == 2");
});
startTest("method_iterator_of_bools", function() {
var obj = new TestObject(null);
var it = obj.checkMethodIteratorOfBools(null);
assert(it != null);
it = obj.checkMethodIteratorOfBools(it);
assert(it != null);
var cmp = [true, false];
var idx = 0;
for (var n = it.next(); !n.done; n = it.next()) {
var v = n.value;
assert(v === cmp[idx], idx+": "+v+" === "+cmp[idx]);
idx++;
}
assert(idx == 2, idx + " == 2");
});
startTest("method_iterator_of_doubles", function() {
var obj = new TestObject(null);
var it = obj.checkMethodIteratorOfDoubles(null);
assert(it != null);
it = obj.checkMethodIteratorOfDoubles(it);
assert(it != null);
var cmp = [42.0, 24.0];
var idx = 0;
for (var n = it.next(); !n.done; n = it.next()) {
var v = n.value;
assert(v === cmp[idx], idx+": "+v+" === "+cmp[idx]);
idx++;
}
assert(idx == 2, idx + " == 2");
});
startTest("method_iterator_of_enums", function() {
var obj = new TestObject(null);
var it = obj.checkMethodIteratorOfEnums(null);
assert(it != null);
it = obj.checkMethodIteratorOfEnums(it);
assert(it != null);
var cmp = [suite.Test.EnumEx.THIRD, suite.Test.EnumEx.FIRST];
var idx = 0;
for (var n = it.next(); !n.done; n = it.next()) {
var v = n.value;
assert(v === cmp[idx], idx+": "+v+" === "+cmp[idx]);
idx++;
}
assert(idx == 2, idx + " == 2");
});
startTest("method_iterator_of_structs", function() {
var obj = new TestObject(null);
var it = obj.checkMethodIteratorOfStructs(null);
assert(it != null);
it = obj.checkMethodIteratorOfStructs(it);
assert(it != null);
var cmp = [[42, suite.Test.EnumEx.THIRD], [24, suite.Test.EnumEx.FIRST]];
var idx = 0;
for (var n = it.next(); !n.done; n = it.next()) {
var v = n.value;
assert(v != null);
assert(v.valueInt === cmp[idx][0], idx+": "+v.valueInt+" === "+cmp[idx][0]);
assert(v.valueEnum === cmp[idx][1], idx+": "+v.valueEnum+" === "+cmp[idx][1]);
idx++;
}
assert(idx == 2, idx + " == 2");
});
// Combinations of complex types // // Combinations of complex types //
// FIXME // FIXME

View File

@ -587,6 +587,128 @@ _test_object_method_accessor_of_structs_check(Eo* obj EINA_UNUSED,
return eina_array_accessor_new(arr); return eina_array_accessor_new(arr);
} }
// Iterator //
EOLIAN static Eina_Iterator *
_test_object_method_iterator_of_objects_check(Eo* obj,
Test_Object_Data *pd EINA_UNUSED,
Eina_Iterator *i_in)
{
fprintf(stdout, "_test_object_method_iterator_of_objects_check(%p)\n", i_in);
fflush(stdout);
if (i_in) return i_in;
Eina_Array *arr = eina_array_new(2);
eina_array_push(arr, obj);
eina_array_push(arr, obj);
return eina_array_iterator_new(arr);
}
EOLIAN static Eina_Iterator *
_test_object_method_iterator_of_strings_check(Eo* obj EINA_UNUSED,
Test_Object_Data *pd EINA_UNUSED,
Eina_Iterator *i_in)
{
fprintf(stdout, "_test_object_method_iterator_of_strings_check(%p)\n", i_in);
fflush(stdout);
if (i_in) return i_in;
Eina_Array *arr = eina_array_new(2);
eina_array_push(arr, "foo");
eina_array_push(arr, "bar");
return eina_array_iterator_new(arr);
}
EOLIAN static Eina_Iterator *
_test_object_method_iterator_of_ints_check(Eo* obj EINA_UNUSED,
Test_Object_Data *pd EINA_UNUSED,
Eina_Iterator *i_in)
{
fprintf(stdout, "_test_object_method_iterator_of_ints_check(%p)\n", i_in);
fflush(stdout);
if (i_in) return i_in;
Eina_Array *arr = eina_array_new(2);
int *v = malloc(sizeof(int));
*v = 42;
eina_array_push(arr, v);
v = malloc(sizeof(int));
*v = 24;
eina_array_push(arr, v);
return eina_array_iterator_new(arr);
}
EOLIAN static Eina_Iterator *
_test_object_method_iterator_of_bools_check(Eo* obj EINA_UNUSED,
Test_Object_Data *pd EINA_UNUSED,
Eina_Iterator *i_in)
{
fprintf(stdout, "_test_object_method_iterator_of_bools_check(%p)\n", i_in);
fflush(stdout);
if (i_in) return i_in;
Eina_Array *arr = eina_array_new(2);
Eina_Bool *v = malloc(sizeof(Eina_Bool));
*v = EINA_TRUE;
eina_array_push(arr, v);
v = malloc(sizeof(Eina_Bool));
*v = EINA_FALSE;
eina_array_push(arr, v);
return eina_array_iterator_new(arr);
}
EOLIAN static Eina_Iterator *
_test_object_method_iterator_of_doubles_check(Eo* obj EINA_UNUSED,
Test_Object_Data *pd EINA_UNUSED,
Eina_Iterator *i_in)
{
fprintf(stdout, "_test_object_method_iterator_of_doubles_check(%p)\n", i_in);
fflush(stdout);
if (i_in) return i_in;
Eina_Array *arr = eina_array_new(2);
double *v = malloc(sizeof(double));
*v = 42.0;
eina_array_push(arr, v);
v = malloc(sizeof(double));
*v = 24.0;
eina_array_push(arr, v);
return eina_array_iterator_new(arr);
}
EOLIAN static Eina_Iterator *
_test_object_method_iterator_of_enums_check(Eo* obj EINA_UNUSED,
Test_Object_Data *pd EINA_UNUSED,
Eina_Iterator *i_in)
{
fprintf(stdout, "_test_object_method_iterator_of_enums_check(%p)\n", i_in);
fflush(stdout);
if (i_in) return i_in;
Eina_Array *arr = eina_array_new(2);
Test_Enum_Ex *v = malloc(sizeof(Test_Enum_Ex));
*v = TEST_ENUM_EX_THIRD;
eina_array_push(arr, v);
v = malloc(sizeof(Test_Enum_Ex));
*v = TEST_ENUM_EX_FIRST;
eina_array_push(arr, v);
return eina_array_iterator_new(arr);
}
EOLIAN static Eina_Iterator *
_test_object_method_iterator_of_structs_check(Eo* obj EINA_UNUSED,
Test_Object_Data *pd EINA_UNUSED,
Eina_Iterator *i_in)
{
fprintf(stdout, "_test_object_method_iterator_of_structs_check(%p)\n", i_in);
fflush(stdout);
if (i_in) return i_in;
Eina_Array *arr = eina_array_new(2);
Test_Struct_Ex *v = malloc(sizeof(Test_Struct_Ex));
v->value_int = 42;
v->value_enum = TEST_ENUM_EX_THIRD;
eina_array_push(arr, v);
v = malloc(sizeof(Test_Struct_Ex));
v->value_int = 24;
v->value_enum = TEST_ENUM_EX_FIRST;
eina_array_push(arr, v);
return eina_array_iterator_new(arr);
}
// Combinations of complex types // Combinations of complex types
EOLIAN static Eina_List * EOLIAN static Eina_List *

View File

@ -251,6 +251,48 @@ class Test.Object (Eo.Base) {
} }
return: accessor<Test.Struct_Ex> *; return: accessor<Test.Struct_Ex> *;
} }
method_iterator_of_objects_check {
params {
@in i_in: iterator<Test.Object *> *;
}
return: iterator<Test.Object *> *;
}
method_iterator_of_strings_check {
params {
@in i_in: iterator<const(char) *> *;
}
return: iterator<const(char) *> *;
}
method_iterator_of_ints_check {
params {
@in i_in: iterator<int> *;
}
return: iterator<int> *;
}
method_iterator_of_bools_check {
params {
@in i_in: iterator<bool> *;
}
return: iterator<bool> *;
}
method_iterator_of_doubles_check {
params {
@in i_in: iterator<double> *;
}
return: iterator<double> *;
}
method_iterator_of_enums_check {
params {
@in i_in: iterator<Test.Enum_Ex> *;
}
return: iterator<Test.Enum_Ex> *;
}
method_iterator_of_structs_check {
params {
@in i_in: iterator<Test.Struct_Ex> *;
}
return: iterator<Test.Struct_Ex> *;
}
method_array_of_arrays_of_ints_check { method_array_of_arrays_of_ints_check {
params { params {
@in a_in: array<array<int> *> *; @in a_in: array<array<int> *> *;