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;
};
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>
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>
::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
template <typename R, typename T>
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);
}
template <typename...I>
template <typename T, typename K>
inline Eina_Iterator* get_value_from_javascript(
v8::Local<v8::Value>,
v8::Local<v8::Value> v,
v8::Isolate* isolate,
const char*,
value_tag<complex_tag<Eina_Iterator *, I...>> tag,
value_tag<complex_tag<Eina_Iterator *, T, K>> /*tag*/,
bool throw_js_exception = true)
{
if(v->IsNull())
return nullptr;
else if(v->IsObject())
{
return import_iterator(v->ToObject());
}
if (throw_js_exception)
eina::js::compatibility_throw
(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("");
}

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>
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;
std::abort();
bool own = false; // TODO: handle ownership
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>
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;
std::abort();
// TODO: implement const iterators?
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>

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(compatibility_get_pointer_internal_field<>(o, 0));
compatibility_set_pointer_internal_field(o, 0, static_cast<void*>(0));
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
have a `done` attribute, because the eina_iterator itself doesn't expose this
information.*/
template<class T>
v8::Local<v8::Object> export_iterator(::efl::eina::iterator<T> *i,
v8::Isolate *isolate)
template <typename T>
inline v8::Local<v8::Object> export_iterator(Eina_Iterator *i,
v8::Isolate *isolate,
const char *class_name)
{
typedef ::efl::eina::iterator<T> value_type;
typedef value_type *ptr_type;
using no_tag_type = typename remove_tag<T>::type;
typedef void (*deleter_t)(void*);
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();
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());
o->Set(compatibility_new<v8::String>(info.GetIsolate(), "value"),
value_cast<v8::Local<v8::Value>>(*value, info.GetIsolate()));
++value;
o->Set(compatibility_new<v8::String>(info.GetIsolate(), "done"),
compatibility_new<v8::Boolean>(info.GetIsolate(), done));
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);
};
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) {
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
@ -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
object. */
template<class T>
::efl::eina::iterator<T> *import_iterator(v8::Handle<v8::Object> o)
;
// {
// typedef ::efl::eina::iterator<T> value_type;
// typedef value_type *ptr_type;
// return reinterpret_cast<ptr_type>(o->GetAlignedPointerFromInternalField(0));
// }
inline
Eina_Iterator* import_iterator(v8::Handle<v8::Object> o)
{
void* ptr = compatibility_get_pointer_internal_field(o, 0);
return static_cast<Eina_Iterator*>(ptr);
}
void register_destroy_iterator(v8::Isolate *isolate,
v8::Handle<v8::Object> global,

View File

@ -252,6 +252,8 @@ startTest("struct_values", function() {
assert(ret.valueEnum === suite.Test.EnumEx.FOURTH);
});
// Events //
startTest("event_simple", function() {
var v = false;
var obj = new TestObject(null);
@ -332,6 +334,8 @@ startTest("event_stringarg", function() {
assert(v);
});
// Array //
// // TODO: disabled. Not implemented yet
// startTest("integral_array", function() {
// var obj = new TestObject(null);
@ -431,6 +435,8 @@ startTest("method_array_of_structs", function() {
assert(s.valueEnum === suite.Test.EnumEx.THIRD);
});
// List //
startTest("list_in_list_out", function() {
var obj = new TestObject(null);
var newList = obj.checkMethodListWith42();
@ -524,6 +530,8 @@ startTest("method_list_of_structs", function() {
assert(s.valueEnum === suite.Test.EnumEx.THIRD);
});
// Accessor //
startTest("method_accessor_of_objects", function() {
var obj = new TestObject(null);
var acc = obj.checkMethodAccessorOfObjects(null);
@ -606,6 +614,125 @@ startTest("method_accessor_of_structs", function() {
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 //
// FIXME

View File

@ -587,6 +587,128 @@ _test_object_method_accessor_of_structs_check(Eo* obj EINA_UNUSED,
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
EOLIAN static Eina_List *

View File

@ -251,6 +251,48 @@ class Test.Object (Eo.Base) {
}
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 {
params {
@in a_in: array<array<int> *> *;