Compare commits

...

5 Commits

Author SHA1 Message Date
Cedric BAIL ad7c9b5c58 eio: instantiate some default Efl.Io.Manager and an Efl.Uri.Mapper for files. 2016-06-22 14:39:33 -07:00
Cedric BAIL fc1271d178 eio: add an Efl.Uri.Mapper for file.
We will need a way to initialize Eio on a specific main loop. Maybe
by manually creating an Efl.Io.Manager and registering it on one.
Don't know. This is for later.
2016-06-22 14:39:33 -07:00
Cedric BAIL 3981d99669 ecore: handle default mapper. 2016-06-22 14:39:33 -07:00
Cedric BAIL f3e103a983 ecore: automatically add an Efl.Uri.Manager to the main loop provider. 2016-06-22 14:39:33 -07:00
Cedric BAIL 1b28a27fbe ecore: add an Efl.Uri_Manager.
efl_uri_manager done, need to add default mapper and a fetcher in efreet.
2016-06-22 14:39:33 -07:00
14 changed files with 554 additions and 4 deletions

View File

@ -10,14 +10,20 @@ ecore_eolian_files = \
lib/ecore/efl_loop.eo \
lib/ecore/efl_loop_user.eo \
lib/ecore/efl_loop_fd.eo \
lib/ecore/efl_uri_manager.eo \
lib/ecore/efl_uri_mapper.eo \
lib/ecore/efl_uri_fetcher.eo \
lib/ecore/ecore_parent.eo \
$(ecore_eolian_files_legacy)
ecore_eolian_files_internal = \
$(ecore_eolian_files)
ecore_eolian_type_files = \
lib/ecore/ecore_types.eot
ecore_eolian_c = $(ecore_eolian_files:%.eo=%.eo.c)
ecore_eolian_h = $(ecore_eolian_files:%.eo=%.eo.h) \
ecore_eolian_c = $(ecore_eolian_files_internal:%.eo=%.eo.c)
ecore_eolian_h = $(ecore_eolian_files_internal:%.eo=%.eo.h) \
$(ecore_eolian_files_legacy:%.eo=%.eo.legacy.h) \
$(ecore_eolian_type_files:%.eot=%.eot.h)
@ -61,6 +67,7 @@ lib/ecore/ecore_job.c \
lib/ecore/ecore_main.c \
lib/ecore/efl_loop_user.c \
lib/ecore/efl_loop_fd.c \
lib/ecore/efl_uri_manager.c \
lib/ecore/ecore_pipe.c \
lib/ecore/ecore_poller.c \
lib/ecore/ecore_time.c \

View File

@ -6,8 +6,12 @@ eio_eolian_files = \
lib/eio/efl_io_manager.eo \
lib/eio/eio_sentry.eo
eio_eolian_h = $(eio_eolian_files:%.eo=%.eo.h)
eio_eolian_c = $(eio_eolian_files:%.eo=%.eo.c)
eio_eolian_files_private = \
lib/eio/efl_uri_mapper_file.eo \
$(eio_eolian_files)
eio_eolian_h = $(eio_eolian_files_private:%.eo=%.eo.h)
eio_eolian_c = $(eio_eolian_files_private:%.eo=%.eo.c)
BUILT_SOURCES += $(eio_eolian_c) $(eio_eolian_h)
@ -42,6 +46,7 @@ lib/eio/eio_monitor_poll.c \
lib/eio/eio_single.c \
lib/eio/eio_xattr.c \
lib/eio/eio_model.c \
lib/eio/efl_uri_mapper_file.c \
lib/eio/eio_model_private.h \
lib/eio/eio_private.h \
lib/eio/eio_sentry_private.h

View File

