Explorar o código

add jerry_callbacks.c jerry_event.c

yangfasheng %!s(int64=7) %!d(string=hai) anos
pai
achega
31e90234d5

+ 149 - 0
rtthread-port/jerry_callbacks.c

@@ -0,0 +1,149 @@
+
+
+#include <jerry_callbacks.h>
+
+struct js_callback *_js_callback = NULL;
+static js_mq_func _js_mq_func = NULL;
+
+static void append_callback(struct js_callback *callback)
+{
+    struct js_callback *_callback = _js_callback;
+
+    if (_js_callback == NULL)
+    {
+        _js_callback = callback;
+        return;
+    }
+
+    while (_callback->next != NULL)
+    {
+        _callback = _callback->next;
+    }
+
+    _callback->next = callback;
+}
+
+static void remove_callback(struct js_callback *callback)
+{
+    struct js_callback *_callback_free, *_callback = _js_callback;
+
+    if (_js_callback == callback)
+    {
+        _js_callback = _js_callback->next;
+        rt_free(_callback);
+        return;
+    }
+
+    while (_callback->next != NULL)
+    {
+        if (_callback == callback)
+        {
+            _callback_free = _callback;
+            _callback = _callback->next;
+            rt_free(_callback_free);
+            break;
+        }
+
+        _callback = _callback->next;
+    }
+}
+
+static rt_bool_t has_callback(struct js_callback *callback)
+{
+    struct js_callback *_callback = _js_callback;
+
+    if (callback == NULL)
+    {
+        return RT_FALSE;
+    }
+
+    while (_callback != NULL)
+    {
+        if (_callback == callback)
+        {
+            return RT_TRUE;
+        }
+    }
+
+    return RT_FALSE;
+}
+
+struct js_callback *js_add_callback(js_callback_func callback)
+{
+    struct js_callback *cb = (struct js_callback *)rt_calloc(1, sizeof(struct js_callback));
+    if (!cb)
+    {
+        return NULL;
+    }
+
+    cb->function = callback;
+    cb->next = NULL;
+
+    append_callback(cb);
+
+    return cb;
+}
+
+void js_remove_callback(struct js_callback *callback)
+{
+    remove_callback(callback);
+}
+
+void js_remove_all_callbacks(void)
+{
+    struct js_callback *_callback_free, *_callback = _js_callback;
+
+    while (_callback != NULL)
+    {
+        _callback_free = _callback;
+        _callback = _callback->next;
+        rt_free(_callback_free);
+    }
+
+    _js_callback = NULL;
+}
+
+void js_call_callback(struct js_callback *callback, const void *data, uint32_t size)
+{
+    if (has_callback(callback))
+    {
+        if (callback->function)
+        {
+            callback->function(data, size);
+        }
+    }
+}
+
+void js_send_callback(struct js_callback *callback, const void *args, uint32_t size)
+{
+    rt_bool_t ret = RT_FALSE;
+    struct js_mq_callback *jmc = NULL;
+
+    jmc = (struct js_mq_callback *)rt_calloc(1, sizeof(struct js_mq_callback));
+    if (jmc)
+    {
+        jmc->callback = callback;
+        jmc->args = rt_malloc(size);
+        if (jmc->args && args)
+        {
+            memcpy(jmc->args, args, size);
+        }
+        jmc->size = size;
+
+        if (_js_mq_func)
+        {
+            ret = _js_mq_func(jmc);
+        }
+
+        if (ret == RT_FALSE)
+        {
+            rt_free(jmc->args);
+            rt_free(jmc);
+        }
+    }
+}
+
+void js_mq_func_set(js_mq_func signal)
+{
+    _js_mq_func = signal;
+}

+ 41 - 0
rtthread-port/jerry_callbacks.h

@@ -0,0 +1,41 @@
+
+
+#ifndef JERRY_BUFFER_H__
+#define JERRY_BUFFER_H__
+
+#include <rtthread.h>
+#include <jerry_util.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void(*js_callback_func)(const void *args, uint32_t size);
+typedef rt_bool_t(*js_mq_func)(void *args);
+
+struct js_callback
+{
+    js_callback_func function;
+    uint8_t flags;
+    struct js_callback *next;
+};
+
+struct js_mq_callback
+{
+    struct js_callback *callback;
+    void *args;
+    uint32_t size;
+};
+
+struct js_callback *js_add_callback(js_callback_func callback);
+void js_remove_callback(struct js_callback *callback);
+void js_remove_all_callbacks(void);
+void js_call_callback(struct js_callback *callback, const void *data, uint32_t size);
+void js_send_callback(struct js_callback *callback, const void *args, uint32_t size);
+void js_mq_func_set(js_mq_func signal);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 443 - 0
rtthread-port/jerry_event.c

