Ver Fonte

ncd: modules: value: refactor for adding new statements

ambrop7 há 14 anos atrás
pai
commit
fb34d919d9
1 ficheiros alterados com 147 adições e 72 exclusões
  1. 147 72
      ncd/modules/value.c

+ 147 - 72
ncd/modules/value.c

@@ -115,11 +115,16 @@
 
 struct value;
 
-struct instance {
-    NCDModuleInst *i;
+struct valref {
     struct value *v;
     LinkedList0Node refs_list_node;
-    int remove_on_deinit;
+};
+
+struct instance {
+    NCDModuleInst *i;
+    struct valref ref;
+    struct valref restore_ref;
+    int restore_on_deinit;
 };
 
 struct value {
@@ -154,11 +159,11 @@ static int ncdvalue_comparator (void *unused, void *vv1, void *vv2);
 static const char * get_type_str (int type);
 static void value_cleanup (struct value *v);
 static void value_delete (struct value *v);
-static void value_remove_from_parent (struct value *v);
 static struct value * value_init_string (NCDModuleInst *i, const char *str);
 static struct value * value_init_list (NCDModuleInst *i);
 static size_t value_list_len (struct value *v);
 static struct value * value_list_at (struct value *v, size_t index);
+static size_t value_list_indexof (struct value *v, struct value *ev);
 static int value_list_insert (NCDModuleInst *i, struct value *list, struct value *v, size_t index);
 static void value_list_remove (struct value *list, struct value *v);
 static struct value * value_init_map (NCDModuleInst *i);
@@ -167,12 +172,17 @@ static struct value * value_map_at (struct value *map, size_t index);
 static struct value * value_map_find (struct value *map, NCDValue *key);
 static int value_map_insert (struct value *map, struct value *v, NCDValue key, NCDModuleInst *i);
 static void value_map_remove (struct value *map, struct value *v);
+static void value_map_remove2 (struct value *map, struct value *v, NCDValue *out_key);
 static struct value * value_init_fromvalue (NCDModuleInst *i, NCDValue *value);
 static int value_to_value (NCDModuleInst *i, struct value *v, NCDValue *out_value);
 static struct value * value_get (NCDModuleInst *i, struct value *v, NCDValue *where, int no_error);
 static struct value * value_get_path (NCDModuleInst *i, struct value *v, NCDValue *path);
 static struct value * value_insert (NCDModuleInst *i, struct value *v, NCDValue *where, NCDValue *what);
 static int value_remove (NCDModuleInst *i, struct value *v, NCDValue *where);
+static void valref_init (struct valref *r, struct value *v);
+static void valref_free (struct valref *r);
+static struct value * valref_val (struct valref *r);
+static void valref_break (struct valref *r);
 
 static int ncdvalue_comparator (void *unused, void *vv1, void *vv2)
 {
@@ -242,10 +252,9 @@ static void value_delete (struct value *v)
     
     LinkedList0Node *ln;
     while (ln = LinkedList0_GetFirst(&v->refs_list)) {
-        struct instance *inst = UPPER_OBJECT(ln, struct instance, refs_list_node);
-        ASSERT(inst->v == v)
-        LinkedList0_Remove(&v->refs_list, &inst->refs_list_node);
-        inst->v = NULL;
+        struct valref *r = UPPER_OBJECT(ln, struct valref, refs_list_node);
+        ASSERT(r->v == v)
+        valref_break(r);
     }
     
     switch (v->type) {
@@ -273,21 +282,6 @@ static void value_delete (struct value *v)
     free(v);
 }
 
-static void value_remove_from_parent (struct value *v)
-{
-    ASSERT(v->parent)
-    
-    switch (v->parent->type) {
-        case NCDVALUE_LIST: {
-            value_list_remove(v->parent, v);
-        } break;
-        case NCDVALUE_MAP: {
-            value_map_remove(v->parent, v);
-        } break;
-        default: ASSERT(0);
-    }
-}
-
 static struct value * value_init_string (NCDModuleInst *i, const char *str)
 {
     struct value *v = malloc(sizeof(*v));
@@ -351,6 +345,17 @@ static struct value * value_list_at (struct value *v, size_t index)
     return e;
 }
 
+static size_t value_list_indexof (struct value *v, struct value *ev)
+{
+    ASSERT(v->type == NCDVALUE_LIST)
+    ASSERT(ev->parent == v)
+    
+    uint64_t index = IndexedList_IndexOf(&v->list.list_contents_il, &ev->list_parent.list_contents_il_node);
+    ASSERT(index < value_list_len(v))
+    
+    return index;
+}
+
 static int value_list_insert (NCDModuleInst *i, struct value *list, struct value *v, size_t index)
 {
     ASSERT(list->type == NCDVALUE_LIST)
@@ -460,6 +465,17 @@ static void value_map_remove (struct value *map, struct value *v)
     v->parent = NULL;
 }
 
+static void value_map_remove2 (struct value *map, struct value *v, NCDValue *out_key)
+{
+    ASSERT(map->type == NCDVALUE_MAP)
+    ASSERT(v->parent == map)
+    ASSERT(out_key)
+    
+    BCountAVL_Remove(&map->map.map_contents_tree, &v->map_parent.map_contents_tree_node);
+    *out_key = v->map_parent.key;
+    v->parent = NULL;
+}
+
 static struct value * value_init_fromvalue (NCDModuleInst *i, NCDValue *value)
 {
     struct value *v;
@@ -782,8 +798,41 @@ fail:
     return 0;
 }
 
-static void func_new_common (NCDModuleInst *i, struct value *v, int remove_on_deinit)
+static void valref_init (struct valref *r, struct value *v)
 {
+    r->v = v;
+    
+    if (v) {
+        LinkedList0_Prepend(&v->refs_list, &r->refs_list_node);
+    }
+}
+
+static void valref_free (struct valref *r)
+{
+    if (r->v) {
+        LinkedList0_Remove(&r->v->refs_list, &r->refs_list_node);
+        value_cleanup(r->v);
+    }
+}
+
+static struct value * valref_val (struct valref *r)
+{
+    return r->v;
+}
+
+static void valref_break (struct valref *r)
+{
+    ASSERT(r->v)
+    
+    LinkedList0_Remove(&r->v->refs_list, &r->refs_list_node);
+    r->v = NULL;
+}
+
+static void func_new_common (NCDModuleInst *i, struct value *v, int restore_on_deinit, struct value *restore_v)
+{
+    ASSERT(!(!restore_on_deinit) || !restore_v)
+    ASSERT(!(restore_v) || !restore_v->parent)
+    
     // allocate instance
     struct instance *o = malloc(sizeof(*o));
     if (!o) {
@@ -793,16 +842,12 @@ static void func_new_common (NCDModuleInst *i, struct value *v, int remove_on_de
     o->i = i;
     NCDModuleInst_Backend_SetUser(i, o);
     
-    // set value
-    o->v = v;
+    // init value references
+    valref_init(&o->ref, v);
+    valref_init(&o->restore_ref, restore_v);
     
-    if (v) {
-        // add reference
-        LinkedList0_Prepend(&o->v->refs_list, &o->refs_list_node);
-    }
-    
-    // set remove on deinit flag
-    o->remove_on_deinit = remove_on_deinit;
+    // set restore on deinit flag
+    o->restore_on_deinit = restore_on_deinit;
     
     NCDModuleInst_Backend_Up(i);
     return;
@@ -820,19 +865,41 @@ static void func_die (void *vo)
     struct instance *o = vo;
     NCDModuleInst *i = o->i;
     
-    if (o->v) {
-        // remove reference
-        LinkedList0_Remove(&o->v->refs_list, &o->refs_list_node);
+    struct value *v = valref_val(&o->ref);
+    
+    if (o->restore_on_deinit && v && v->parent) {
+        // get restore value
+        struct value *rv = valref_val(&o->restore_ref);
+        ASSERT(!rv || !rv->parent)
         
-        // remove value from parent if requested
-        if (o->remove_on_deinit && o->v->parent) {
-            value_remove_from_parent(o->v);
+        // remove this value from parent and restore saved one (or none)
+        switch (v->parent->type) {
+            case NCDVALUE_LIST: {
+                size_t index = value_list_indexof(v->parent, v);
+                value_list_remove(v->parent, v);
+                if (rv) {
+                    int res = value_list_insert(i, v->parent, rv, index);
+                    ASSERT(res)
+                }
+            } break;
+            case NCDVALUE_MAP: {
+                NCDValue key;
+                value_map_remove2(v->parent, v, &key);
+                if (rv) {
+                    int res = value_map_insert(v->parent, rv, key, i);
+                    ASSERT(res)
+                } else {
+                    NCDValue_Free(&key);
+                }
+            } break;
+            default: ASSERT(0);
         }
-        
-        // cleanup after removing reference
-        value_cleanup(o->v);
     }
     
+    // free value references
+    valref_free(&o->ref);
+    valref_free(&o->restore_ref);
+    
     // free instance
     free(o);
     
@@ -842,9 +909,10 @@ static void func_die (void *vo)
 static int func_getvar (void *vo, const char *name, NCDValue *out_value)
 {
     struct instance *o = vo;
+    struct value *v = valref_val(&o->ref);
     
     if (!strcmp(name, "exists")) {
-        const char *str = o->v ? "true" : "false";
+        const char *str = v ? "true" : "false";
         if (!NCDValue_InitString(out_value, str)) {
             ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitString failed");
             return 0;
@@ -856,25 +924,25 @@ static int func_getvar (void *vo, const char *name, NCDValue *out_value)
         return 0;
     }
     
-    if (!o->v) {
+    if (!v) {
         ModuleLog(o->i, BLOG_ERROR, "value was deleted");
         return 0;
     }
     
     if (!strcmp(name, "type")) {
-        if (!NCDValue_InitString(out_value, get_type_str(o->v->type))) {
+        if (!NCDValue_InitString(out_value, get_type_str(v->type))) {
             ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitString failed");
             return 0;
         }
     }
     else if (!strcmp(name, "length")) {
         size_t len;
-        switch (o->v->type) {
+        switch (v->type) {
             case NCDVALUE_LIST:
-                len = value_list_len(o->v);
+                len = value_list_len(v);
                 break;
             case NCDVALUE_MAP:
-                len = value_map_len(o->v);
+                len = value_map_len(v);
                 break;
             default:
                 ModuleLog(o->i, BLOG_ERROR, "value is not a list or map");
@@ -889,15 +957,15 @@ static int func_getvar (void *vo, const char *name, NCDValue *out_value)
         }
     }
     else if (!strcmp(name, "keys")) {
-        if (o->v->type != NCDVALUE_MAP) {
+        if (v->type != NCDVALUE_MAP) {
             ModuleLog(o->i, BLOG_ERROR, "value is not a map (reading keys variable)");
             return 0;
         }
         
         NCDValue_InitList(out_value);
         
-        for (size_t i = 0; i < value_map_len(o->v); i++) {
-            struct value *ev = value_map_at(o->v, i);
+        for (size_t i = 0; i < value_map_len(v); i++) {
+            struct value *ev = value_map_at(v, i);
             
             NCDValue key;
             if (!NCDValue_InitCopy(&key, &ev->map_parent.key)) {
@@ -919,7 +987,7 @@ static int func_getvar (void *vo, const char *name, NCDValue *out_value)
         return 0;
     }
     else if (!strcmp(name, "")) {
-        if (!value_to_value(o->i, o->v, out_value)) {
+        if (!value_to_value(o->i, v, out_value)) {
             return 0;
         }
     }
@@ -943,7 +1011,7 @@ static void func_new_value (NCDModuleInst *i)
         goto fail0;
     }
     
-    func_new_common(i, v, 0);
+    func_new_common(i, v, 0, NULL);
     return;
     
 fail0:
@@ -960,18 +1028,19 @@ static void func_new_get (NCDModuleInst *i)
     }
     
     struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
+    struct value *mov = valref_val(&mo->ref);
     
-    if (!mo->v) {
+    if (!mov) {
         ModuleLog(i, BLOG_ERROR, "value was deleted");
         goto fail0;
     }
     
-    struct value *v = value_get(i, mo->v, where_arg, 0);
+    struct value *v = value_get(i, mov, where_arg, 0);
     if (!v) {
         goto fail0;
     }
     
-    func_new_common(i, v, 0);
+    func_new_common(i, v, 0, NULL);
     return;
     
 fail0:
@@ -988,15 +1057,16 @@ static void func_new_try_get (NCDModuleInst *i)
     }
     
     struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
+    struct value *mov = valref_val(&mo->ref);
     
-    if (!mo->v) {
+    if (!mov) {
         ModuleLog(i, BLOG_ERROR, "value was deleted");
         goto fail0;
     }
     
-    struct value *v = value_get(i, mo->v, where_arg, 1);
+    struct value *v = value_get(i, mov, where_arg, 1);
     
-    func_new_common(i, v, 0);
+    func_new_common(i, v, 0, NULL);
     return;
     
 fail0:
@@ -1017,18 +1087,19 @@ static void func_new_getpath (NCDModuleInst *i)
     }
     
     struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
+    struct value *mov = valref_val(&mo->ref);
     
-    if (!mo->v) {
+    if (!mov) {
         ModuleLog(i, BLOG_ERROR, "value was deleted");
         goto fail0;
     }
     
-    struct value *v = value_get_path(i, mo->v, path_arg);
+    struct value *v = value_get_path(i, mov, path_arg);
     if (!v) {
         goto fail0;
     }
     
-    func_new_common(i, v, 0);
+    func_new_common(i, v, 0, NULL);
     return;
     
 fail0:
@@ -1046,18 +1117,19 @@ static void func_new_insert (NCDModuleInst *i)
     }
     
     struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
+    struct value *mov = valref_val(&mo->ref);
     
-    if (!mo->v) {
+    if (!mov) {
         ModuleLog(i, BLOG_ERROR, "value was deleted");
         goto fail0;
     }
     
-    struct value *v = value_insert(i, mo->v, where_arg, what_arg);
+    struct value *v = value_insert(i, mov, where_arg, what_arg);
     if (!v) {
         goto fail0;
     }
     
-    func_new_common(i, v, 0);
+    func_new_common(i, v, 0, NULL);
     return;
     
 fail0:
@@ -1075,18 +1147,19 @@ static void func_new_insert_remove (NCDModuleInst *i)
     }
     
     struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
+    struct value *mov = valref_val(&mo->ref);
     
-    if (!mo->v) {
+    if (!mov) {
         ModuleLog(i, BLOG_ERROR, "value was deleted");
         goto fail0;
     }
     
-    struct value *v = value_insert(i, mo->v, where_arg, what_arg);
+    struct value *v = value_insert(i, mov, where_arg, what_arg);
     if (!v) {
         goto fail0;
     }
     
-    func_new_common(i, v, 1);
+    func_new_common(i, v, 1, NULL);
     return;
     
 fail0:
@@ -1103,13 +1176,14 @@ static void remove_func_new (NCDModuleInst *i)
     }
     
     struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
+    struct value *mov = valref_val(&mo->ref);
     
-    if (!mo->v) {
+    if (!mov) {
         ModuleLog(i, BLOG_ERROR, "value was deleted");
         goto fail0;
     }
     
-    if (!value_remove(i, mo->v, where_arg)) {
+    if (!value_remove(i, mov, where_arg)) {
         goto fail0;
     }
     
@@ -1129,13 +1203,14 @@ static void delete_func_new (NCDModuleInst *i)
     }
     
     struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
+    struct value *mov = valref_val(&mo->ref);
     
-    if (!mo->v) {
+    if (!mov) {
         ModuleLog(i, BLOG_ERROR, "value was deleted");
         goto fail0;
     }
     
-    value_delete(mo->v);
+    value_delete(mov);
     
     NCDModuleInst_Backend_Up(i);
     return;