string: strlist, parse_word_list
authorMarko Kreen <markokr@gmail.com>
Wed, 13 May 2009 11:51:43 +0000 (14:51 +0300)
committerMarko Kreen <markokr@gmail.com>
Mon, 1 Jun 2009 07:08:41 +0000 (10:08 +0300)
usual/string.c [new file with mode: 0644]
usual/string.h

diff --git a/usual/string.c b/usual/string.c
new file mode 100644 (file)
index 0000000..9270dd1
--- /dev/null
@@ -0,0 +1,156 @@
+#include <usual/string.h>
+
+#include <usual/alloc.h>
+#include <usual/mbuf.h>
+#include <usual/statlist.h>
+
+#include <errno.h>
+#include <ctype.h>
+
+/*
+ * Dynamic list of strings.
+ */
+
+struct StrList {
+       struct StatList list;
+};
+
+struct StrItem {
+       struct List node;
+       const char *str;
+};
+
+bool strlist_empty(struct StrList *slist)
+{
+       return statlist_empty(&slist->list);
+}
+
+bool strlist_append(struct StrList *slist, const char *str)
+{
+       struct StrItem *item = calloc(1, sizeof(*item));
+       if (!item)
+               return false;
+       list_init(&item->node);
+       item->str = strdup(str);
+       if (!item->str) {
+               free(item);
+               return false;
+       }
+       statlist_append(&slist->list, &item->node);
+       return true;
+}
+
+const char *strlist_pop(struct StrList *slist)
+{
+       struct StrItem *item;
+       struct List *el;
+       const char *str;
+
+       el = statlist_pop(&slist->list);
+       if (!el)
+               return NULL;
+
+       item = container_of(el, struct StrItem, node);
+       str = item->str;
+       free(item);
+       return str;
+}
+
+struct StrList *strlist_new(void)
+{
+       struct StrList *slist = calloc(1, sizeof(*slist));
+       if (!slist)
+               return NULL;
+       statlist_init(&slist->list, "strlist");
+       return slist;
+}
+
+void strlist_free(struct StrList *slist)
+{
+       const char *s;
+       if (!slist)
+               return;
+       while (1) {
+               s = strlist_pop(slist);
+               if (!s)
+                       break;
+               free(s);
+       }
+       free(slist);
+}
+
+bool strlist_foreach(struct StrList *slist, str_cb func, void *arg)
+{
+       struct List *el;
+       struct StrItem *item;
+       statlist_for_each(el, &slist->list) {
+               item = container_of(el, struct StrItem, node);
+               if (!func(arg, item->str))
+                       return false;
+       }
+       return true;
+}
+
+/*
+ * Parse comma separated words.
+ */
+
+static inline const char *skip_ws(const char *p)
+{
+       while (*p && isspace(*p))
+               p++;
+       return p;
+}
+
+
+bool parse_word_list(const char *s, str_cb cb_func, void *cb_arg)
+{
+       struct MBuf buf;
+       const char *p = s;
+       const char *start, *end;
+
+       mbuf_init_dynamic(&buf);
+       while (*p) {
+               /* parse word */
+               p = skip_ws(p);
+               start = p;
+               while (*p && *p != ',')
+                       p++;
+               end = p;
+               while (end > start && isspace(*(end - 1)))
+                       end--;
+
+               /* parse comma */
+               if (*p) {
+                       if (*p == ',') {
+                               p++;
+                       } else {
+                               goto failed_syntax;
+                       }
+               }
+
+               /* extract string */
+               if (start == end)
+                       goto failed_syntax;
+               if (!mbuf_write(&buf, start, end - start))
+                       goto failed;
+               if (!mbuf_write_byte(&buf, 0))
+                       goto failed;
+
+               /* launch callback */
+               if (!cb_func(cb_arg, (const char *)buf.data))
+                       goto failed;
+
+               /* reset */
+               mbuf_rewind_writer(&buf);
+       }
+       mbuf_free(&buf);
+       return true;
+
+failed_syntax:
+       errno = EINVAL;
+failed:
+       mbuf_free(&buf);
+       return false;
+}
+
index 077856f62d353ce9e684747954a37b9ac7b4d48c..4d7a5a83bd43c872ce41e618e857f10dd6522815 100644 (file)
@@ -57,5 +57,18 @@ static inline size_t strlcat(char *dst, const char *src, size_t n)
 
 #endif /* !HAVE_STRLCAT */
 
+typedef bool (*str_cb)(void *arg, const char *s);
+
+struct StrList;
+struct StrList *strlist_new(void);
+void strlist_free(struct StrList *slist);
+bool strlist_empty(struct StrList *slist);
+bool strlist_append(struct StrList *slist, const char *str);
+bool strlist_foreach(struct StrList *slist, str_cb cb_func, void *cb_arg);
+const char *strlist_pop(struct StrList *slist);
+
+bool parse_word_list(const char *s, str_cb cb_func, void *cb_arg);
+
+
 #endif