aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2019-01-29 15:46:05 +0100
committerDaniel Kolesa <d.kolesa@samsung.com>2019-02-28 00:52:14 +0100
commita9360222b053f38c8fd0f2ee21fc2f3ea94430d7 (patch)
treeb41d6444a59455449c59e29ae3bc994ccf816576
parenttests: add test for elm_layout_text_set (diff)
downloadefl-a9360222b053f38c8fd0f2ee21fc2f3ea94430d7.tar.gz
eolian: add support for inlist structs
This adds support for inlist structs, a special type of struct that can only be used with inlists. This differs from regular structs in a couple ways: 1) They are stored separately. Just like structs, enums, aliases have their own storage, so do inlist structs. 2) They can't be @extern, nor they can be opaque. 3) They are their own type of typedecl. 4) When they contain only one field, this field must be a value type always, cannot be a pointer. Like regular structs, they can have arbitrary fields, and they can have a pre-set free function via @free(). In C, the inlist structs will be generated exactly like ordinary ones, except they will have EINA_INLIST before the first field. Other binding generators can deal with them as they wish, for example to provide high level interfaces to them. This does not yet do the plumbing necessary to hook these into the type system, nor it adds generator support. @feature
-rw-r--r--src/lib/eolian/Eolian.h62
-rw-r--r--src/lib/eolian/database_check.c1
-rw-r--r--src/lib/eolian/database_type.c20
-rw-r--r--src/lib/eolian/database_type_api.c4
-rw-r--r--src/lib/eolian/database_validate.c23
-rw-r--r--src/lib/eolian/eo_parser.c20
-rw-r--r--src/lib/eolian/eolian_database.c36
-rw-r--r--src/lib/eolian/eolian_database.h4
8 files changed, 155 insertions, 15 deletions
diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h
index a61f1086b9..321a1ff5af 100644
--- a/src/lib/eolian/Eolian.h
+++ b/src/lib/eolian/Eolian.h
@@ -264,7 +264,8 @@ typedef enum
EOLIAN_TYPEDECL_STRUCT_OPAQUE,
EOLIAN_TYPEDECL_ENUM,
EOLIAN_TYPEDECL_ALIAS,
- EOLIAN_TYPEDECL_FUNCTION_POINTER
+ EOLIAN_TYPEDECL_FUNCTION_POINTER,
+ EOLIAN_TYPEDECL_STRUCT_INLIST
} Eolian_Typedecl_Type;
typedef enum
@@ -1051,6 +1052,16 @@ EAPI const Eolian_Typedecl *eolian_unit_struct_by_name_get(const Eolian_Unit *un
EAPI const Eolian_Typedecl *eolian_unit_enum_by_name_get(const Eolian_Unit *unit, const char *name);
/*
+ * @brief Get an inlist struct declaration within a unit by name.
+ *
+ * @param[in] unit The unit.
+ * @param[in] name The name of the alias.
+ *
+ * @ingroup Eolian
+ */
+EAPI const Eolian_Typedecl *eolian_unit_inlist_struct_by_name_get(const Eolian_Unit *unit, const char *name);
+
+/*
* @brief Get an iterator to all aliases in the Eolian database.
*
* @param[in] unit The unit.
@@ -1084,6 +1095,17 @@ EAPI Eina_Iterator *eolian_unit_structs_get(const Eolian_Unit *unit);
EAPI Eina_Iterator *eolian_unit_enums_get(const Eolian_Unit *unit);
/*
+ * @brief Get an iterator to all inlist structs in the Eolian database.
+ *
+ * @param[in] unit The unit.
+ *
+ * Thanks to internal caching, this is an O(1) operation.
+ *
+ * @ingroup Eolian
+ */
+EAPI Eina_Iterator *eolian_unit_inlist_structs_get(const Eolian_Unit *unit);
+
+/*
* @brief A helper function to get an object in a state by name.
*
* @see eolian_unit_object_by_name_get
@@ -1276,6 +1298,19 @@ eolian_state_enum_by_name_get(const Eolian_State *state, const char *name)
}
/*
+ * @brief A helper function to get an inlist struct in a state by name.
+ *
+ * @see eolian_unit_inlist_struct_by_name_get
+ *
+ * @ingroup Eolian
+ */
+static inline const Eolian_Typedecl *
+eolian_state_inlist_struct_by_name_get(const Eolian_State *state, const char *name)
+{
+ return eolian_unit_inlist_struct_by_name_get(EOLIAN_UNIT(state), name);
+}
+
+/*
* @brief Get an iterator to all aliases contained in a file.
*
* @param[in] state The state.
@@ -1312,6 +1347,18 @@ EAPI Eina_Iterator *eolian_state_structs_by_file_get(const Eolian_State *state,
EAPI Eina_Iterator *eolian_state_enums_by_file_get(const Eolian_State *state, const char *file_name);
/*
+ * @brief Get an iterator to all inlist structs contained in a file.
+ *
+ * @param[in] state The state.
+ * @param[in] file_name The file name.
+ *
+ * Thanks to internal caching, this is an O(1) operation.
+ *
+ * @ingroup Eolian
+ */
+EAPI Eina_Iterator *eolian_state_inlist_structs_by_file_get(const Eolian_State *state, const char *file_name);
+
+/*
* @brief A helper function to get all aliases in a state.
*
* @see eolian_unit_aliases_get
@@ -1351,6 +1398,19 @@ eolian_state_enums_get(const Eolian_State *state)
}
/*
+ * @brief A helper function to get all inlist structs in a state.
+ *
+ * @see eolian_unit_inlist_structs_get
+ *
+ * @ingroup Eolian
+ */
+static inline Eina_Iterator *
+eolian_state_inlist_structs_get(const Eolian_State *state)
+{
+ return eolian_unit_inlist_structs_get(EOLIAN_UNIT(state));
+}
+
+/*
* @brief A helper function to get the full name of a class.
*
* @see eolian_object_name_get
diff --git a/src/lib/eolian/database_check.c b/src/lib/eolian/database_check.c
index 61afa6e281..cc5a697d31 100644
--- a/src/lib/eolian/database_check.c
+++ b/src/lib/eolian/database_check.c
@@ -172,6 +172,7 @@ _check_typedecl(const Eolian_Typedecl *tp, Eina_Hash *depset, Eina_Hash *chash)
switch (tp->type)
{
case EOLIAN_TYPEDECL_STRUCT:
+ case EOLIAN_TYPEDECL_STRUCT_INLIST:
_check_type(((const Eolian_Struct_Type_Field *)data)->type,
depset, chash);
break;
diff --git a/src/lib/eolian/database_type.c b/src/lib/eolian/database_type.c
index 31517d6487..d629a44395 100644
--- a/src/lib/eolian/database_type.c
+++ b/src/lib/eolian/database_type.c
@@ -43,11 +43,20 @@ database_type_add(Eolian_Unit *unit, Eolian_Typedecl *tp)
}
void
-database_struct_add(Eolian_Unit *unit, Eolian_Typedecl *tp)
+database_struct_add(Eolian_Unit *unit, Eolian_Typedecl *tp, Eina_Bool is_inlist)
{
- EOLIAN_OBJECT_ADD(unit, tp->base.name, tp, structs);
- eina_hash_set(unit->state->staging.structs_f, tp->base.file, eina_list_append
- ((Eina_List*)eina_hash_find(unit->state->staging.structs_f, tp->base.file), tp));
+ if (is_inlist)
+ {
+ EOLIAN_OBJECT_ADD(unit, tp->base.name, tp, inlists);
+ }
+ else
+ {
+ EOLIAN_OBJECT_ADD(unit, tp->base.name, tp, structs);
+ }
+ Eina_Hash *sh = is_inlist ? unit->state->staging.structs_f
+ : unit->state->staging.inlists_f;
+ eina_hash_set(sh, tp->base.file, eina_list_append
+ ((Eina_List*)eina_hash_find(sh, tp->base.file), tp));
database_object_add(unit, &tp->base);
}
@@ -160,6 +169,8 @@ _stype_to_str(const Eolian_Typedecl *tp, Eina_Strbuf *buf)
if (tp->type == EOLIAN_TYPEDECL_STRUCT_OPAQUE)
return;
eina_strbuf_append(buf, " { ");
+ if (tp->type == EOLIAN_TYPEDECL_STRUCT_INLIST)
+ eina_strbuf_append(buf, "EINA_INLIST; ");
Eina_List *l;
Eolian_Struct_Type_Field *sf;
EINA_LIST_FOREACH(tp->field_list, l, sf)
@@ -234,6 +245,7 @@ database_typedecl_to_str(const Eolian_Typedecl *tp, Eina_Strbuf *buf)
break;
case EOLIAN_TYPEDECL_STRUCT:
case EOLIAN_TYPEDECL_STRUCT_OPAQUE:
+ case EOLIAN_TYPEDECL_STRUCT_INLIST:
_stype_to_str(tp, buf);
break;
default:
diff --git a/src/lib/eolian/database_type_api.c b/src/lib/eolian/database_type_api.c
index 7d471c7ee4..a0887943f1 100644
--- a/src/lib/eolian/database_type_api.c
+++ b/src/lib/eolian/database_type_api.c
@@ -31,7 +31,7 @@ EAPI Eina_Iterator *
eolian_typedecl_struct_fields_get(const Eolian_Typedecl *tp)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL);
- if (tp->type != EOLIAN_TYPEDECL_STRUCT)
+ if (tp->type != EOLIAN_TYPEDECL_STRUCT && tp->type != EOLIAN_TYPEDECL_STRUCT_INLIST)
return NULL;
return eina_list_iterator_new(tp->field_list);
}
@@ -42,7 +42,7 @@ eolian_typedecl_struct_field_get(const Eolian_Typedecl *tp, const char *field)
Eolian_Struct_Type_Field *sf = NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(field, NULL);
- if (tp->type != EOLIAN_TYPEDECL_STRUCT)
+ if (tp->type != EOLIAN_TYPEDECL_STRUCT && tp->type != EOLIAN_TYPEDECL_STRUCT_INLIST)
return NULL;
sf = eina_hash_find(tp->fields, field);
if (!sf) return NULL;
diff --git a/src/lib/eolian/database_validate.c b/src/lib/eolian/database_validate.c
index 319b45a802..09ca6e5de3 100644
--- a/src/lib/eolian/database_validate.c
+++ b/src/lib/eolian/database_validate.c
@@ -171,6 +171,25 @@ _validate_typedecl(Validate_State *vals, Eolian_Typedecl *tp)
if (!tp->freefunc && tp->base_type->freefunc)
tp->freefunc = eina_stringshare_ref(tp->base_type->freefunc);
return _validate(&tp->base);
+ case EOLIAN_TYPEDECL_STRUCT_INLIST:
+ if (eina_hash_population(tp->fields) == 1)
+ {
+ Eina_Iterator *itr = eina_hash_iterator_data_new(tp->fields);
+ const Eolian_Struct_Type_Field *sf;
+ if (!eina_iterator_next(itr, (void **)&sf))
+ {
+ _eo_parser_log(&tp->base, "internal error: failed fetching field");
+ eina_iterator_free(itr);
+ return EINA_FALSE;
+ }
+ eina_iterator_free(itr);
+ if (database_type_is_ownable(tp->base.unit, sf->type, EINA_FALSE))
+ {
+ _eo_parser_log(&sf->base, "single-field inlist struct must contain a value type");
+ return EINA_FALSE;
+ }
+ }
+ /* fallthrough */
case EOLIAN_TYPEDECL_STRUCT:
{
Cb_Ret rt = { vals, EINA_TRUE };
@@ -1388,6 +1407,10 @@ database_validate(const Eolian_Unit *src)
if (!rt.succ)
return EINA_FALSE;
+ eina_hash_foreach(src->inlists, (Eina_Hash_Foreach)_typedecl_map_cb, &rt);
+ if (!rt.succ)
+ return EINA_FALSE;
+
eina_hash_foreach(src->globals, (Eina_Hash_Foreach)_var_map_cb, &rt);
if (!rt.succ)
return EINA_FALSE;
diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c
index cc3ea7aabb..57b5e117c0 100644
--- a/src/lib/eolian/eo_parser.c
+++ b/src/lib/eolian/eo_parser.c
@@ -133,6 +133,7 @@ _eolian_decl_name_get(Eolian_Object *obj)
return "type alias";
case EOLIAN_TYPEDECL_STRUCT:
case EOLIAN_TYPEDECL_STRUCT_OPAQUE:
+ case EOLIAN_TYPEDECL_STRUCT_INLIST:
return "struct";
case EOLIAN_TYPEDECL_ENUM:
return "enum";
@@ -433,13 +434,13 @@ _struct_field_free(Eolian_Struct_Type_Field *def)
static Eolian_Typedecl *
parse_struct(Eo_Lexer *ls, const char *name, Eina_Bool is_extern,
- int line, int column, const char *freefunc)
+ int line, int column, const char *freefunc, Eina_Bool is_inlist)
{
int bline = ls->line_number, bcolumn = ls->column;
Eolian_Typedecl *def = eo_lexer_typedecl_new(ls);
def->is_extern = is_extern;
def->base.name = name;
- def->type = EOLIAN_TYPEDECL_STRUCT;
+ def->type = is_inlist ? EOLIAN_TYPEDECL_STRUCT_INLIST : EOLIAN_TYPEDECL_STRUCT;
def->fields = eina_hash_string_small_new(EINA_FREE_CB(_struct_field_free));
if (freefunc)
{
@@ -475,7 +476,7 @@ parse_struct(Eo_Lexer *ls, const char *name, Eina_Bool is_extern,
}
check_match(ls, '}', '{', bline, bcolumn);
FILL_BASE(def->base, ls, line, column, TYPEDECL);
- database_struct_add(ls->unit, eo_lexer_typedecl_release(ls, def));
+ database_struct_add(ls->unit, eo_lexer_typedecl_release(ls, def), is_inlist);
return def;
}
@@ -2205,8 +2206,10 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
}
case KW_struct:
case KW_enum:
+ case KW_inlist:
{
Eina_Bool is_enum = (ls->t.kw == KW_enum);
+ Eina_Bool is_inlist = (ls->t.kw == KW_inlist);
const char *name;
int line, col;
const char *freefunc = NULL;
@@ -2217,6 +2220,8 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
{
case KW_at_extern:
CASE_LOCK(ls, extern, "@extern qualifier")
+ if (is_inlist)
+ eo_lexer_syntax_error(ls, "inlist structs cannot be @extern");
eo_lexer_get(ls);
break;
case KW_at_free:
@@ -2254,12 +2259,13 @@ postparams:
eo_lexer_context_restore(ls);
Eolian_Typedecl tdecl;
tdecl.base.type = EOLIAN_OBJECT_TYPEDECL;
- tdecl.type = is_enum ? EOLIAN_TYPEDECL_ENUM : EOLIAN_TYPEDECL_STRUCT;
+ tdecl.type = is_inlist ? EOLIAN_TYPEDECL_STRUCT_INLIST :
+ (is_enum ? EOLIAN_TYPEDECL_ENUM : EOLIAN_TYPEDECL_STRUCT);
redef_error(ls, decl, &tdecl.base);
}
eo_lexer_context_pop(ls);
eo_lexer_dtor_pop(ls);
- if (!is_enum && ls->t.token == ';')
+ if (!is_enum && !is_inlist && ls->t.token == ';')
{
Eolian_Typedecl *def = eo_lexer_typedecl_new(ls);
def->is_extern = has_extern;
@@ -2273,13 +2279,13 @@ postparams:
eo_lexer_get(ls);
FILL_DOC(ls, def, doc);
FILL_BASE(def->base, ls, line, col, TYPEDECL);
- database_struct_add(ls->unit, eo_lexer_typedecl_release(ls, def));
+ database_struct_add(ls->unit, eo_lexer_typedecl_release(ls, def), EINA_FALSE);
break;
}
if (is_enum)
parse_enum(ls, name, has_extern, line, col);
else
- parse_struct(ls, name, has_extern, line, col, freefunc);
+ parse_struct(ls, name, has_extern, line, col, freefunc, is_inlist);
break;
}
def:
diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c
index eb6e896bab..a97c53f526 100644
--- a/src/lib/eolian/eolian_database.c
+++ b/src/lib/eolian/eolian_database.c
@@ -557,6 +557,7 @@ database_unit_init(Eolian_State *state, Eolian_Unit *unit, const char *file)
unit->aliases = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del));
unit->structs = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del));
unit->enums = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del));
+ unit->inlists = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del));
unit->objects = eina_hash_stringshared_new(NULL);
}
@@ -571,6 +572,7 @@ _unit_contents_del(Eolian_Unit *unit)
eina_hash_free(unit->aliases);
eina_hash_free(unit->structs);
eina_hash_free(unit->enums);
+ eina_hash_free(unit->inlists);
eina_hash_free(unit->objects);
}
@@ -618,6 +620,7 @@ _state_area_init(Eolian_State *state, Eolian_State_Area *a)
a->aliases_f = eina_hash_stringshared_new(NULL);
a->structs_f = eina_hash_stringshared_new(NULL);
a->enums_f = eina_hash_stringshared_new(NULL);
+ a->inlists_f = eina_hash_stringshared_new(NULL);
a->globals_f = eina_hash_stringshared_new(NULL);
a->constants_f = eina_hash_stringshared_new(NULL);
a->objects_f = eina_hash_stringshared_new(NULL);
@@ -644,6 +647,7 @@ _state_area_contents_del(Eolian_State_Area *a)
_hashlist_free(a->aliases_f);
_hashlist_free(a->structs_f);
_hashlist_free(a->enums_f);
+ _hashlist_free(a->inlists_f);
_hashlist_free(a->globals_f);
_hashlist_free(a->constants_f);
_hashlist_free(a->objects_f);
@@ -848,6 +852,7 @@ _state_clean(Eolian_State *state)
eina_hash_free_buckets(stu->aliases);
eina_hash_free_buckets(stu->structs);
eina_hash_free_buckets(stu->enums);
+ eina_hash_free_buckets(stu->inlists);
eina_hash_free_buckets(stu->objects);
eina_hash_foreach(st->units, _ulist_free_cb, NULL);
@@ -858,6 +863,7 @@ _state_clean(Eolian_State *state)
_hashlist_free_buckets(st->aliases_f);
_hashlist_free_buckets(st->structs_f);
_hashlist_free_buckets(st->enums_f);
+ _hashlist_free_buckets(st->inlists_f);
_hashlist_free_buckets(st->globals_f);
_hashlist_free_buckets(st->constants_f);
_hashlist_free_buckets(st->objects_f);
@@ -952,6 +958,7 @@ _merge_unit(Eolian_Unit *dest, Eolian_Unit *src)
eina_hash_foreach(src->aliases, _merge_unit_cb, dest->aliases);
eina_hash_foreach(src->structs, _merge_unit_cb, dest->structs);
eina_hash_foreach(src->enums, _merge_unit_cb, dest->enums);
+ eina_hash_foreach(src->inlists, _merge_unit_cb, dest->inlists);
eina_hash_foreach(src->objects, _merge_unit_cb_noref, dest->objects);
}
@@ -1010,6 +1017,7 @@ _merge_staging(Eolian_State *state)
EOLIAN_STAGING_MERGE_LIST(aliases);
EOLIAN_STAGING_MERGE_LIST(structs);
EOLIAN_STAGING_MERGE_LIST(enums);
+ EOLIAN_STAGING_MERGE_LIST(inlists);
EOLIAN_STAGING_MERGE_LIST(globals);
EOLIAN_STAGING_MERGE_LIST(constants);
EOLIAN_STAGING_MERGE_LIST(objects);
@@ -1205,6 +1213,17 @@ eolian_state_enums_by_file_get(const Eolian_State *state, const char *file_name)
return eina_list_iterator_new(l);
}
+EAPI Eina_Iterator *
+eolian_state_inlist_structs_by_file_get(const Eolian_State *state, const char *file_name)
+{
+ if (!state) return NULL;
+ Eina_Stringshare *shr = eina_stringshare_add(file_name);
+ Eina_List *l = eina_hash_find(state->main.inlists_f, shr);
+ eina_stringshare_del(shr);
+ if (!l) return NULL;
+ return eina_list_iterator_new(l);
+}
+
EAPI const Eolian_State *
eolian_unit_state_get(const Eolian_Unit *unit)
{
@@ -1332,6 +1351,17 @@ eolian_unit_enum_by_name_get(const Eolian_Unit *unit, const char *name)
return tp;
}
+EAPI const Eolian_Typedecl *
+eolian_unit_inlist_struct_by_name_get(const Eolian_Unit *unit, const char *name)
+{
+ if (!unit) return NULL;
+ Eina_Stringshare *shr = eina_stringshare_add(name);
+ Eolian_Typedecl *tp = eina_hash_find(unit->inlists, shr);
+ eina_stringshare_del(shr);
+ if (!tp) return NULL;
+ return tp;
+}
+
EAPI Eina_Iterator *
eolian_unit_aliases_get(const Eolian_Unit *unit)
{
@@ -1350,6 +1380,12 @@ eolian_unit_enums_get(const Eolian_Unit *unit)
return (unit ? eina_hash_iterator_data_new(unit->enums) : NULL);
}
+EAPI Eina_Iterator *
+eolian_unit_inlist_structs_get(const Eolian_Unit *unit)
+{
+ return (unit ? eina_hash_iterator_data_new(unit->inlists) : NULL);
+}
+
char *
database_class_to_filename(const char *cname)
{
diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h
index b70f2b4f1e..fd15d6401a 100644
--- a/src/lib/eolian/eolian_database.h
+++ b/src/lib/eolian/eolian_database.h
@@ -44,6 +44,7 @@ struct _Eolian_Unit
Eina_Hash *aliases;
Eina_Hash *structs;
Eina_Hash *enums;
+ Eina_Hash *inlists;
Eina_Hash *objects;
};
@@ -57,6 +58,7 @@ typedef struct _Eolian_State_Area
Eina_Hash *aliases_f;
Eina_Hash *structs_f;
Eina_Hash *enums_f;
+ Eina_Hash *inlists_f;
Eina_Hash *globals_f;
Eina_Hash *constants_f;
Eina_Hash *objects_f;
@@ -407,7 +409,7 @@ Eolian_Object_Type database_doc_token_ref_resolve(const Eolian_Doc_Token *tok,
/* types */
void database_type_add(Eolian_Unit *unit, Eolian_Typedecl *tp);
-void database_struct_add(Eolian_Unit *unit, Eolian_Typedecl *tp);
+void database_struct_add(Eolian_Unit *unit, Eolian_Typedecl *tp, Eina_Bool is_inlist);
void database_enum_add(Eolian_Unit *unit, Eolian_Typedecl *tp);
void database_type_del(Eolian_Type *tp);
void database_typedecl_del(Eolian_Typedecl *tp);