summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--header_checks/meson.build3
-rw-r--r--meson.build1
-rw-r--r--src/Makefile_Ecore.am7
-rw-r--r--src/lib/ecore/Ecore_Eo.h3
-rw-r--r--src/lib/ecore/efl_core_env.c107
-rw-r--r--src/lib/ecore/efl_core_env.eo57
-rw-r--r--src/lib/ecore/efl_core_proc_env.c145
-rw-r--r--src/lib/ecore/efl_core_proc_env.eo21
-rw-r--r--src/lib/ecore/meson.build6
-rw-r--r--src/tests/ecore/efl_app_suite.c2
-rw-r--r--src/tests/ecore/efl_app_suite.h1
-rw-r--r--src/tests/ecore/efl_app_test_env.c135
-rw-r--r--src/tests/ecore/meson.build3
13 files changed, 486 insertions, 5 deletions
diff --git a/header_checks/meson.build b/header_checks/meson.build
index b23e774ec1..066d228a83 100644
--- a/header_checks/meson.build
+++ b/header_checks/meson.build
@@ -53,7 +53,8 @@ header_checks = [
'langinfo.h',
'locale.h',
'uv.h',
- 'ws2tcpip.h'
+ 'ws2tcpip.h',
+ 'crt_externs.h'
]
function_checks = [
diff --git a/meson.build b/meson.build
index 0e2a50c2c9..d6b9b6074d 100644
--- a/meson.build
+++ b/meson.build
@@ -210,6 +210,7 @@ elif sys_osx == true
sys_lib_extension = 'dylib'
sys_exe_extension = ''
sys_mod_extension = 'dylib'
+ config_h.set('environ', '(*_NSGetEnviron())')
else
error('System '+host_machine.system()+' not known')
endif
diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am
index 7bc8e43b74..5f10ea7f2e 100644
--- a/src/Makefile_Ecore.am
+++ b/src/Makefile_Ecore.am
@@ -49,7 +49,9 @@ ecore_eolian_files_public = \
lib/ecore/efl_boolean_model.eo \
lib/ecore/efl_select_model.eo \
lib/ecore/efl_composite_model.eo \
- lib/ecore/efl_view_model.eo
+ lib/ecore/efl_view_model.eo \
+ lib/ecore/efl_core_env.eo \
+ lib/ecore/efl_core_proc_env.eo \
ecore_eolian_files = \
$(ecore_eolian_files_legacy) \
@@ -98,6 +100,8 @@ lib/ecore/ecore_job.c \
lib/ecore/ecore_main.c \
lib/ecore/ecore_event_message.c \
lib/ecore/ecore_event_message_handler.c \
+lib/ecore/efl_core_env.c \
+lib/ecore/efl_core_proc_env.c \
lib/ecore/efl_app.c \
lib/ecore/efl_loop.c \
lib/ecore/efl_loop_consumer.c \
@@ -335,6 +339,7 @@ tests/ecore/efl_app_test_loop.c \
tests/ecore/efl_app_test_loop_fd.c \
tests/ecore/efl_app_test_loop_timer.c \
tests/ecore/efl_app_test_promise.c \
+tests/ecore/efl_app_test_env.c \
tests/ecore/efl_app_suite.c \
tests/ecore/efl_app_suite.h
diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h
index 6a21ff5ea7..348b0f5b6d 100644
--- a/src/lib/ecore/Ecore_Eo.h
+++ b/src/lib/ecore/Ecore_Eo.h
@@ -26,6 +26,9 @@
* @{
*/
+#include "efl_core_env.eo.h"
+#include "efl_core_proc_env.eo.h"
+
#include "efl_loop_message.eo.h"
#include "efl_loop_message_handler.eo.h"
diff --git a/src/lib/ecore/efl_core_env.c b/src/lib/ecore/efl_core_env.c
new file mode 100644
index 0000000000..38fc9ba1a9
--- /dev/null
+++ b/src/lib/ecore/efl_core_env.c
@@ -0,0 +1,107 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore.h>
+#include <ctype.h>
+
+#include "ecore_private.h"
+
+#define MY_CLASS EFL_CORE_ENV_CLASS
+
+extern char **environ;
+
+typedef struct {
+ Eina_Hash *env;
+} Efl_Core_Env_Data;
+
+static inline Eina_Bool
+str_valid(const char *var)
+{
+ return var && var[0] != '\0';
+}
+
+static inline Eina_Bool
+key_valid(const char *key)
+{
+ if (!key || key[0] == '\0') return EINA_FALSE;
+
+ if isdigit(key[0]) return EINA_FALSE;
+
+ for (int i = 0; key[i] != '\0'; ++i) {
+ if (!isalnum(key[i]) && key[i] != '_') return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+EOLIAN static void
+_efl_core_env_env_set(Eo *obj EINA_UNUSED, Efl_Core_Env_Data *pd, const char *var, const char *value)
+{
+ EINA_SAFETY_ON_FALSE_RETURN(key_valid(var));
+ if (str_valid(value))
+ {
+ Eina_Stringshare *share;
+ share = eina_hash_set(pd->env, var, eina_stringshare_add(value));
+ if (share) eina_stringshare_del(share);
+ }
+ else
+ eina_hash_del(pd->env, var, NULL);
+}
+
+EOLIAN static const char*
+_efl_core_env_env_get(const Eo *obj EINA_UNUSED, Efl_Core_Env_Data *pd, const char *var)
+{
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(key_valid(var), NULL);
+
+ return eina_hash_find(pd->env, var);
+}
+
+EOLIAN static void
+_efl_core_env_unset(Eo *obj EINA_UNUSED, Efl_Core_Env_Data *pd, const char *var)
+{
+ EINA_SAFETY_ON_FALSE_RETURN(key_valid(var));
+ eina_hash_del_by_key(pd->env, var);
+}
+
+EOLIAN static void
+_efl_core_env_clear(Eo *obj EINA_UNUSED, Efl_Core_Env_Data *pd)
+{
+ eina_hash_free_buckets(pd->env);
+}
+
+EOLIAN static Efl_Core_Env*
+_efl_core_env_efl_duplicate_duplicate(const Eo *obj EINA_UNUSED, Efl_Core_Env_Data *pd)
+{
+ Efl_Core_Env *fork = efl_add_ref(MY_CLASS, NULL);
+ Eina_Iterator *iter;
+ Eina_Hash_Tuple *tuple;
+
+ iter = eina_hash_iterator_tuple_new(pd->env);
+
+ EINA_ITERATOR_FOREACH(iter, tuple)
+ {
+ efl_core_env_set(fork, tuple->key, tuple->data);
+ }
+
+ eina_iterator_free(iter);
+ return fork;
+}
+
+EOLIAN static Efl_Object*
+_efl_core_env_efl_object_constructor(Eo *obj, Efl_Core_Env_Data *pd)
+{
+ pd->env = eina_hash_string_superfast_new((Eina_Free_Cb)eina_stringshare_del);
+
+ return efl_constructor(efl_super(obj, MY_CLASS));
+}
+
+EOLIAN static Eina_Iterator*
+_efl_core_env_content_get(const Eo *obj EINA_UNUSED, Efl_Core_Env_Data *pd)
+{
+ Eina_Iterator *iter = eina_hash_iterator_key_new(pd->env);
+ return iter;
+}
+
+
+#include "efl_core_env.eo.c"
diff --git a/src/lib/ecore/efl_core_env.eo b/src/lib/ecore/efl_core_env.eo
new file mode 100644
index 0000000000..86da8c14ff
--- /dev/null
+++ b/src/lib/ecore/efl_core_env.eo
@@ -0,0 +1,57 @@
+class Efl.Core.Env extends Efl.Object implements Efl.Duplicate {
+ [[This object can maintain a set of key value pairs
+
+ A object of this type alone does not apply the object to the system.
+ For getting the value into the system, see @Efl.Core.Proc_Env.
+
+ A object can be forked, which will only copy its values, changes to the returned object will not change the object where it is forked off.
+ ]]
+ methods {
+ @property env {
+ [[ Stored var value pairs of this object.
+
+ Var must contain only: underscores ('_'), letters ('a-z', 'A-Z'),
+ numbers ('0-9'), but the first character may not be a number.
+ ]]
+ set {
+ [[ Add a new pair to this object ]]
+ }
+ get {
+ [[ Get the value of the $var, or $null if no such $var exists in the object]]
+ }
+ keys {
+ var: string; [[ The name of the variable ]]
+ }
+ values {
+ value: string; [[ Set var to this value if not $NULL,
+ otherwise clear this env value if value
+ is $NULL or if it is an empty string ]]
+ }
+ }
+ unset {
+ [[ Remove the pair with the matching $var from this object]]
+ params {
+ var : string; [[ The name of the variable ]]
+ }
+ }
+ clear {
+ [[ Remove all pairs from this object]]
+ }
+ @property content {
+ [[ Get the content of this object.
+
+ This will return a iterator that contains all keys that are part of this object.
+ ]]
+ get {
+
+ }
+ values {
+ iter : iterator<string>;
+ }
+ }
+ }
+ implements {
+ Efl.Object.constructor;
+ Efl.Duplicate.duplicate;
+ }
+}
diff --git a/src/lib/ecore/efl_core_proc_env.c b/src/lib/ecore/efl_core_proc_env.c
new file mode 100644
index 0000000000..846b69a350
--- /dev/null
+++ b/src/lib/ecore/efl_core_proc_env.c
@@ -0,0 +1,145 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore.h>
+#ifdef HAVE_CRT_EXTERNS_H
+# include <crt_externs.h>
+#endif
+#include "ecore_private.h"
+
+#define MY_CLASS EFL_CORE_PROC_ENV_CLASS
+
+static Efl_Core_Env *env = NULL;
+
+typedef struct {
+ Eina_Bool in_sync;
+} Efl_Core_Proc_Env_Data;
+
+static void
+_sync(Efl_Core_Env *obj, Efl_Core_Proc_Env_Data *pd)
+{
+ Eina_List *existing_keys = NULL, *n;
+ Eina_Iterator *content;
+ const char *key;
+
+ pd->in_sync = EINA_TRUE;
+ content = efl_core_env_content_get(obj);
+
+ EINA_ITERATOR_FOREACH(content, key)
+ {
+ existing_keys = eina_list_append(existing_keys, key);
+ }
+
+ if (environ)
+ {
+ char **p;
+
+ for (p = environ; *p; p++)
+ {
+ char **values;
+
+ values = eina_str_split(*p, "=", 2);
+ efl_core_env_set(obj, values[0], values[1]);
+
+ EINA_LIST_FOREACH(existing_keys, n, key)
+ {
+ if (!strcmp(key, values[0]))
+ {
+ existing_keys = eina_list_remove_list(existing_keys, n);
+ break;
+ }
+ }
+ }
+ }
+ EINA_LIST_FOREACH(existing_keys, n, key)
+ {
+ efl_core_env_unset(obj, key);
+ }
+ pd->in_sync = EINA_FALSE;
+}
+
+EOLIAN static const char*
+_efl_core_proc_env_efl_core_env_env_get(const Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *var)
+{
+ if (!pd->in_sync)
+ _sync((Eo*)obj, pd);
+ return efl_core_env_get(efl_super(obj, MY_CLASS), var);
+}
+
+EOLIAN static void
+_efl_core_proc_env_efl_core_env_env_set(Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *var, const char *value)
+{
+ efl_core_env_set(efl_super(obj, MY_CLASS), var, value);
+ if (!pd->in_sync)
+ {
+ if (value)
+ setenv(var, value, 1);
+ else
+ unsetenv(var);
+ }
+}
+
+EOLIAN static void
+_efl_core_proc_env_efl_core_env_unset(Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *key)
+{
+ efl_core_env_unset(efl_super(obj, MY_CLASS), key);
+ if (!pd->in_sync)
+ {
+ unsetenv(key);
+ }
+}
+
+EOLIAN static void
+_efl_core_proc_env_efl_core_env_clear(Eo *obj, Efl_Core_Proc_Env_Data *pd)
+{
+ efl_core_env_clear(efl_super(obj, MY_CLASS));
+ if (!pd->in_sync)
+ {
+#ifdef HAVE_CLEARENV
+ clearenv();
+#else
+ environ = NULL;
+#endif
+ }
+}
+
+
+EOLIAN static Efl_Duplicate*
+_efl_core_proc_env_efl_duplicate_duplicate(const Eo *obj, Efl_Core_Proc_Env_Data *pd)
+{
+ if (!pd->in_sync)
+ _sync((Eo*) obj, pd);
+ return efl_duplicate(efl_super(obj, MY_CLASS));
+}
+
+EOLIAN static Eina_Iterator*
+_efl_core_proc_env_efl_core_env_content_get(const Eo *obj, Efl_Core_Proc_Env_Data *pd)
+{
+ if (!pd->in_sync)
+ _sync((Eo*) obj, pd);
+ return efl_core_env_content_get(efl_super(obj, MY_CLASS));
+}
+
+EOLIAN static Efl_Object*
+_efl_core_proc_env_efl_object_constructor(Eo *obj, Efl_Core_Proc_Env_Data *pd EINA_UNUSED)
+{
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(!!env, NULL);
+
+ obj = efl_constructor(efl_super(obj, MY_CLASS));
+ return obj;
+}
+
+EOLIAN static Efl_Core_Env*
+_efl_core_proc_env_self(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
+{
+ if (!env)
+ {
+ env = efl_add_ref(EFL_CORE_PROC_ENV_CLASS, NULL);
+ efl_wref_add(env, &env);
+ }
+
+ return env;
+}
+
+#include "efl_core_proc_env.eo.c"
diff --git a/src/lib/ecore/efl_core_proc_env.eo b/src/lib/ecore/efl_core_proc_env.eo
new file mode 100644
index 0000000000..23c2c67d75
--- /dev/null
+++ b/src/lib/ecore/efl_core_proc_env.eo
@@ -0,0 +1,21 @@
+class Efl.Core.Proc_Env extends Efl.Core.Env
+{
+ eo_prefix : efl_env;
+ methods {
+ self @class {
+ [[Get a instance of this object
+
+ The object will apply the environment operations onto this process.
+ ]]
+ return : Efl.Core.Env;
+ }
+ }
+ implements {
+ Efl.Core.Env.env { set; get; }
+ Efl.Core.Env.content { get; }
+ Efl.Core.Env.unset;
+ Efl.Core.Env.clear;
+ Efl.Duplicate.duplicate;
+ Efl.Object.constructor;
+ }
+}
diff --git a/src/lib/ecore/meson.build b/src/lib/ecore/meson.build
index baa5263698..98909cb618 100644
--- a/src/lib/ecore/meson.build
+++ b/src/lib/ecore/meson.build
@@ -74,7 +74,9 @@ pub_eo_files = [
'efl_boolean_model.eo',
'efl_select_model.eo',
'efl_composite_model.eo',
- 'efl_view_model.eo'
+ 'efl_view_model.eo',
+ 'efl_core_env.eo',
+ 'efl_core_proc_env.eo'
]
foreach eo_file : pub_eo_files
@@ -180,6 +182,8 @@ ecore_src = [
'efl_thread.c',
'efl_threadio.c',
'efl_appthread.c',
+ 'efl_core_env.c',
+ 'efl_core_proc_env.c',
]
if sys_windows == true
diff --git a/src/tests/ecore/efl_app_suite.c b/src/tests/ecore/efl_app_suite.c
index b3be09915a..cd26e2d95e 100644
--- a/src/tests/ecore/efl_app_suite.c
+++ b/src/tests/ecore/efl_app_suite.c
@@ -9,7 +9,6 @@
#include "efl_app_suite.h"
#include "../efl_check.h"
-
EFL_START_TEST(efl_app_test_efl_build_version)
{
const Efl_Version *ver;
@@ -53,6 +52,7 @@ static const Efl_Test_Case etc[] = {
{ "Promise", efl_app_test_promise_2 },
{ "Promise", efl_app_test_promise_3 },
{ "Promise", efl_app_test_promise_safety },
+ { "Env", efl_test_efl_env },
{ NULL, NULL }
};
diff --git a/src/tests/ecore/efl_app_suite.h b/src/tests/ecore/efl_app_suite.h
index 29ed8f031f..3a66dcdfcf 100644
--- a/src/tests/ecore/efl_app_suite.h
+++ b/src/tests/ecore/efl_app_suite.h
@@ -11,5 +11,6 @@ void efl_app_test_promise(TCase *tc);
void efl_app_test_promise_2(TCase *tc);
void efl_app_test_promise_3(TCase *tc);
void efl_app_test_promise_safety(TCase *tc);
+void efl_test_efl_env(TCase *tc);
#endif /* _EFL_APP_SUITE_H */
diff --git a/src/tests/ecore/efl_app_test_env.c b/src/tests/ecore/efl_app_test_env.c
new file mode 100644
index 0000000000..63bad166a2
--- /dev/null
+++ b/src/tests/ecore/efl_app_test_env.c
@@ -0,0 +1,135 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#define EFL_NOLEGACY_API_SUPPORT
+#include <Efl_Core.h>
+#include "efl_app_suite.h"
+#include "../efl_check.h"
+
+EFL_START_TEST(efl_core_env_test_set_get)
+{
+ Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
+
+ efl_core_env_set(env, "FOO", "bar");
+ efl_core_env_set(env, "going", "home");
+ efl_core_env_set(env, "Merry", "christmas");
+
+ ck_assert_str_eq(efl_core_env_get(env, "FOO"), "bar");
+ ck_assert_str_eq(efl_core_env_get(env, "going"), "home");
+ ck_assert_str_eq(efl_core_env_get(env, "Merry"), "christmas");
+
+ efl_core_env_unset(env, "Merry");
+
+ ck_assert_str_eq(efl_core_env_get(env, "FOO"), "bar");
+ ck_assert_str_eq(efl_core_env_get(env, "going"), "home");
+ ck_assert_ptr_eq(efl_core_env_get(env, "Merry"), NULL);
+
+ efl_unref(env);
+}
+EFL_END_TEST
+
+EFL_START_TEST(efl_core_env_test_invalid_keys)
+{
+ Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
+
+#define CHECK(val) \
+ efl_core_env_set(env, val, "TEST"); \
+ ck_assert_ptr_eq(efl_core_env_get(env, val), NULL);
+
+ CHECK("0foo");
+ CHECK("foo bar");
+ CHECK("foo!bar");
+
+#undef CHECK
+
+
+#define CHECK(val) \
+ efl_core_env_set(env, val, "TEST"); \
+ ck_assert_str_eq(efl_core_env_get(env, val), "TEST");
+
+ CHECK("foo0");
+ CHECK("foo_bar");
+
+#undef CHECK
+
+}
+EFL_END_TEST
+
+EFL_START_TEST(efl_core_env_test_clear)
+{
+ Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
+
+ efl_core_env_set(env, "FOO", "bar");
+ efl_core_env_set(env, "going", "home");
+ efl_core_env_set(env, "Merry", "christmas");
+
+ efl_core_env_clear(env);
+
+ ck_assert_ptr_eq(efl_core_env_get(env, "FOO"), NULL);
+ ck_assert_ptr_eq(efl_core_env_get(env, "going"), NULL);
+ ck_assert_ptr_eq(efl_core_env_get(env, "Merry"), NULL);
+
+ efl_unref(env);
+}
+EFL_END_TEST
+
+EFL_START_TEST(efl_core_env_test_fork)
+{
+ Efl_Core_Env *env_fork, *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
+
+ efl_core_env_set(env, "FOO", "bar");
+ efl_core_env_set(env, "going", "home");
+ efl_core_env_set(env, "Merry", "christmas");
+
+ env_fork = efl_duplicate(env);
+
+ ck_assert_str_eq(efl_core_env_get(env_fork, "FOO"), "bar");
+ ck_assert_str_eq(efl_core_env_get(env_fork, "going"), "home");
+ ck_assert_str_eq(efl_core_env_get(env_fork, "Merry"), "christmas");
+
+ efl_unref(env);
+}
+EFL_END_TEST
+
+EFL_START_TEST(efl_core_env_test_process)
+{
+ Efl_Core_Env *env_fork, *env = efl_env_self(EFL_CORE_PROC_ENV_CLASS);
+
+ ck_assert(env);
+
+ ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH"));
+ env_fork = efl_duplicate(env);
+ ck_assert_str_eq(efl_core_env_get(env_fork, "PATH"), getenv("PATH"));
+
+ efl_unref(env);
+}
+EFL_END_TEST
+
+EFL_START_TEST(efl_core_env_test_undepend_fork)
+{
+ Efl_Core_Env *env_fork, *env = efl_env_self(EFL_CORE_PROC_ENV_CLASS);
+
+ ck_assert(env);
+
+ ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH"));
+ env_fork = efl_duplicate(env);
+ efl_core_env_set(env_fork, "PATH", "abc");
+ ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH"));
+
+ efl_unref(env);
+ efl_unref(env_fork);
+}
+EFL_END_TEST
+
+void efl_test_efl_env(TCase *tc)
+{
+ tcase_add_test(tc, efl_core_env_test_set_get);
+ tcase_add_test(tc, efl_core_env_test_invalid_keys);
+ tcase_add_test(tc, efl_core_env_test_clear);
+ tcase_add_test(tc, efl_core_env_test_fork);
+ tcase_add_test(tc, efl_core_env_test_process);
+ tcase_add_test(tc, efl_core_env_test_undepend_fork);
+}
diff --git a/src/tests/ecore/meson.build b/src/tests/ecore/meson.build
index 4b46814bbe..e3b4f6c851 100644
--- a/src/tests/ecore/meson.build
+++ b/src/tests/ecore/meson.build
@@ -75,7 +75,8 @@ efl_app_suite_src = [
'efl_app_test_loop.c',
'efl_app_test_loop_fd.c',
'efl_app_test_loop_timer.c',
- 'efl_app_test_promise.c'
+ 'efl_app_test_promise.c',
+ 'efl_app_test_env.c'
]
efl_app_suite_deps = [m]