summaryrefslogtreecommitdiffstats
path: root/pigeonhole/src/lib-sieve/sieve-stringlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'pigeonhole/src/lib-sieve/sieve-stringlist.c')
-rw-r--r--pigeonhole/src/lib-sieve/sieve-stringlist.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/sieve-stringlist.c b/pigeonhole/src/lib-sieve/sieve-stringlist.c
new file mode 100644
index 0000000..17b7d5c
--- /dev/null
+++ b/pigeonhole/src/lib-sieve/sieve-stringlist.c
@@ -0,0 +1,276 @@
+/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+#include "array.h"
+#include "str.h"
+
+#include "sieve-common.h"
+#include "sieve-stringlist.h"
+
+/*
+ * Default implementation
+ */
+
+int sieve_stringlist_read_all
+(struct sieve_stringlist *strlist, pool_t pool,
+ const char * const **list_r)
+{
+ if ( strlist->read_all == NULL ) {
+ ARRAY(const char *) items;
+ string_t *item;
+ int ret;
+
+ sieve_stringlist_reset(strlist);
+
+ p_array_init(&items, pool, 4);
+
+ item = NULL;
+ while ( (ret=sieve_stringlist_next_item(strlist, &item)) > 0 ) {
+ const char *stritem = p_strdup(pool, str_c(item));
+
+ array_append(&items, &stritem, 1);
+ }
+
+ (void)array_append_space(&items);
+ *list_r = array_idx(&items, 0);
+
+ return ( ret < 0 ? -1 : 1 );
+ }
+
+ return strlist->read_all(strlist, pool, list_r);
+}
+
+int sieve_stringlist_get_length
+(struct sieve_stringlist *strlist)
+{
+ if ( strlist->get_length == NULL ) {
+ string_t *item;
+ int count = 0;
+ int ret;
+
+ sieve_stringlist_reset(strlist);
+ while ( (ret=sieve_stringlist_next_item(strlist, &item)) > 0 ) {
+ count++;
+ }
+ sieve_stringlist_reset(strlist);
+
+ return ( ret < 0 ? -1 : count );
+ }
+
+ return strlist->get_length(strlist);
+}
+
+/*
+ * Single Stringlist
+ */
+
+/* Object */
+
+static int sieve_single_stringlist_next_item
+ (struct sieve_stringlist *_strlist, string_t **str_r);
+static void sieve_single_stringlist_reset
+ (struct sieve_stringlist *_strlist);
+static int sieve_single_stringlist_get_length
+ (struct sieve_stringlist *_strlist);
+
+struct sieve_single_stringlist {
+ struct sieve_stringlist strlist;
+
+ string_t *value;
+
+ bool end:1;
+ bool count_empty:1;
+};
+
+struct sieve_stringlist *sieve_single_stringlist_create
+(const struct sieve_runtime_env *renv, string_t *str, bool count_empty)
+{
+ struct sieve_single_stringlist *strlist;
+
+ strlist = t_new(struct sieve_single_stringlist, 1);
+ strlist->strlist.runenv = renv;
+ strlist->strlist.exec_status = SIEVE_EXEC_OK;
+ strlist->strlist.next_item = sieve_single_stringlist_next_item;
+ strlist->strlist.reset = sieve_single_stringlist_reset;
+ strlist->strlist.get_length = sieve_single_stringlist_get_length;
+ strlist->count_empty = count_empty;
+ strlist->value = str;
+
+ return &strlist->strlist;
+}
+
+struct sieve_stringlist *sieve_single_stringlist_create_cstr
+(const struct sieve_runtime_env *renv, const char *cstr, bool count_empty)
+{
+ string_t *str = t_str_new_const(cstr, strlen(cstr));
+
+ return sieve_single_stringlist_create(renv, str, count_empty);
+}
+
+/* Implementation */
+
+static int sieve_single_stringlist_next_item
+(struct sieve_stringlist *_strlist, string_t **str_r)
+{
+ struct sieve_single_stringlist *strlist =
+ (struct sieve_single_stringlist *)_strlist;
+
+ if ( strlist->end ) {
+ *str_r = NULL;
+ return 0;
+ }
+
+ *str_r = strlist->value;
+ strlist->end = TRUE;
+ return 1;
+}
+
+static void sieve_single_stringlist_reset
+(struct sieve_stringlist *_strlist)
+{
+ struct sieve_single_stringlist *strlist =
+ (struct sieve_single_stringlist *)_strlist;
+
+ strlist->end = FALSE;
+}
+
+static int sieve_single_stringlist_get_length
+(struct sieve_stringlist *_strlist)
+{
+ struct sieve_single_stringlist *strlist =
+ (struct sieve_single_stringlist *)_strlist;
+
+ return ( strlist->count_empty || str_len(strlist->value) > 0 ? 1 : 0 );
+}
+
+/*
+ * Index Stringlist
+ */
+
+/* Object */
+
+static int sieve_index_stringlist_next_item
+ (struct sieve_stringlist *_strlist, string_t **str_r);
+static void sieve_index_stringlist_reset
+ (struct sieve_stringlist *_strlist);
+static int sieve_index_stringlist_get_length
+ (struct sieve_stringlist *_strlist);
+static void sieve_index_stringlist_set_trace
+ (struct sieve_stringlist *strlist, bool trace);
+
+struct sieve_index_stringlist {
+ struct sieve_stringlist strlist;
+
+ struct sieve_stringlist *source;
+
+ int index;
+ bool end:1;
+};
+
+struct sieve_stringlist *sieve_index_stringlist_create
+(const struct sieve_runtime_env *renv, struct sieve_stringlist *source,
+ int index)
+{
+ struct sieve_index_stringlist *strlist;
+
+ strlist = t_new(struct sieve_index_stringlist, 1);
+ strlist->strlist.runenv = renv;
+ strlist->strlist.exec_status = SIEVE_EXEC_OK;
+ strlist->strlist.next_item = sieve_index_stringlist_next_item;
+ strlist->strlist.reset = sieve_index_stringlist_reset;
+ strlist->strlist.get_length = sieve_index_stringlist_get_length;
+ strlist->strlist.set_trace = sieve_index_stringlist_set_trace;
+ strlist->source = source;
+ strlist->index = index;
+
+ return &strlist->strlist;
+}
+
+/* Implementation */
+
+static int sieve_index_stringlist_next_item
+(struct sieve_stringlist *_strlist, string_t **str_r)
+{
+ struct sieve_index_stringlist *strlist =
+ (struct sieve_index_stringlist *)_strlist;
+ int index, ret;
+
+ if ( strlist->end ) {
+ *str_r = NULL;
+ return 0;
+ }
+
+ if ( strlist->index < 0 ) {
+ int len = sieve_stringlist_get_length(strlist->source);
+ if (len < 0) {
+ _strlist->exec_status = strlist->source->exec_status;
+ return -1;
+ }
+
+ if (len < -strlist->index) {
+ *str_r = NULL;
+ strlist->end = TRUE;
+ return 0;
+ }
+ index = len + 1 + strlist->index;
+ } else {
+ index = strlist->index;
+ }
+
+ i_assert(index > 0);
+ while ( index > 0 ) {
+ if ( (ret=sieve_stringlist_next_item(strlist->source, str_r)) <= 0 ) {
+ if (ret < 0)
+ _strlist->exec_status = strlist->source->exec_status;
+ return ret;
+ }
+
+ index--;
+ }
+
+ strlist->end = TRUE;
+ return 1;
+}
+
+static void sieve_index_stringlist_reset
+(struct sieve_stringlist *_strlist)
+{
+ struct sieve_index_stringlist *strlist =
+ (struct sieve_index_stringlist *)_strlist;
+
+ sieve_stringlist_reset(strlist->source);
+ strlist->end = FALSE;
+}
+
+static int sieve_index_stringlist_get_length
+(struct sieve_stringlist *_strlist)
+{
+ struct sieve_index_stringlist *strlist =
+ (struct sieve_index_stringlist *)_strlist;
+ int len;
+
+ len = sieve_stringlist_get_length(strlist->source);
+ if (len < 0) {
+ _strlist->exec_status = strlist->source->exec_status;
+ return -1;
+ }
+
+ if ( strlist->index < 0 ) {
+ if ( -strlist->index >= len )
+ return 0;
+ } else if ( strlist->index >= len ) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void sieve_index_stringlist_set_trace
+(struct sieve_stringlist *_strlist, bool trace)
+{
+ struct sieve_index_stringlist *strlist =
+ (struct sieve_index_stringlist *)_strlist;
+
+ sieve_stringlist_set_trace(strlist->source, trace);
+}