@@ -0,0 +1,443 @@
+
+
+#include <jerry_event.h>
+
+static jerry_value_t _js_emitter_prototype = 0;
+
+struct js_listener
+{
+    jerry_value_t func;
+    struct js_listener *next;
+};
+
+struct js_event
+{
+    char *name;
+    struct js_listener *listeners;
+    struct js_event *next;
+};
+
+struct js_emitter
+{
+    struct js_event *events;
+};
+
+static void free_listener(void *ptr)
+{
+    if (ptr)
+    {
+        struct js_listener *listener = (struct js_listener *)ptr;
+        jerry_release_value(listener->func);
+        rt_free(listener);
+    }
+}
+
+static void js_emitter_free_cb(void *native)
+{
+    struct js_emitter *emitter = (struct js_emitter *)native;
+    struct js_event *_event,  *event = emitter->events;
+
+    while (event)
+    {
+        struct js_listener *_listener, *listener = event->listeners;
+
+        while (listener != NULL)
+        {
+            _listener = listener;
+            listener = listener->next;
+            free_listener(_listener);
+        }
+
+        _event = event;
+        event = event->next;
+
+        rt_free(_event->name);
+        rt_free(_event);
+    }
+
+    rt_free(emitter);
+}
+
+static const jerry_object_native_info_t emitter_type_info =
+{
+    .free_cb = js_emitter_free_cb
+};
+
+static void js_event_proto_free_cb(void *native)
+{
+    _js_emitter_prototype = 0;
+}
+
+static const jerry_object_native_info_t event_proto_type_info =
+{
+    .free_cb = js_event_proto_free_cb
+};
+
+static struct js_listener *find_listener(struct js_event *event, jerry_value_t func)
+{
+    struct js_listener *_listener = event->listeners;
+
+    while (_listener != NULL)
+    {
+        if (_listener->func == func)
+        {
+            break;
+        }
+
+        _listener = _listener->next;
+    }
+
+    return _listener;
+}
+
+static void append_listener(struct js_event *event, struct js_listener *listener)
+{
+    struct js_listener *_listener = event->listeners;
+
+    if (event->listeners == NULL)
+    {
+        event->listeners = listener;
+        return;
+    }
+
+    while (_listener->next != NULL)
+    {
+        _listener = _listener->next;
+    }
+
+    _listener->next = listener;
+}
+
+static void remove_listener(struct js_event *event, struct js_listener *listener)
+{
+    struct js_listener *_listener = event->listeners;
+
+    if (event->listeners == listener || event->listeners == NULL)
+    {
+        event->listeners = NULL;
+        return;
+    }
+
+    while (_listener->next != listener)
+    {
+        _listener = _listener->next;
+    }
+
+    _listener->next = listener->next;
+}
+
+static struct js_event *find_event(struct js_emitter *emitter, const char *event_name)
+{
+    struct js_event *event = emitter->events;
+
+    while (event != NULL)
+    {
+        if (strcmp(event->name, event_name) == 0)
+        {
+            break;
+        }
+
+        event = event->next;
+    }
+
+    return event;
+}
+
+static void append_event(struct js_emitter *emitter, struct js_event *event)
+{
+    struct js_event *_event = emitter->events;
+
+    if (emitter->events == NULL)
+    {
+        emitter->events = event;
+        return;
+    }
+
+    while (_event->next != NULL)
+    {
+        _event = _event->next;
+    }
+
+    _event->next = event;
+}
+
+jerry_value_t js_add_event_listener(jerry_value_t obj, const char *event_name, jerry_value_t func)
+{
+    void* native_handle = NULL;
+    struct js_event *event = NULL;
+    struct js_listener *listener = NULL;
+
+    jerry_get_object_native_pointer(obj, &native_handle, NULL);
+
+    event = find_event((struct js_emitter *)native_handle, event_name);
+    if (!event)
+    {
+        event = (struct js_event *)rt_malloc(sizeof(struct js_event));
+        if (!event)
+        {
+            return jerry_create_undefined();
+        }
+
+        event->next = NULL;
+        event->listeners = NULL;
+        event->name = rt_strdup(event_name);
+        append_event((struct js_emitter *)native_handle, event);
+    }
+
+    listener = (struct js_listener *)rt_malloc(sizeof(struct js_listener));
+    if (!listener)
+    {
+        rt_free(event->name);
+        rt_free(event);
+        return jerry_create_undefined();
+    }
+
+    listener->func = jerry_acquire_value(func);
+    listener->next = NULL;
+
+    append_listener(event, listener);
+
+    return jerry_create_undefined();
+}
+
+rt_bool_t js_emit_event(jerry_value_t obj, const char *event_name, const jerry_value_t argv[], const jerry_length_t argc)
+{
+    void* native_handle = NULL;
+    struct js_event *event = NULL;
+
+    jerry_get_object_native_pointer(obj, &native_handle, NULL);
+
+    event = find_event((struct js_emitter *)native_handle, event_name);
+    if (event)
+    {
+        struct js_listener *listener = event->listeners;
+
+        while (listener)
+        {
+            jerry_value_t ret = jerry_call_function(listener->func, obj, argv, argc);
+            if (jerry_value_is_error(ret))
+            {
+                rt_kprintf("error calling listener\n");
+            }
+            listener = listener->next;
+        }
+
+        return RT_TRUE;
+    }
+
+    return RT_FALSE;
+}
+
+DECLARE_HANDLER(add_listener)
+{
+    if (args_cnt == 2)
+    {
+        char *name = js_value_to_string(args[0]);
+        if (name)
+        {
+            js_add_event_listener(this_value, name, args[1]);
+        }
+
+        rt_free(name);
+    }
+
+    return jerry_acquire_value(this_value);
+}
+
+DECLARE_HANDLER(remove_listener)
+{
+    if (args_cnt == 2)
+    {
+        char *name = js_value_to_string(args[0]);
+        if (name)
+        {
+            void* native_handle = NULL;
+            struct js_event *event = NULL;
+            struct js_listener *listener = NULL;
+
+            jerry_get_object_native_pointer(this_value, &native_handle, NULL);
+
+            event = find_event((struct js_emitter *)native_handle, name);
+            if (event)
+            {
+                listener = find_listener(event, args[1]);
+                if (listener)
+                {
+                    remove_listener(event, listener);
+                    free_listener(listener);
+                }
+            }
+        }
+
+        rt_free(name);
+    }
+
+    return jerry_acquire_value(this_value);
+}
+
+DECLARE_HANDLER(remove_all_listeners)
+{
+    if (args_cnt == 1)
+    {
+        char *name = js_value_to_string(args[0]);
+        if (name)
+        {
+            void* native_handle = NULL;
+            struct js_event *event = NULL;
+
+            jerry_get_object_native_pointer(this_value, &native_handle, NULL);
+
+            event = find_event((struct js_emitter *)native_handle, name);
+            if (event)
+            {
+                struct js_listener *_listener, *listener = event->listeners;
+
+                while (listener != NULL)
+                {
+                    _listener = listener;
+                    listener = listener->next;
+                    free_listener(_listener);
+                }
+
+                event->listeners = NULL;
+            }
+        }
+
+        rt_free(name);
+    }
+
+    return jerry_acquire_value(this_value);
+}
+
+DECLARE_HANDLER(emit_event)
+{
+    rt_bool_t ret = RT_FALSE;
+
+    if (args_cnt > 1)
+    {
+        char *name = js_value_to_string(args[0]);
+        if (name)
+        {
+            ret = js_emit_event(this_value, name, args + 1, args_cnt - 1);
+        }
+
+        rt_free(name);
+    }
+
+    return jerry_create_boolean(ret);
+}
+
+DECLARE_HANDLER(get_event_names)
+{
+    uint32_t i = 0;
+    void* native_handle = NULL;
+    struct js_event *event = NULL;
+    jerry_value_t ret;
+
+
+    jerry_get_object_native_pointer(this_value, &native_handle, NULL);
+
+    event = ((struct js_emitter *)native_handle)->events;
+    while (event)
+    {
+        i++;
+        event = event->next;
+    }
+
+    ret = jerry_create_array(i);
+    event = ((struct js_emitter *)native_handle)->events;
+    i = 0;
+    while (event)
+    {
+        jerry_set_property_by_index(ret, i++, jerry_create_string((jerry_char_t *)event->name));
+        event = event->next;
+    }
+
+    return ret;
+}
+
+void js_destroy_emitter(jerry_value_t obj)
+{
+    void* native_handle = NULL;
+    struct js_event *event = NULL;
+
+    jerry_get_object_native_pointer(obj, &native_handle, NULL);
+
+    if (native_handle)
+    {
+        struct js_emitter *emitter = (struct js_emitter *)native_handle;
+        struct js_event *_event,  *event = emitter->events;
+
+        while (event)
+        {
+            struct js_listener *_listener, *listener = event->listeners;
+
+            while (listener != NULL)
+            {
+                _listener = listener;
+                listener = listener->next;
+                free_listener(_listener);
+            }
+
+            _event = event;
+            event = event->next;
+
+            rt_free(_event->name);
+            rt_free(_event);
+        }
+
+        emitter->events = NULL;
+    }
+}
+
+static void js_event_init_prototype(void)
+{
+    if (!_js_emitter_prototype)
+    {
+        _js_emitter_prototype = jerry_create_object();
+
+        REGISTER_METHOD_NAME(_js_emitter_prototype, "on", add_listener);
+        REGISTER_METHOD_NAME(_js_emitter_prototype, "addListener", add_listener);
+        REGISTER_METHOD_NAME(_js_emitter_prototype, "emit", emit_event);
+        REGISTER_METHOD_NAME(_js_emitter_prototype, "removeListener", remove_listener);
+        REGISTER_METHOD_NAME(_js_emitter_prototype, "removeAllListeners", remove_all_listeners);
+        REGISTER_METHOD_NAME(_js_emitter_prototype, "eventNames", get_event_names);
+
+        jerry_set_object_native_pointer(_js_emitter_prototype, NULL, &event_proto_type_info);
+    }
+}
+
+void js_make_emitter(jerry_value_t obj, jerry_value_t prototype)
+{
+    jerry_value_t proto;
+    struct js_emitter *emitter = NULL;
+
+    js_event_init_prototype();
+    proto = _js_emitter_prototype;
+    if (jerry_value_is_object(prototype))
+    {
+        jerry_set_prototype(prototype, proto);
+        proto = prototype;
+    }
+    jerry_set_prototype(obj, proto);
+
+    emitter = rt_malloc(sizeof(struct js_emitter));
+    if (emitter)
+    {
+        emitter->events = NULL;
+        jerry_set_object_native_pointer(obj, emitter, &emitter_type_info);
+    }
+}
+
+DECLARE_HANDLER(Event)
+{
+    jerry_value_t emitter = jerry_create_object();
+    js_make_emitter(emitter, jerry_create_undefined());
+    return emitter;
+}
+
+int js_event_init(void)
+{
+    REGISTER_HANDLER(Event);
+    return 0;
+}

