]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/generic: implemented deletion for pack
authorMarek Vavruša <marek.vavrusa@nic.cz>
Sat, 18 Apr 2015 21:30:16 +0000 (23:30 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Sat, 18 Apr 2015 21:30:16 +0000 (23:30 +0200)
lib/generic/pack.h
tests/test_pack.c

index 49f9a0c3088cd93495ae5ffcefef7f670b80cb32..33e889c532fa6459e841bd8135c794d3a38da65e 100644 (file)
@@ -43,6 +43,9 @@
  *          it = pack_obj_next(it);
  *      }
  *
+ *      // Remove object
+ *      pack_obj_del(pack, U8("jedi"), 4);
+ *
  *      pack_clear(pack);
  *
  * \addtogroup generics
@@ -80,7 +83,7 @@ typedef array_t(uint8_t) pack_t;
        array_reserve_mm((pack), (pack).len + (sizeof(pack_objlen_t)*(objs_count) + (objs_len)), (reserve), (baton))
 /** Return pointer to first packed object. */
 #define pack_head(pack) \
-       &((pack).at[0])
+       ((pack).len > 0 ? &((pack).at[0]) : NULL)
 /** Return pack end pointer. */
 #define pack_tail(pack) \
        &((pack).at[(pack).len])
@@ -122,6 +125,26 @@ static inline int pack_obj_push(pack_t *pack, const uint8_t *obj, pack_objlen_t
        return 0;
 }
 
+/** Delete object from the pack
+  * @return 0 on success, negative number on failure
+  */
+static inline int pack_obj_del(pack_t *pack, const uint8_t *obj, pack_objlen_t len)
+{
+       uint8_t *endp = pack_tail(*pack);
+       uint8_t *it = pack_head(*pack);
+       while (it != endp) {
+               uint8_t *val = pack_obj_val(it);
+               if (pack_obj_len(it) == len && memcmp(obj, val, len) == 0) {
+                       size_t packed_len = len + sizeof(len);
+                       memmove(it, it + packed_len, endp - it - packed_len);
+                       pack->len -= packed_len;
+                       return 0;
+               }
+               it = pack_obj_next(it);
+       }
+       return -1;
+}
+
 #ifdef __cplusplus
 }
 #endif
index 27c09bffdea585b62964162bd58b67e9869fa4b9..f5ad501cd28580b1d0062e4c377407a7442917d4 100644 (file)
@@ -27,8 +27,9 @@ static void test_pack_std(void **state)
        pack_init(pack);
        assert_int_equal(pack.len, 0);
 
-       /* Push without reservation. */
+       /* Push/delete without reservation. */
        assert_int_not_equal(pack_obj_push(&pack, U8(""), 1), 0);
+       assert_int_not_equal(pack_obj_del(&pack, U8(""), 1), 0);
 
        /* Reserve capacity and fill. */
        assert_true(pack_reserve(pack, 10, 10 * 2) >= 0);
@@ -48,6 +49,10 @@ static void test_pack_std(void **state)
                count += 1;
        }
 
+       /* Delete */
+       assert_int_not_equal(pack_obj_del(&pack, U8("be"), 2), 0);
+       assert_int_equal(pack_obj_del(&pack, U8("de"), 2), 0);
+       assert_int_equal(pack.len, 9*(2+2)); /* 9 objects, length=2 */
 
        pack_clear(pack);
 }