Browse Source

ncd: modules: value: add value::set() and test code

ambrop7 13 years ago
parent
commit
05eecc0a5c
2 changed files with 75 additions and 5 deletions
  1. 58 5
      ncd/modules/value.c
  2. 17 0
      ncd/tests/value.ncd

+ 58 - 5
ncd/modules/value.c

@@ -40,6 +40,8 @@
  * 
  * Description:
  *   Value objects allow examining and manipulating values.
+ *   These value objects are actually references to internal value structures, which
+ *   may be shared between value objects.
  * 
  *   value(value) constructs a new value object from the given value.
  * 
@@ -72,9 +74,9 @@
  *   list, the value at the specified index is replaced with the new value (unless
  *   the index is equal to the length of the list).
  * 
- *   value::insert_undo(where, what) and value::replace_undo(where, what) are versions
- *   of insert() and replace() which attempt to revert the modifications when they
- *   deinitialize. Specifically, they work like that:
+ *   insert_undo() and replace_undo() are versions of insert() and replace() which
+ *   attempt to revert the modifications when they deinitialize.
+ *   Specifically, they work like that:
  *   - On initiialization, they take an internal reference to the value being replaced
  *     (if any; note that insert_undo() into a list never replaces a value).
  *   - On deinitialization, they remove the the inserted value from its parent (if there
@@ -118,6 +120,16 @@
  *   'length' specifies the maximum number of characters to extract, if given.
  *   The newly constructed value is a copy of the extracted substring.
  *   The value must be a string value.
+ * 
+ * Synopsis:
+ *   value::set(what)
+ * 
+ * Description:
+ *   Effectively deconstructs and reconstructs the value object. More precisely,
+ *   it builds a new value structure from 'what', possibly invokes a scheduled undo
+ *   operation (as scheduled by insert_undo() and replace_undo()), sets up this
+ *   value object to reference the newly built value structure, without any scheduled
+ *   undo operation.
  */
 
 #include <stdlib.h>
@@ -1154,7 +1166,7 @@ struct insert_undo_deinit_data {
     struct valref oldval_ref;
 };
 
-static void insert_undo_deinit_func (struct insert_undo_deinit_data *data, NCDModuleInst *i)
+static void undo_deinit_func (struct insert_undo_deinit_data *data, NCDModuleInst *i)
 {
     struct value *val = valref_val(&data->val_ref);
     struct value *oldval = valref_val(&data->oldval_ref);
@@ -1227,7 +1239,7 @@ static void func_new_insert_replace_undo_common (void *vo, NCDModuleInst *i, int
     valref_init(&data->val_ref, v);
     valref_init(&data->oldval_ref, oldv);
     
-    func_new_common(vo, i, v, (value_deinit_func)insert_undo_deinit_func, data);
+    func_new_common(vo, i, v, (value_deinit_func)undo_deinit_func, data);
     return;
     
 fail1:
@@ -1360,6 +1372,44 @@ fail0:
     NCDModuleInst_Backend_Dead(i);
 }
 
+static void set_func_new (NCDModuleInst *i)
+{
+    NCDValRef what_arg;
+    if (!NCDVal_ListRead(i->args, 1, &what_arg)) {
+        ModuleLog(i, BLOG_ERROR, "wrong arity");
+        goto fail0;
+    }
+    
+    struct instance *mo = NCDModuleInst_Backend_GetUser((NCDModuleInst *)i->method_user);
+    
+    // build value from argument
+    struct value *newv = value_init_fromvalue(i, what_arg);
+    if (!newv) {
+        goto fail0;
+    }
+    
+    // deinit
+    if (mo->deinit_func) {
+        mo->deinit_func(mo->deinit_data, i);
+    }
+    
+    // free value reference
+    valref_free(&mo->ref);
+    
+    // set up value reference
+    valref_init(&mo->ref, newv);
+    
+    // set no deinit function
+    mo->deinit_func = NULL;
+    
+    NCDModuleInst_Backend_Up(i);
+    return;
+    
+fail0:
+    NCDModuleInst_Backend_SetError(i);
+    NCDModuleInst_Backend_Dead(i);
+}
+
 static const struct NCDModule modules[] = {
     {
         .type = "value",
@@ -1422,6 +1472,9 @@ static const struct NCDModule modules[] = {
     }, {
         .type = "value::delete",
         .func_new = delete_func_new
+    }, {
+        .type = "value::set",
+        .func_new = set_func_new
     }, {
         .type = "value::substr",
         .base_type = "value",

+ 17 - 0
ncd/tests/value.ncd

@@ -104,6 +104,23 @@ process main {
     val_equal(v, {"A", "B", "C", "D"}) a;
     assert(a);
 
+    value("A") v;
+    v->set("B");
+    val_equal(v, "B") a;
+    assert(a);
+
+    value({"a", "c"}) v;
+    v->insert_undo("1", "b") vb;
+    val_equal(v, {"a", "b", "c"}) a;
+    assert(a);
+    val_equal(vb, "b") a;
+    assert(a);
+    vb->set("B");
+    val_equal(v, {"a", "c"}) a;
+    assert(a);
+    val_equal(vb, "B") a;
+    assert(a);
+
     println("succeeded");
     exit("0");
 }