From: Marek VavruĊĦa Date: Sat, 18 Apr 2015 21:30:16 +0000 (+0200) Subject: lib/generic: implemented deletion for pack X-Git-Tag: v1.0.0-beta1~237^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5502f48a3a9cded75757e2f2d243add0bf8321e;p=thirdparty%2Fknot-resolver.git lib/generic: implemented deletion for pack --- diff --git a/lib/generic/pack.h b/lib/generic/pack.h index 49f9a0c30..33e889c53 100644 --- a/lib/generic/pack.h +++ b/lib/generic/pack.h @@ -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 diff --git a/tests/test_pack.c b/tests/test_pack.c index 27c09bffd..f5ad501cd 100644 --- a/tests/test_pack.c +++ b/tests/test_pack.c @@ -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); }