diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | include/libast/linked_list.h | 1 | ||||
-rw-r--r-- | include/libast/map_if.h | 8 | ||||
-rw-r--r-- | include/libast/str.h | 6 | ||||
-rw-r--r-- | libast.spec | 2 | ||||
-rw-r--r-- | src/linked_list.c | 271 | ||||
-rw-r--r-- | src/str.c | 75 | ||||
-rw-r--r-- | test/test.c | 281 |
8 files changed, 627 insertions, 23 deletions
@@ -633,3 +633,9 @@ Wed Mar 3 12:25:22 2004 Michael Jennings (mej) New and improved autogen stuff. Prefers autoconf 2.13 and automake 1.4, but it's also been tested with autoconf 2.57 and automake 1.6.3. ---------------------------------------------------------------------- +Wed Mar 10 17:15:14 2004 Michael Jennings (mej) + +Working map implementation using the linked_list class. + +Added some new string functions. +---------------------------------------------------------------------- diff --git a/include/libast/linked_list.h b/include/libast/linked_list.h index e88fbd4..861e602 100644 --- a/include/libast/linked_list.h +++ b/include/libast/linked_list.h @@ -48,5 +48,6 @@ SPIF_DECL_OBJ(linked_list) { extern spif_listclass_t SPIF_LISTCLASS_VAR(linked_list); extern spif_vectorclass_t SPIF_VECTORCLASS_VAR(linked_list); +extern spif_mapclass_t SPIF_MAPCLASS_VAR(linked_list); #endif /* _LIBAST_LINKED_LIST_H_ */ diff --git a/include/libast/map_if.h b/include/libast/map_if.h index 034b19f..9a23e3a 100644 --- a/include/libast/map_if.h +++ b/include/libast/map_if.h @@ -56,11 +56,11 @@ #define SPIF_MAP_COUNT(o) SPIF_CAST_C(size_t) ((SPIF_MAP_CALL_METHOD((o), count))(o)) #define SPIF_MAP_GET(o, key) SPIF_CAST(obj) ((SPIF_MAP_CALL_METHOD((o), get))(o, key)) -#define SPIF_MAP_GET_KEYS(o) SPIF_CAST(list) ((SPIF_MAP_CALL_METHOD((o), get_keys))(o)) -#define SPIF_MAP_GET_PAIRS(o) SPIF_CAST(list) ((SPIF_MAP_CALL_METHOD((o), get_pairs))(o)) -#define SPIF_MAP_GET_VALUES(o) SPIF_CAST(list) ((SPIF_MAP_CALL_METHOD((o), get_values))(o)) +#define SPIF_MAP_GET_KEYS(o, l) SPIF_CAST(list) ((SPIF_MAP_CALL_METHOD((o), get_keys))(o, l)) +#define SPIF_MAP_GET_PAIRS(o, l) SPIF_CAST(list) ((SPIF_MAP_CALL_METHOD((o), get_pairs))(o, l)) +#define SPIF_MAP_GET_VALUES(o, l) SPIF_CAST(list) ((SPIF_MAP_CALL_METHOD((o), get_values))(o, l)) #define SPIF_MAP_HAS_KEY(o, key) SPIF_CAST(bool) ((SPIF_MAP_CALL_METHOD((o), has_key))(o, key)) -#define SPIF_MAP_HAS_VALUE(o, value) SPIF_CAST(bool) ((SPIF_MAP_CALL_METHOD((o), hash_value))(o, value)) +#define SPIF_MAP_HAS_VALUE(o, value) SPIF_CAST(bool) ((SPIF_MAP_CALL_METHOD((o), has_value))(o, value)) #define SPIF_MAP_ITERATOR(o) SPIF_CAST(iterator) ((SPIF_MAP_CALL_METHOD((o), iterator))(o)) #define SPIF_MAP_REMOVE(o, item) SPIF_CAST(obj) ((SPIF_MAP_CALL_METHOD((o), remove))(o, item)) #define SPIF_MAP_SET(o, key, value) SPIF_CAST(bool) ((SPIF_MAP_CALL_METHOD((o), set))(o, key, value)) diff --git a/include/libast/str.h b/include/libast/str.h index fe45c8c..76cb1d8 100644 --- a/include/libast/str.h +++ b/include/libast/str.h @@ -68,6 +68,7 @@ extern spif_str_t spif_str_show(spif_str_t, spif_charptr_t, spif_str_t, size_t); extern spif_cmp_t spif_str_comp(spif_str_t, spif_str_t); extern spif_str_t spif_str_dup(spif_str_t); extern spif_classname_t spif_str_type(spif_str_t); + extern spif_bool_t spif_str_append(spif_str_t, spif_str_t); extern spif_bool_t spif_str_append_char(spif_str_t, spif_char_t); extern spif_bool_t spif_str_append_from_ptr(spif_str_t, spif_charptr_t); @@ -76,6 +77,7 @@ extern spif_cmp_t spif_str_casecmp_with_ptr(spif_str_t, spif_charptr_t); extern spif_bool_t spif_str_clear(spif_str_t, spif_char_t); extern spif_cmp_t spif_str_cmp(spif_str_t, spif_str_t); extern spif_cmp_t spif_str_cmp_with_ptr(spif_str_t, spif_charptr_t); +extern spif_bool_t spif_str_downcase(spif_str_t); extern spif_stridx_t spif_str_find(spif_str_t, spif_str_t); extern spif_stridx_t spif_str_find_from_ptr(spif_str_t, spif_charptr_t); extern spif_stridx_t spif_str_index(spif_str_t, spif_char_t); @@ -83,6 +85,9 @@ extern spif_cmp_t spif_str_ncasecmp(spif_str_t, spif_str_t, spif_stridx_t); extern spif_cmp_t spif_str_ncasecmp_with_ptr(spif_str_t, spif_charptr_t, spif_stridx_t); extern spif_cmp_t spif_str_ncmp(spif_str_t, spif_str_t, spif_stridx_t); extern spif_cmp_t spif_str_ncmp_with_ptr(spif_str_t, spif_charptr_t, spif_stridx_t); +extern spif_bool_t spif_str_prepend(spif_str_t, spif_str_t); +extern spif_bool_t spif_str_prepend_char(spif_str_t, spif_char_t); +extern spif_bool_t spif_str_prepend_from_ptr(spif_str_t, spif_charptr_t); extern spif_bool_t spif_str_reverse(spif_str_t); extern spif_stridx_t spif_str_rindex(spif_str_t, spif_char_t); extern spif_bool_t spif_str_splice(spif_str_t, spif_stridx_t, spif_stridx_t, spif_str_t); @@ -92,6 +97,7 @@ extern spif_charptr_t spif_str_substr_to_ptr(spif_str_t, spif_stridx_t, spif_str extern double spif_str_to_float(spif_str_t); extern size_t spif_str_to_num(spif_str_t, int); extern spif_bool_t spif_str_trim(spif_str_t); +extern spif_bool_t spif_str_upcase(spif_str_t); SPIF_DECL_PROPERTY_FUNC_C(str, spif_stridx_t, size); SPIF_DECL_PROPERTY_FUNC_C(str, spif_stridx_t, len); diff --git a/libast.spec b/libast.spec index e37dc37..cc6219b 100644 --- a/libast.spec +++ b/libast.spec @@ -1,7 +1,7 @@ Summary: Library of Assorted Spiffy Things Name: libast Version: 0.6 -Release: 0.8 +Release: 0.9 Copyright: BSD Group: System Environment/Libraries Source: %{name}-%{version}.tar.gz diff --git a/src/linked_list.c b/src/linked_list.c index 92006bf..398ec16 100644 --- a/src/linked_list.c +++ b/src/linked_list.c @@ -50,31 +50,42 @@ SPIF_DECL_PROPERTY_FUNC(linked_list_item, linked_list_item, next); static spif_linked_list_t spif_linked_list_new(void); static spif_linked_list_t spif_linked_list_vector_new(void); +static spif_linked_list_t spif_linked_list_map_new(void); static spif_bool_t spif_linked_list_init(spif_linked_list_t); static spif_bool_t spif_linked_list_vector_init(spif_linked_list_t); +static spif_bool_t spif_linked_list_map_init(spif_linked_list_t); static spif_bool_t spif_linked_list_done(spif_linked_list_t); static spif_bool_t spif_linked_list_del(spif_linked_list_t); static spif_str_t spif_linked_list_show(spif_linked_list_t, spif_charptr_t, spif_str_t, size_t); static spif_cmp_t spif_linked_list_comp(spif_linked_list_t, spif_linked_list_t); static spif_linked_list_t spif_linked_list_dup(spif_linked_list_t); static spif_linked_list_t spif_linked_list_vector_dup(spif_linked_list_t); +static spif_linked_list_t spif_linked_list_map_dup(spif_linked_list_t); static spif_classname_t spif_linked_list_type(spif_linked_list_t); -static spif_bool_t spif_linked_list_append(spif_linked_list_t, spif_obj_t); -static spif_bool_t spif_linked_list_contains(spif_linked_list_t, spif_obj_t); -static spif_bool_t spif_linked_list_vector_contains(spif_linked_list_t, spif_obj_t); -static spif_listidx_t spif_linked_list_count(spif_linked_list_t); -static spif_obj_t spif_linked_list_find(spif_linked_list_t, spif_obj_t); -static spif_obj_t spif_linked_list_vector_find(spif_linked_list_t, spif_obj_t); -static spif_obj_t spif_linked_list_get(spif_linked_list_t, spif_listidx_t); -static spif_listidx_t spif_linked_list_index(spif_linked_list_t, spif_obj_t); -static spif_bool_t spif_linked_list_insert(spif_linked_list_t, spif_obj_t); -static spif_bool_t spif_linked_list_insert_at(spif_linked_list_t, spif_obj_t, spif_listidx_t); -static spif_iterator_t spif_linked_list_iterator(spif_linked_list_t); -static spif_bool_t spif_linked_list_prepend(spif_linked_list_t, spif_obj_t); -static spif_obj_t spif_linked_list_remove(spif_linked_list_t, spif_obj_t); -static spif_obj_t spif_linked_list_remove_at(spif_linked_list_t, spif_listidx_t); -static spif_bool_t spif_linked_list_reverse(spif_linked_list_t); -static spif_obj_t *spif_linked_list_to_array(spif_linked_list_t); +static spif_bool_t spif_linked_list_append(spif_linked_list_t self, spif_obj_t obj); +static spif_bool_t spif_linked_list_contains(spif_linked_list_t self, spif_obj_t obj); +static spif_bool_t spif_linked_list_vector_contains(spif_linked_list_t self, spif_obj_t obj); +static spif_listidx_t spif_linked_list_count(spif_linked_list_t self); +static spif_obj_t spif_linked_list_find(spif_linked_list_t self, spif_obj_t obj); +static spif_obj_t spif_linked_list_vector_find(spif_linked_list_t self, spif_obj_t obj); +static spif_obj_t spif_linked_list_get(spif_linked_list_t self, spif_listidx_t idx); +static spif_obj_t spif_linked_list_map_get(spif_linked_list_t self, spif_obj_t key); +static spif_list_t spif_linked_list_get_keys(spif_linked_list_t self, spif_list_t key_list); +static spif_list_t spif_linked_list_get_pairs(spif_linked_list_t self, spif_list_t pair_list); +static spif_list_t spif_linked_list_get_values(spif_linked_list_t self, spif_list_t value_list); +static spif_bool_t spif_linked_list_has_key(spif_linked_list_t self, spif_obj_t key); +static spif_bool_t spif_linked_list_has_value(spif_linked_list_t self, spif_obj_t value); +static spif_listidx_t spif_linked_list_index(spif_linked_list_t self, spif_obj_t obj); +static spif_bool_t spif_linked_list_insert(spif_linked_list_t self, spif_obj_t obj); +static spif_bool_t spif_linked_list_insert_at(spif_linked_list_t self, spif_obj_t obj, spif_listidx_t idx); +static spif_iterator_t spif_linked_list_iterator(spif_linked_list_t self); +static spif_bool_t spif_linked_list_prepend(spif_linked_list_t self, spif_obj_t obj); +static spif_obj_t spif_linked_list_remove(spif_linked_list_t self, spif_obj_t item); +static spif_obj_t spif_linked_list_map_remove(spif_linked_list_t self, spif_obj_t item); +static spif_obj_t spif_linked_list_remove_at(spif_linked_list_t self, spif_listidx_t idx); +static spif_bool_t spif_linked_list_reverse(spif_linked_list_t self); +static spif_bool_t spif_linked_list_set(spif_linked_list_t self, spif_obj_t key, spif_obj_t value); +static spif_obj_t * spif_linked_list_to_array(spif_linked_list_t self); SPIF_DECL_PROPERTY_FUNC(linked_list, listidx, len); SPIF_DECL_PROPERTY_FUNC(linked_list, linked_list_item, head); @@ -156,6 +167,31 @@ static spif_const_vectorclass_t llv_class = { }; spif_vectorclass_t SPIF_VECTORCLASS_VAR(linked_list) = &llv_class; +static spif_const_mapclass_t llm_class = { + { + SPIF_DECL_CLASSNAME(linked_list), + (spif_func_t) spif_linked_list_map_new, + (spif_func_t) spif_linked_list_map_init, + (spif_func_t) spif_linked_list_done, + (spif_func_t) spif_linked_list_del, + (spif_func_t) spif_linked_list_show, + (spif_func_t) spif_linked_list_comp, + (spif_func_t) spif_linked_list_map_dup, + (spif_func_t) spif_linked_list_type + }, + (spif_func_t) spif_linked_list_count, + (spif_func_t) spif_linked_list_map_get, + (spif_func_t) spif_linked_list_get_keys, + (spif_func_t) spif_linked_list_get_pairs, + (spif_func_t) spif_linked_list_get_values, + (spif_func_t) spif_linked_list_has_key, + (spif_func_t) spif_linked_list_has_value, + (spif_func_t) spif_linked_list_iterator, + (spif_func_t) spif_linked_list_map_remove, + (spif_func_t) spif_linked_list_set +}; +spif_mapclass_t SPIF_MAPCLASS_VAR(linked_list) = &llm_class; + static spif_const_iteratorclass_t li_class = { { SPIF_DECL_CLASSNAME(linked_list), @@ -301,6 +337,19 @@ spif_linked_list_vector_new(void) return self; } +static spif_linked_list_t +spif_linked_list_map_new(void) +{ + spif_linked_list_t self; + + self = SPIF_ALLOC(linked_list); + if (!spif_linked_list_map_init(self)) { + SPIF_DEALLOC(self); + self = SPIF_NULL_TYPE(linked_list); + } + return self; +} + static spif_bool_t spif_linked_list_init(spif_linked_list_t self) { @@ -328,6 +377,19 @@ spif_linked_list_vector_init(spif_linked_list_t self) } static spif_bool_t +spif_linked_list_map_init(spif_linked_list_t self) +{ + spif_bool_t t; + + ASSERT_RVAL(!SPIF_LIST_ISNULL(self), FALSE); + /* ***NOT NEEDED*** spif_obj_init(SPIF_OBJ(self)); */ + t = spif_obj_set_class(SPIF_OBJ(self), SPIF_CLASS(SPIF_MAPCLASS_VAR(linked_list))); + self->len = 0; + self->head = SPIF_NULL_TYPE(linked_list_item); + return t; +} + +static spif_bool_t spif_linked_list_done(spif_linked_list_t self) { spif_linked_list_item_t current; @@ -436,6 +498,23 @@ spif_linked_list_vector_dup(spif_linked_list_t self) return tmp; } +static spif_linked_list_t +spif_linked_list_map_dup(spif_linked_list_t self) +{ + spif_linked_list_t tmp; + spif_linked_list_item_t src, dest; + + ASSERT_RVAL(!SPIF_LIST_ISNULL(self), SPIF_NULL_TYPE(linked_list)); + tmp = spif_linked_list_map_new(); + memcpy(tmp, self, SPIF_SIZEOF_TYPE(linked_list)); + tmp->head = spif_linked_list_item_dup(self->head); + for (src = self->head, dest = tmp->head; src->next; src = src->next, dest = dest->next) { + dest->next = spif_linked_list_item_dup(src->next); + } + dest->next = SPIF_NULL_TYPE(linked_list_item); + return tmp; +} + static spif_classname_t spif_linked_list_type(spif_linked_list_t self) { @@ -494,6 +573,7 @@ spif_linked_list_find(spif_linked_list_t self, spif_obj_t obj) ASSERT_RVAL(!SPIF_LIST_ISNULL(self), SPIF_NULL_TYPE(obj)); REQUIRE_RVAL(!SPIF_OBJ_ISNULL(obj), SPIF_NULL_TYPE(obj)); for (current = self->head; current; current = current->next) { + /* current->data may be NULL here, so use obj methods. */ if (SPIF_CMP_IS_EQUAL(SPIF_OBJ_COMP(obj, current->data))) { return current->data; } @@ -511,10 +591,12 @@ spif_linked_list_vector_find(spif_linked_list_t self, spif_obj_t obj) for (current = self->head; current; current = current->next) { spif_cmp_t c; - c = SPIF_OBJ_COMP(obj, current->data); + /* current->data is always non-NULL in vectors. */ + ASSERT_RVAL(!SPIF_OBJ_ISNULL(current->data), SPIF_NULL_TYPE(obj)); + c = SPIF_OBJ_COMP(current->data, obj); if (SPIF_CMP_IS_EQUAL(c)) { return current->data; - } else if (SPIF_CMP_IS_LESS(c)) { + } else if (SPIF_CMP_IS_GREATER(c)) { break; } } @@ -538,6 +620,103 @@ spif_linked_list_get(spif_linked_list_t self, spif_listidx_t idx) return (current ? (current->data) : SPIF_NULL_TYPE(obj)); } +static spif_obj_t +spif_linked_list_map_get(spif_linked_list_t self, spif_obj_t key) +{ + spif_linked_list_item_t current; + + ASSERT_RVAL(!SPIF_VECTOR_ISNULL(self), SPIF_NULL_TYPE(obj)); + REQUIRE_RVAL(!SPIF_OBJ_ISNULL(key), SPIF_NULL_TYPE(obj)); + for (current = self->head; current; current = current->next) { + spif_cmp_t c; + + /* current->data is always non-NULL in maps. */ + ASSERT_RVAL(!SPIF_OBJ_ISNULL(current->data), SPIF_NULL_TYPE(obj)); + c = SPIF_OBJ_COMP(current->data, key); + if (SPIF_CMP_IS_EQUAL(c)) { + return SPIF_OBJPAIR(current->data)->value; + } else if (SPIF_CMP_IS_GREATER(c)) { + break; + } + } + return SPIF_NULL_TYPE(obj); +} + +static spif_list_t +spif_linked_list_get_keys(spif_linked_list_t self, spif_list_t key_list) +{ + spif_linked_list_item_t current; + + ASSERT_RVAL(!SPIF_VECTOR_ISNULL(self), SPIF_NULL_TYPE(list)); + if (SPIF_LIST_ISNULL(key_list)) { + key_list = SPIF_LIST_NEW(linked_list); + } + for (current = self->head; current; current = current->next) { + /* current->data is always non-NULL in maps. */ + SPIF_LIST_APPEND(key_list, SPIF_OBJ_DUP(SPIF_OBJPAIR(current->data)->key)); + } + return key_list; +} + +static spif_list_t +spif_linked_list_get_pairs(spif_linked_list_t self, spif_list_t pair_list) +{ + spif_linked_list_item_t current; + + ASSERT_RVAL(!SPIF_VECTOR_ISNULL(self), SPIF_NULL_TYPE(list)); + if (SPIF_LIST_ISNULL(pair_list)) { + pair_list = SPIF_LIST_NEW(linked_list); + } + for (current = self->head; current; current = current->next) { + /* current->data is always non-NULL in maps. */ + SPIF_LIST_APPEND(pair_list, SPIF_OBJ_DUP(SPIF_OBJPAIR(current->data))); + } + return pair_list; +} + +static spif_list_t +spif_linked_list_get_values(spif_linked_list_t self, spif_list_t value_list) +{ + spif_linked_list_item_t current; + + ASSERT_RVAL(!SPIF_VECTOR_ISNULL(self), SPIF_NULL_TYPE(list)); + if (SPIF_LIST_ISNULL(value_list)) { + value_list = SPIF_LIST_NEW(linked_list); + } + for (current = self->head; current; current = current->next) { + /* current->data is always non-NULL in maps. */ + SPIF_LIST_APPEND(value_list, SPIF_OBJ_DUP(SPIF_OBJPAIR(current->data)->value)); + } + return value_list; +} + +static spif_bool_t +spif_linked_list_has_key(spif_linked_list_t self, spif_obj_t key) +{ + return ((SPIF_OBJ_ISNULL(spif_linked_list_map_get(self, key))) ? FALSE : TRUE); +} + +static spif_bool_t +spif_linked_list_has_value(spif_linked_list_t self, spif_obj_t value) +{ + spif_linked_list_item_t current; + + ASSERT_RVAL(!SPIF_VECTOR_ISNULL(self), FALSE); + + for (current = self->head; current; current = current->next) { + spif_objpair_t pair; + + /* current->data is always non-NULL in maps. */ + pair = SPIF_OBJPAIR(current->data); + if (SPIF_OBJ_ISNULL(value) && SPIF_OBJ_ISNULL(pair->value)) { + return TRUE; + } else if (SPIF_CMP_IS_EQUAL(SPIF_OBJ_COMP(pair->value, value))) { + return TRUE; + } + } + return FALSE; +} + static spif_listidx_t spif_linked_list_index(spif_linked_list_t self, spif_obj_t obj) { @@ -660,6 +839,35 @@ spif_linked_list_remove(spif_linked_list_t self, spif_obj_t item) } static spif_obj_t +spif_linked_list_map_remove(spif_linked_list_t self, spif_obj_t item) +{ + spif_linked_list_item_t current, tmp; + + ASSERT_RVAL(!SPIF_LIST_ISNULL(self), SPIF_NULL_TYPE(obj)); + REQUIRE_RVAL(!SPIF_OBJ_ISNULL(item), SPIF_NULL_TYPE(obj)); + if (SPIF_LINKED_LIST_ITEM_ISNULL(self->head)) { + return SPIF_NULL_TYPE(obj); + } else if (SPIF_CMP_IS_EQUAL(SPIF_OBJ_COMP(self->head->data, item))) { + tmp = self->head; + self->head = self->head->next; + } else { + for (current = self->head; current->next && !SPIF_CMP_IS_EQUAL(SPIF_OBJ_COMP(current->next->data, item)); current = current->next); + if (current->next) { + tmp = current->next; + current->next = current->next->next; + } else { + return SPIF_NULL_TYPE(obj); + } + } + item = tmp->data; + tmp->data = SPIF_NULL_TYPE(obj); + spif_linked_list_item_del(tmp); + + self->len--; + return item; +} + +static spif_obj_t spif_linked_list_remove_at(spif_linked_list_t self, spif_listidx_t idx) { spif_listidx_t i; @@ -709,6 +917,33 @@ spif_linked_list_reverse(spif_linked_list_t self) return TRUE; } +static spif_bool_t +spif_linked_list_set(spif_linked_list_t self, spif_obj_t key, spif_obj_t value) +{ + spif_linked_list_item_t current; + + ASSERT_RVAL(!SPIF_LIST_ISNULL(self), FALSE); + REQUIRE_RVAL(!SPIF_OBJ_ISNULL(key), FALSE); + + if (SPIF_OBJ_IS_OBJPAIR(key) && SPIF_OBJ_ISNULL(value)) { + value = SPIF_OBJ(SPIF_OBJPAIR(key)->value); + key = SPIF_OBJ(SPIF_OBJPAIR(key)->key); + } + for (current = self->head; current; current = current->next) { + if (SPIF_CMP_IS_EQUAL(SPIF_OBJ_COMP(current->data, key))) { + break; + } + } + + if (SPIF_LINKED_LIST_ITEM_ISNULL(current)) { + spif_linked_list_insert(self, SPIF_OBJ(spif_objpair_new_from_both(key, value))); + return FALSE; + } else { + spif_objpair_set_value(SPIF_OBJPAIR(current->data), SPIF_OBJ_DUP(value)); + return TRUE; + } +} + static spif_obj_t * spif_linked_list_to_array(spif_linked_list_t self) { @@ -405,6 +405,18 @@ spif_str_cmp_with_ptr(spif_str_t self, spif_charptr_t other) return SPIF_CMP_FROM_INT(strcmp(SPIF_CONST_CAST_C(char *) SPIF_STR_STR(self), SPIF_CONST_CAST_C(char *)other)); } +spif_bool_t +spif_str_downcase(spif_str_t self) +{ + char *tmp; + + ASSERT_RVAL(!SPIF_STR_ISNULL(self), FALSE); + for (tmp = self->s; *tmp; tmp++) { + *tmp = tolower(*tmp); + } + return TRUE; +} + spif_stridx_t spif_str_find(spif_str_t self, spif_str_t other) { @@ -480,6 +492,53 @@ spif_str_ncmp_with_ptr(spif_str_t self, spif_charptr_t other, spif_stridx_t cnt) } spif_bool_t +spif_str_prepend(spif_str_t self, spif_str_t other) +{ + ASSERT_RVAL(!SPIF_STR_ISNULL(self), FALSE); + REQUIRE_RVAL(!SPIF_STR_ISNULL(other), FALSE); + if (other->size && other->len) { + self->size += other->size - 1; + self->s = SPIF_CAST(charptr) REALLOC(self->s, self->size); + memmove(self->s + other->len, self->s, self->len + 1); + memcpy(self->s, SPIF_STR_STR(other), other->len); + self->len += other->len; + } + return TRUE; +} + +spif_bool_t +spif_str_prepend_char(spif_str_t self, spif_char_t c) +{ + ASSERT_RVAL(!SPIF_STR_ISNULL(self), FALSE); + self->len++; + if (self->size <= self->len) { + self->size++; + self->s = SPIF_CAST(charptr) REALLOC(self->s, self->size); + } + memmove(self->s + 1, self->s, self->len + 1); + self->s[0] = SPIF_CAST(uchar) c; + return TRUE; +} + +spif_bool_t +spif_str_prepend_from_ptr(spif_str_t self, spif_charptr_t other) +{ + spif_stridx_t len; + + ASSERT_RVAL(!SPIF_STR_ISNULL(self), FALSE); + REQUIRE_RVAL((other != SPIF_NULL_TYPE(charptr)), FALSE); + len = strlen(SPIF_CONST_CAST_C(char *) other); + if (len) { + self->size += len; + self->s = SPIF_CAST(charptr) REALLOC(self->s, self->size); + memmove(self->s + len, self->s, self->len + 1); + memcpy(self->s, other, len); + self->len += len; + } + return TRUE; +} + +spif_bool_t spif_str_reverse(spif_str_t self) { ASSERT_RVAL(!SPIF_STR_ISNULL(self), FALSE); @@ -587,10 +646,12 @@ spif_str_substr(spif_str_t self, spif_stridx_t idx, spif_stridx_t cnt) idx = self->len + idx; } REQUIRE_RVAL(idx >= 0, SPIF_NULL_TYPE(str)); + REQUIRE_RVAL(idx < self->len, SPIF_NULL_TYPE(str)); if (cnt <= 0) { cnt = self->len - idx + cnt; } REQUIRE_RVAL(cnt >= 0, SPIF_NULL_TYPE(str)); + UPPER_BOUND(cnt, self->len - idx); return spif_str_new_from_buff(SPIF_STR_STR(self) + idx, cnt); } @@ -604,10 +665,12 @@ spif_str_substr_to_ptr(spif_str_t self, spif_stridx_t idx, spif_stridx_t cnt) idx = self->len + idx; } REQUIRE_RVAL(idx >= 0, SPIF_NULL_TYPE(charptr)); + REQUIRE_RVAL(idx < self->len, SPIF_NULL_TYPE(charptr)); if (cnt <= 0) { cnt = self->len - idx + cnt; } REQUIRE_RVAL(cnt >= 0, SPIF_NULL_TYPE(charptr)); + UPPER_BOUND(cnt, self->len - idx); newstr = SPIF_CAST(charptr) MALLOC(cnt + 1); memcpy(newstr, SPIF_STR_STR(self) + idx, cnt); @@ -650,5 +713,17 @@ spif_str_trim(spif_str_t self) return TRUE; } +spif_bool_t +spif_str_upcase(spif_str_t self) +{ + char *tmp; + + ASSERT_RVAL(!SPIF_STR_ISNULL(self), FALSE); + for (tmp = self->s; *tmp; tmp++) { + *tmp = toupper(*tmp); + } + return TRUE; +} + SPIF_DEFINE_PROPERTY_FUNC_C(str, spif_stridx_t, size); SPIF_DEFINE_PROPERTY_FUNC_C(str, spif_stridx_t, len); diff --git a/test/test.c b/test/test.c index a82d725..6ede7d6 100644 --- a/test/test.c +++ b/test/test.c @@ -44,6 +44,7 @@ int test_tok(void); int test_url(void); int test_list(void); int test_vector(void); +int test_map(void); int test_socket(void); int test_regexp(void); @@ -1444,6 +1445,283 @@ test_vector(void) } int +test_map(void) +{ + unsigned short i; + spif_map_t testmap; + spif_obj_t ret; + spif_str_t key, value; + spif_url_t homepage; + spif_list_t testlist; + spif_iterator_t it; + size_t j; + + for (i = 0; i < 1; i++) { + if (i == 0) { + TEST_NOTICE("*** Testing map interface, linked_list class:"); + testmap = SPIF_MAP_NEW(linked_list); +#if 0 + } else if (i == 1) { + TEST_NOTICE("*** Testing map interface, dlinked_list class:"); + testmap = SPIF_MAP_NEW(dlinked_list); + } else if (i == 2) { + TEST_NOTICE("*** Testing map interface, array class:"); + testmap = SPIF_MAP_NEW(array); + } else if (i == 3) { +#endif + } + + TEST_BEGIN("SPIF_MAP_SET() macro"); + key = spif_str_new_from_ptr("name"); + value = spif_str_new_from_ptr("Bob"); + TEST_FAIL_IF(SPIF_MAP_SET(testmap, key, value)); + spif_str_done(key); + spif_str_done(value); + spif_str_init_from_ptr(key, "rank"); + spif_str_init_from_ptr(value, "Dweeb"); + TEST_FAIL_IF(SPIF_MAP_SET(testmap, key, value)); + spif_str_done(key); + spif_str_done(value); + spif_str_init_from_ptr(key, "serial number"); + spif_str_init_from_ptr(value, "123456"); + TEST_FAIL_IF(SPIF_MAP_SET(testmap, key, value)); + spif_str_done(key); + spif_str_done(value); + spif_str_init_from_ptr(key, "homepage"); + homepage = spif_url_new_from_ptr("http://www.dweeb.com/"); + TEST_FAIL_IF(SPIF_MAP_SET(testmap, key, homepage)); + spif_str_done(key); + spif_url_del(homepage); + spif_str_init_from_ptr(key, "e-mail"); + spif_str_init_from_ptr(value, "bob@dweeb.com"); + TEST_FAIL_IF(SPIF_MAP_SET(testmap, key, value)); + spif_str_done(key); + spif_str_done(value); + spif_str_init_from_ptr(key, "loser"); + spif_str_init_from_ptr(value, "YES"); + TEST_FAIL_IF(SPIF_MAP_SET(testmap, key, value)); + spif_str_del(key); + spif_str_del(value); + TEST_PASS(); + + TEST_BEGIN("SPIF_MAP_COUNT() macro"); + TEST_FAIL_IF(SPIF_MAP_COUNT(testmap) != 6); + TEST_PASS(); + + TEST_BEGIN("SPIF_MAP_GET() macro"); + key = spif_str_new_from_ptr("serial number"); + value = SPIF_CAST(str) SPIF_MAP_GET(testmap, key); + TEST_FAIL_IF(SPIF_STR_ISNULL(value)); + TEST_FAIL_IF(!SPIF_OBJ_IS_STR(value)); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(spif_str_cmp_with_ptr(value, "123456"))); + spif_str_done(key); + spif_str_init_from_ptr(key, "loser"); + value = SPIF_CAST(str) SPIF_MAP_GET(testmap, key); + TEST_FAIL_IF(SPIF_STR_ISNULL(value)); + TEST_FAIL_IF(!SPIF_OBJ_IS_STR(value)); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(spif_str_cmp_with_ptr(value, "YES"))); + spif_str_done(key); + spif_str_init_from_ptr(key, "name"); + value = SPIF_CAST(str) SPIF_MAP_GET(testmap, key); + TEST_FAIL_IF(SPIF_STR_ISNULL(value)); + TEST_FAIL_IF(!SPIF_OBJ_IS_STR(value)); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(spif_str_cmp_with_ptr(value, "Bob"))); + spif_str_done(key); + spif_str_init_from_ptr(key, "e-mail"); + value = SPIF_CAST(str) SPIF_MAP_GET(testmap, key); + TEST_FAIL_IF(SPIF_STR_ISNULL(value)); + TEST_FAIL_IF(!SPIF_OBJ_IS_STR(value)); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(spif_str_cmp_with_ptr(value, "bob@dweeb.com"))); + spif_str_done(key); + spif_str_init_from_ptr(key, "rank"); + value = SPIF_CAST(str) SPIF_MAP_GET(testmap, key); + TEST_FAIL_IF(SPIF_STR_ISNULL(value)); + TEST_FAIL_IF(!SPIF_OBJ_IS_STR(value)); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(spif_str_cmp_with_ptr(value, "Dweeb"))); + spif_str_done(key); + spif_str_init_from_ptr(key, "homepage"); + homepage = SPIF_CAST(url) SPIF_MAP_GET(testmap, key); + TEST_FAIL_IF(SPIF_URL_ISNULL(homepage)); + TEST_FAIL_IF(!SPIF_OBJ_IS_URL(homepage)); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(spif_str_cmp_with_ptr(SPIF_STR(homepage), "http://www.dweeb.com/"))); + spif_str_del(key); + TEST_PASS(); + + TEST_BEGIN("SPIF_MAP_GET_KEYS() macro"); + testlist = SPIF_LIST_NEW(array); + SPIF_MAP_GET_KEYS(testmap, testlist); + TEST_FAIL_IF(SPIF_LIST_COUNT(testlist) != SPIF_MAP_COUNT(testmap)); + key = spif_str_new_from_ptr("serial number"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "loser"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "name"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "e-mail"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "rank"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "homepage"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, key)); + spif_str_del(key); + value = spif_str_new_from_ptr("123456"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, value)); + spif_str_done(value); + spif_str_init_from_ptr(value, "YES"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, value)); + spif_str_done(value); + spif_str_init_from_ptr(value, "Bob"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, value)); + spif_str_done(value); + spif_str_init_from_ptr(value, "bob@dweeb.com"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, value)); + spif_str_done(value); + spif_str_init_from_ptr(value, "Dweeb"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, value)); + spif_str_del(value); + homepage = spif_url_new_from_ptr("http://www.dweeb.com/"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, homepage)); + spif_url_del(homepage); + SPIF_LIST_DEL(testlist); + TEST_PASS(); + + TEST_BEGIN("SPIF_MAP_GET_PAIRS() macro"); + testlist = SPIF_LIST_NEW(array); + SPIF_MAP_GET_PAIRS(testmap, testlist); + TEST_FAIL_IF(SPIF_LIST_COUNT(testlist) != SPIF_MAP_COUNT(testmap)); + SPIF_LIST_DEL(testlist); + TEST_PASS(); + + TEST_BEGIN("SPIF_MAP_GET_VALUES() macro"); + testlist = SPIF_LIST_NEW(array); + SPIF_MAP_GET_VALUES(testmap, testlist); + TEST_FAIL_IF(SPIF_LIST_COUNT(testlist) != SPIF_MAP_COUNT(testmap)); + key = spif_str_new_from_ptr("serial number"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "loser"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "name"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "e-mail"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "rank"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, key)); + spif_str_done(key); + spif_str_init_from_ptr(key, "homepage"); + TEST_FAIL_IF(SPIF_LIST_CONTAINS(testlist, key)); + spif_str_del(key); + value = spif_str_new_from_ptr("123456"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, value)); + spif_str_done(value); + spif_str_init_from_ptr(value, "YES"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, value)); + spif_str_done(value); + spif_str_init_from_ptr(value, "Bob"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, value)); + spif_str_done(value); + spif_str_init_from_ptr(value, "bob@dweeb.com"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, value)); + spif_str_done(value); + spif_str_init_from_ptr(value, "Dweeb"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, value)); + spif_str_del(value); + homepage = spif_url_new_from_ptr("http://www.dweeb.com/"); + TEST_FAIL_IF(!SPIF_LIST_CONTAINS(testlist, homepage)); + spif_url_del(homepage); + SPIF_LIST_DEL(testlist); + TEST_PASS(); + + TEST_BEGIN("SPIF_MAP_ITERATOR(), SPIF_MAP_HAS_KEY(), and SPIF_MAP_HAS_VALUE() macros"); + for (j = 0, it = SPIF_MAP_ITERATOR(testmap); SPIF_ITERATOR_HAS_NEXT(it); j++) { + spif_objpair_t tmp; + + tmp = SPIF_CAST(objpair) SPIF_ITERATOR_NEXT(it); + TEST_FAIL_IF(SPIF_OBJPAIR_ISNULL(tmp)); + TEST_FAIL_IF(!SPIF_MAP_HAS_KEY(testmap, tmp->key)); + TEST_FAIL_IF(!SPIF_MAP_HAS_VALUE(testmap, tmp->value)); + } + TEST_FAIL_IF(j != 6); + TEST_FAIL_IF(SPIF_ITERATOR_HAS_NEXT(it)); + TEST_FAIL_IF(!SPIF_OBJ_ISNULL(SPIF_ITERATOR_NEXT(it))); + SPIF_ITERATOR_DEL(it); + TEST_PASS(); + + TEST_BEGIN("SPIF_MAP_REMOVE() macro"); + key = spif_str_new_from_ptr("name"); + value = spif_str_new_from_ptr("Bob"); + ret = SPIF_MAP_REMOVE(testmap, key); + TEST_FAIL_IF(SPIF_OBJ_ISNULL(ret)); + TEST_FAIL_IF(!SPIF_OBJ_COMP(ret, value)); + TEST_FAIL_IF(SPIF_MAP_HAS_KEY(testmap, key)); + SPIF_OBJ_DEL(ret); + spif_str_done(key); + spif_str_done(value); + spif_str_init_from_ptr(key, "rank"); + spif_str_init_from_ptr(value, "Dweeb"); + ret = SPIF_MAP_REMOVE(testmap, key); + TEST_FAIL_IF(SPIF_OBJ_ISNULL(ret)); + TEST_FAIL_IF(!SPIF_OBJ_COMP(ret, value)); + TEST_FAIL_IF(SPIF_MAP_HAS_KEY(testmap, key)); + SPIF_OBJ_DEL(ret); + spif_str_done(key); + spif_str_done(value); + spif_str_init_from_ptr(key, "serial number"); + spif_str_init_from_ptr(value, "123456"); + ret = SPIF_MAP_REMOVE(testmap, key); + TEST_FAIL_IF(SPIF_OBJ_ISNULL(ret)); + TEST_FAIL_IF(!SPIF_OBJ_COMP(ret, value)); + TEST_FAIL_IF(SPIF_MAP_HAS_KEY(testmap, key)); + SPIF_OBJ_DEL(ret); + spif_str_done(key); + spif_str_done(value); + spif_str_init_from_ptr(key, "homepage"); + homepage = spif_url_new_from_ptr("http://www.dweeb.com/"); + ret = SPIF_MAP_REMOVE(testmap, key); + TEST_FAIL_IF(SPIF_OBJ_ISNULL(ret)); + TEST_FAIL_IF(!SPIF_OBJ_COMP(ret, homepage)); + TEST_FAIL_IF(SPIF_MAP_HAS_KEY(testmap, key)); + SPIF_OBJ_DEL(ret); + spif_str_done(key); + spif_url_del(homepage); + spif_str_init_from_ptr(key, "e-mail"); + spif_str_init_from_ptr(value, "bob@dweeb.com"); + ret = SPIF_MAP_REMOVE(testmap, key); + TEST_FAIL_IF(SPIF_OBJ_ISNULL(ret)); + TEST_FAIL_IF(!SPIF_OBJ_COMP(ret, value)); + TEST_FAIL_IF(SPIF_MAP_HAS_KEY(testmap, key)); + SPIF_OBJ_DEL(ret); + spif_str_done(key); + spif_str_done(value); + spif_str_init_from_ptr(key, "loser"); + spif_str_init_from_ptr(value, "YES"); + ret = SPIF_MAP_REMOVE(testmap, key); + TEST_FAIL_IF(SPIF_OBJ_ISNULL(ret)); + TEST_FAIL_IF(!SPIF_OBJ_COMP(ret, value)); + TEST_FAIL_IF(SPIF_MAP_HAS_KEY(testmap, key)); + SPIF_OBJ_DEL(ret); + spif_str_del(key); + spif_str_del(value); + TEST_FAIL_IF(SPIF_MAP_COUNT(testmap) != 0); + TEST_PASS(); + + /*SPIF_SHOW(testmap, stdout);*/ + SPIF_MAP_DEL(testmap); + } + + TEST_PASSED("map interface"); + return 0; +} + +int test_socket(void) { spif_socket_t src1, dest1, src2, dest2, listen1, listen2; @@ -1913,6 +2191,9 @@ main(int argc, char *argv[]) if ((ret = test_vector()) != 0) { return ret; } + if ((ret = test_map()) != 0) { + return ret; + } if ((ret = test_socket()) != 0) { return ret; } |