@ -54,6 +54,12 @@ extern "C" {
#include "efl_loop_fd.eo.h"
#include "efl_uri_fetcher.eo.h"
#include "efl_uri_mapper.eo.h"
#include "efl_uri_manager.eo.h"
/* We ue the factory pattern here, so you shouldn't call eo_add directly. */
EAPI Eo *ecore_main_loop_get(void);

View File

@ -2807,6 +2807,16 @@ _efl_loop_eo_base_constructor(Eo *obj, Efl_Loop_Data *pd)
return obj;
}
EOLIAN static Eo_Base *
_efl_loop_eo_base_finalize(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
{
// Every loop object once build as an URI manager
// Wondering if it should be available earlier.
eo_add(EFL_URI_MANAGER_CLASS, obj);
return obj;
}
EOLIAN static void
_efl_loop_eo_base_destructor(Eo *obj, Efl_Loop_Data *pd)
{

View File

@ -151,6 +151,9 @@ EAPI void _ecore_magic_fail(const void *d,
const char *fname);
EAPI void ecore_loop_arguments_send(int argc, const char **argv);
EAPI void efl_uri_manager_default_set(Efl_Uri_Manager *obj, Efl_Uri_Mapper *def);
void _ecore_time_init(void);
void *_efl_loop_timer_del(Ecore_Timer *timer);

View File

@ -74,6 +74,7 @@ class Efl.Loop (Eo.Base)
}
implements {
Eo.Base.constructor;
Eo.Base.finalize;
Eo.Base.destructor;
Eo.Base.provider_find;
}

View File

@ -0,0 +1,13 @@
import eina_types;
interface Efl.Uri.Fetcher
{
methods {
fetch {
params {
@in file: const(char)*;
}
return: promise<Eina.Stringshare*>;
}
}
}

View File

@ -0,0 +1,356 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <fnmatch.h>
#ifdef HAVE_EVIL
# include <Evil.h>
#endif
#include <Eina.h>
#include <Efl.h>
#include "Ecore.h"
#include "ecore_private.h"
typedef struct _Efl_Uri_Manager_Data Efl_Uri_Manager_Data;
typedef struct _Efl_Uri_Fetcher_Tuple Efl_Uri_Fetcher_Tuple;
typedef struct _Efl_Uri_Fetcher_Promise Efl_Uri_Fetcher_Promise;
typedef struct _Efl_Uri_Mapper_Promise Efl_Uri_Mapper_Promise;
struct _Efl_Uri_Manager_Data
{
Eina_Hash *mappers;
Eina_List *fetchers;
Efl_Uri_Mapper *def;
};
struct _Efl_Uri_Fetcher_Tuple
{
Efl_Uri_Fetcher *manager;
const char regexp[1];
};
struct _Efl_Uri_Fetcher_Promise
{
Eina_Promise_Owner *promise;
Efl_Loop *loop;
Efl_Uri_Manager *o;
Efl_Uri_Manager_Data *pd;
Eina_Promise *progress;
unsigned int count;
char *current;
};
struct _Efl_Uri_Mapper_Promise
{
Eina_Promise_Owner *promise;
Efl_Uri_Manager *o;
Efl_Uri_Manager_Data *pd;
Eina_Promise *request;
};
static Eina_Error EFL_URI_MANAGER_INFINITE_LOOP = -1;
static void _efl_uri_idle_run(void *data, const Eo_Event *ev);
static void _efl_uri_main_loop_del(void *data, const Eo_Event *ev);
static void
_efl_uri_fetcher_promise_clean(Efl_Uri_Fetcher_Promise *p)
{
eo_event_callback_del(p->loop, EFL_LOOP_EVENT_IDLE, _efl_uri_idle_run, p);
eo_event_callback_del(p->loop, EO_EVENT_DEL, _efl_uri_main_loop_del, p);
free(p->current);
free(p);
}
static void
_efl_uri_main_loop_del(void *data, const Eo_Event *ev EINA_UNUSED)
{
Efl_Uri_Fetcher_Promise *p = data;
eina_promise_owner_error_set(p->promise, EINA_ERROR_PROMISE_CANCEL);
_efl_uri_fetcher_promise_clean(p);
}
static void
_fetcher_done(void *data, void *value)
{
Efl_Uri_Fetcher_Promise *p = data;
char *s = value;
free(p->current);
p->current = s;
// Start processing the fetchers again
eo_event_callback_add(p->loop, EFL_LOOP_EVENT_IDLE, _efl_uri_idle_run, p);
}
static void
_fetcher_error(void *data, Eina_Error error)
{
Efl_Uri_Fetcher_Promise *p = data;
eina_promise_owner_error_set(p->promise, error);
_efl_uri_fetcher_promise_clean(p);
}
static void
_efl_uri_idle_run(void *data, const Eo_Event *ev EINA_UNUSED)
{
Efl_Uri_Fetcher_Promise *p = data;
Efl_Uri_Fetcher_Tuple *tuple;
Eina_List *l;
p->count++;
if (p->count > eina_list_count(p->pd->fetchers))
{
eina_promise_owner_error_set(p->promise, EFL_URI_MANAGER_INFINITE_LOOP);
_efl_uri_fetcher_promise_clean(p);
return ;
}
/* Walking the list and running fnmatch shouldn't take us
that long. If it does, we might just do that in batch and
slice the list in chunk. */
EINA_LIST_FOREACH(p->pd->fetchers, l, tuple)
if (!fnmatch(tuple->regexp, p->current, 0))
{
p->progress = efl_uri_fetcher_fetch(tuple->manager, p->current);
eo_event_callback_del(p->loop, EFL_LOOP_EVENT_IDLE, _efl_uri_idle_run, p);
eina_promise_then(p->progress, &_fetcher_done, &_fetcher_error, p);
return ;
}
// No more match, we are done !
eina_promise_owner_value_set(p->promise, eina_stringshare_add(p->current), (void*)eina_stringshare_del);
_efl_uri_fetcher_promise_clean(p);
return ;
}
static void
_fetch_cancel(void *data, Eina_Promise_Owner *promise)
{
eina_promise_owner_error_set(promise, EINA_ERROR_PROMISE_CANCEL);
_efl_uri_fetcher_promise_clean(data);
}
static Eina_Promise *
_efl_uri_manager_fetch(Eo *obj, Efl_Uri_Manager_Data *pd, const char *file)
{
Efl_Uri_Fetcher_Promise *p;
p = calloc (1, sizeof (Efl_Uri_Fetcher_Promise));
if (!p) return NULL;
p->promise = eina_promise_add();
if (!p->promise) goto on_error;
eina_promise_owner_default_cancel_cb_add(p->promise, &_fetch_cancel, p, NULL);
p->loop = eo_provider_find(obj, EFL_LOOP_CLASS);
eo_event_callback_add(p->loop, EFL_LOOP_EVENT_IDLE, _efl_uri_idle_run, p);
eo_event_callback_add(p->loop, EO_EVENT_DEL, _efl_uri_main_loop_del, p);
p->current = strdup(file);
p->o = obj;
p->pd = pd;
return eina_promise_owner_promise_get(p->promise);
on_error:
free(p);
return NULL;
}
static void
_efl_uri_mapper_promise_clean(Efl_Uri_Mapper_Promise *p)
{
free(p);
}
static void
_request_error(void *data, Eina_Error error)
{
Efl_Uri_Mapper_Promise *p = data;
eina_promise_owner_error_set(p->promise, error);
_efl_uri_mapper_promise_clean(p);
}
static void
_mapper_then(void *data, void *value)
{
Efl_Uri_Mapper_Promise *p = data;
eina_promise_owner_value_set(p->promise, eina_file_dup(value), (void*)eina_file_close);
_efl_uri_mapper_promise_clean(p);
}
static void
_mmap_cancel(void* data, Eina_Promise_Owner* promise EINA_UNUSED)
{
Efl_Uri_Mapper_Promise *p = data;
eina_promise_cancel(p->request);
}
static void
_fetch_then(void *data, void *value)
{
Efl_Uri_Mapper_Promise *p = data;
const Eina_Stringshare *file = value;
Efl_Uri_Mapper *mapper;
char *search;
search = strstr(file, "://");
if (!search)
{
mapper = p->pd->def;
}
else
{
char *prefix = alloca(search - file + 1);
if (!prefix) goto on_error;
strncpy(prefix, file, search - file);
mapper = eina_hash_find(p->pd->mappers, prefix);
mapper = mapper ? mapper : p->pd->def;
}
p->request = efl_uri_mapper_fetch(mapper, file);
eina_promise_then(p->request, &_mapper_then, &_request_error, p);
return ;
on_error:
eina_promise_owner_error_set(p->promise, EINA_ERROR_OUT_OF_MEMORY);
_efl_uri_mapper_promise_clean(p);
}
static Eina_Promise *
_efl_uri_manager_mmap(Eo *obj, Efl_Uri_Manager_Data *pd, const char *file)
{
Efl_Uri_Mapper_Promise *p;
p = calloc(1, sizeof (Efl_Uri_Mapper_Promise));
if (!p) return NULL;
p->promise = eina_promise_add();
if (!p->promise) goto on_error;
eina_promise_owner_default_cancel_cb_add(p->promise, &_mmap_cancel, p, NULL);
p->o = obj;
p->pd = pd;
p->request = efl_uri_manager_fetch(obj, file);
eina_promise_then(p->request, &_fetch_then, &_request_error, p);
return eina_promise_owner_promise_get(p->promise);
on_error:
free(p);
return NULL;
}
static Eina_Bool
_efl_uri_manager_register_fetcher(Eo *obj EINA_UNUSED, Efl_Uri_Manager_Data *pd, const char *regexp, const Efl_Uri_Fetcher *manager)
{
Efl_Uri_Fetcher_Tuple *tuple;
unsigned int length;
if (!regexp) return EINA_FALSE;
length = strlen(regexp);
tuple = calloc(1, sizeof (Efl_Uri_Fetcher_Tuple) + length);
if (!tuple) return EINA_FALSE;
tuple->manager = eo_ref(manager);
strcpy((char*) tuple->regexp, regexp);
pd->fetchers = eina_list_append(pd->fetchers, tuple);
return EINA_TRUE;
}
static Eina_Bool
_efl_uri_manager_register_mapper(Eo *obj EINA_UNUSED, Efl_Uri_Manager_Data *pd, const char *prefix, const Efl_Uri_Mapper *manager)
{
if (eina_hash_find(pd->mappers, prefix))
return EINA_FALSE;
return eina_hash_add(pd->mappers, prefix, eo_ref(manager));
}
static Eina_Bool
_efl_uri_manager_unregister_fetcher(Eo *obj EINA_UNUSED, Efl_Uri_Manager_Data *pd, const char *regexp, const Efl_Uri_Fetcher *manager)
{
Efl_Uri_Fetcher_Tuple *tuple;
Eina_List *l;
if (!regexp) return EINA_FALSE;
EINA_LIST_FOREACH(pd->fetchers, l, tuple)
if (tuple->manager == manager && !strcmp(tuple->regexp, regexp))
{
pd->fetchers = eina_list_remove_list(pd->fetchers, l);
eo_unref(tuple->manager);
free(tuple);
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_efl_uri_manager_unregister_mapper(Eo *obj EINA_UNUSED, Efl_Uri_Manager_Data *pd, const char *prefix, const Efl_Uri_Mapper *manager)
{
return eina_hash_del(pd->mappers, prefix, manager);
}
static Eo_Base *
_efl_uri_manager_eo_base_constructor(Eo *obj, Efl_Uri_Manager_Data *pd)
{
eo_constructor(eo_super(obj, EFL_URI_MANAGER_CLASS));
pd->mappers = eina_hash_string_small_new((Eina_Free_Cb) eo_unref);
if (EFL_URI_MANAGER_INFINITE_LOOP == -1)
EFL_URI_MANAGER_INFINITE_LOOP = eina_error_msg_static_register("Infinite loop during name fetch in Efl.Uri.Manager.");
return obj;
}
static void
_efl_uri_manager_eo_base_destructor(Eo *obj EINA_UNUSED, Efl_Uri_Manager_Data *pd)
{
eo_destructor(eo_super(obj, EFL_URI_MANAGER_CLASS));
eina_hash_free(pd->mappers);
eo_wref_del(pd->def, &pd->def);
}
EAPI void
efl_uri_manager_default_set(Efl_Uri_Manager *obj, Efl_Uri_Mapper *def)
{
Efl_Uri_Manager_Data *pd;
pd = obj ? eo_data_scope_get(obj, EFL_URI_MANAGER_CLASS) : NULL;
if (!pd) return ;
eo_wref_add(def, &pd->def);
}
#include "efl_uri_manager.eo.c"
#include "efl_uri_mapper.eo.c"
#include "efl_uri_fetcher.eo.c"

View File

@ -0,0 +1,68 @@
import eina_types;
class Efl.Uri.Manager (Efl.Loop_User)
{
[[The Efl Uri manager
Efl URI manager give you an easy way to request the opening of a file
providing expansion of local FreeDesktop name (and more) along with
remote file access if your system provide them. Of course everything
being done asynchronously.]]
methods {
fetch {
[[Request the resolution of all possible needed expansion for a
specific file path.]]
params {
@in file: const(char)*; [[The file path to expand.]]
}
return: promise<Eina.Stringshare*>; [[A promise to return the expanded file path in the future.]]
}
mmap {
[[Request the resolution of all possible expansion and provide the
file. This may include doing network operation.]]
params {
@in file: const(char)*; [[The file to get.]]
}
return: promise<Eina.File*>; [[A promise to return the content of the file path in the future.]]
}
register_fetcher {
[[Register an URI fetcher that will be run when a specific regexp has been found to match
its expansion capability.]]
params {
@in regexp: const(char)* @nonull; [[The regexp to match against]]
@in manager: const(Efl.Uri.Fetcher); [[The fetcher manager to ask for this expansion.]]
}
return: bool; [[Will return true uppon success.]]
}
unregister_fetcher {
[[Register an URI fetcher that will be run when a specific regexp has been found to match
its expansion capability.]]
params {
@in regexp: const(char)* @nonull; [[The regexp to match against]]
@in manager: const(Efl.Uri.Fetcher); [[The fetcher manager to ask for this expansion.]]
}
return: bool; [[Will return true uppon success.]]
}
register_mapper {
[[Register an URI mapper that will be run for a specific kind of URI schema.]]
params {
@in prefix: const(char)*; [[The URI schema to identify the capability provided.]]
@in manager: const(Efl.Uri.Mapper); [[The URI mapper to match the above schema.]]
}
return: bool; [[Will return true uppon success.]]
}
unregister_mapper {
[[Register an URI mapper that will be run for a specific kind of URI schema.]]
params {
@in prefix: const(char)*; [[The URI schema to identify the capability provided.]]
@in manager: const(Efl.Uri.Mapper); [[The URI mapper to match the above schema.]]
}
return: bool; [[Will return true uppon success.]]
}
}
implements {
Eo.Base.constructor;
Eo.Base.destructor;
}
}

View File

@ -0,0 +1,13 @@
import eina_types;
interface Efl.Uri.Mapper
{
methods {
fetch {
params {
@in file: const(stringshare);
}
return: promise<Eina.File*>;
}
}
}

View File

@ -0,0 +1,43 @@
/* EIO - EFL data type library
* Copyright (C) 2010 Enlightenment Developers:
* Cedric Bail <cedric.bail@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#include "eio_private.h"
#include "efl_uri_mapper_file.eo.h"
typedef struct _Efl_Uri_Mapper_File_Data Efl_Uri_Mapper_File_Data;
struct _Efl_Uri_Mapper_File_Data
{
};
static Eina_Promise *
_efl_uri_mapper_file_efl_uri_mapper_fetch(Eo *obj, Efl_Uri_Mapper_File_Data *pd EINA_UNUSED, const Eina_Stringshare *file)
{
Efl_Io_Manager *iom;
unsigned int offset = 0;
iom = eo_provider_find(obj, EFL_IO_MANAGER_CLASS);
if (!iom) return NULL;
if (!strncmp("file://", file, 7))
offset += 7;
return efl_io_manager_file_open(iom, file + offset, EINA_FALSE);
}
#include "efl_uri_mapper_file.eo.c"

View File

@ -0,0 +1,6 @@
class Efl.Uri.Mapper.File (Eo.Base, Efl.Uri.Mapper)
{
implements {
Efl.Uri.Mapper.fetch;
}
}

View File

@ -57,6 +57,10 @@ static Eina_Lock memory_pool_mutex;
static Eina_Condition memory_pool_cond;
static Eina_Bool memory_pool_suspended = 1;
static Efl_Io_Manager *io_manager = NULL;
static Efl_Uri_Mapper *file_mapper = NULL;
// Internal API from ecore to only be used here
EAPI void efl_uri_manager_default_set(Efl_Uri_Manager *obj, Efl_Uri_Mapper *def);
static void *
_eio_pool_malloc(Eio_Alloc_Pool *pool)
@ -274,6 +278,8 @@ eio_file_unregister(Eio_File *common)
EAPI int
eio_init(void)
{
Efl_Uri_Manager *uri_manager;
if (++_eio_init_count != 1)
return _eio_init_count;
@ -321,6 +327,12 @@ eio_init(void)
io_manager = eo_add(EFL_IO_MANAGER_CLASS, ecore_main_loop_get());
efl_loop_register(ecore_main_loop_get(), EFL_IO_MANAGER_CLASS, io_manager);
// Add default URI mapper for file (serving also "file://").
file_mapper = eo_add(EFL_URI_MAPPER_FILE_CLASS, io_manager);
uri_manager = eo_provider_find(ecore_main_loop_get(), EFL_URI_MANAGER_CLASS);
efl_uri_manager_register_mapper(uri_manager, "file", file_mapper);
efl_uri_manager_default_set(uri_manager, file_mapper);
eina_log_timing(_eio_log_dom_global,
EINA_LOG_STATE_STOP,
EINA_LOG_STATE_INIT);
@ -357,6 +369,11 @@ eio_shutdown(void)
EINA_LOG_STATE_START,
EINA_LOG_STATE_SHUTDOWN);
// Right now URI manager does hold a reference on the file_mapper
// We need to unregister it to be able to properly delete it.
efl_uri_manager_unregister_mapper(eo_provider_find(ecore_main_loop_get(), EFL_URI_MANAGER_CLASS),
"file", file_mapper);
eo_del(file_mapper);
eo_del(io_manager);
io_manager = NULL;

View File

@ -55,6 +55,8 @@
#include "Eio.h"
#include "efl_uri_mapper_file.eo.h"
#ifdef _WIN32
typedef struct __stat64 _eio_stat_t;
#define _eio_stat(p, b) _stat64(p, b)