summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--include/libast/linked_list.h1
-rw-r--r--include/libast/map_if.h8
-rw-r--r--include/libast/str.h6
-rw-r--r--libast.spec2
-rw-r--r--src/linked_list.c271
-rw-r--r--src/str.c75
-rw-r--r--test/test.c281
8 files changed, 627 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 8a13bc4..2cf2972 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)
{
diff --git a/src/str.c b/src/str.c
index 4a3688c..0f2952f 100644
--- a/src/str.c
+++ b/src/str.c
@@ -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;
}