+ 22 - 0
rtthread-port/jerry_event.h

@@ -0,0 +1,22 @@
+
+#ifndef JERRY_EVENT_H__
+#define JERRY_EVENT_H__
+
+#include <rtthread.h>
+#include <jerry_util.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+jerry_value_t js_add_event_listener(jerry_value_t obj, const char *event_name, jerry_value_t func);
+rt_bool_t js_emit_event(jerry_value_t obj, const char *event_name, const jerry_value_t argv[], const jerry_length_t argc);
+void js_destroy_emitter(jerry_value_t obj);
+void js_make_emitter(jerry_value_t obj, jerry_value_t prototype);
+int js_event_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 4 - 1
rtthread-port/jerry_util.c

@@ -182,6 +182,7 @@ void js_value_dump(jerry_value_t value)
         {
             jerry_value_t item = jerry_get_property_by_index(value, index);
             js_value_dump(item);
+            printf(" , ");
             jerry_release_value(item);
         }
         printf("]\n");
@@ -236,6 +237,7 @@ extern int js_console_init();
 extern int js_module_init();
 extern int js_buffer_init();
 extern int js_buffer_cleanup();
+extern int js_event_init(void);
 
 int js_util_init(void)
 {
@@ -245,6 +247,7 @@ int js_util_init(void)
     js_console_init();
     js_module_init();
     js_buffer_init();
+    js_event_init();
 
     return 0;
 }
@@ -252,7 +255,7 @@ int js_util_init(void)
 int js_util_cleanup(void)
 {
     js_buffer_cleanup();
-	
+
     return 0;
 }
 

+ 2 - 0
rtthread-port/jerry_util.h

@@ -18,6 +18,8 @@
     js_add_function (OBJ, # NAME, NAME ## _handler)
 #define REGISTER_METHOD_ALIAS(OBJ, NAME, HANDLER) \
     js_add_function (OBJ, # NAME, HANDLER)
+#define REGISTER_METHOD_NAME(OBJ, NAME, HANDLER)  \
+    js_add_function (OBJ, NAME, HANDLER ## _handler)
 
 #ifdef RT_USING_FINSH
 #include <finsh.h>