diff --git a/src/lib-sieve/sieve-stringlist.c b/src/lib-sieve/sieve-stringlist.c index 51d9fc4fea8d4e5ccf19ac24afbac1a5eb13a160..cbbe5adf3763e7391d98160da00f010a55e1b16c 100644 --- a/src/lib-sieve/sieve-stringlist.c +++ b/src/lib-sieve/sieve-stringlist.c @@ -49,9 +49,11 @@ int sieve_stringlist_get_length 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 ); } @@ -141,3 +143,133 @@ static int sieve_single_stringlist_get_length return ( strlist->count_empty || str_len(strlist->value) > 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; + unsigned int 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; + } + + 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); +} diff --git a/src/lib-sieve/sieve-stringlist.h b/src/lib-sieve/sieve-stringlist.h index da9e355fb6d25680031171935c8287ad5cb84524..eb9dbe33fcab2ee3e1c089fb0d4078163822279f 100644 --- a/src/lib-sieve/sieve-stringlist.h +++ b/src/lib-sieve/sieve-stringlist.h @@ -66,4 +66,12 @@ struct sieve_stringlist *sieve_single_stringlist_create struct sieve_stringlist *sieve_single_stringlist_create_cstr (const struct sieve_runtime_env *renv, const char *cstr, bool count_empty); +/* + * Index Stringlist + */ + +struct sieve_stringlist *sieve_index_stringlist_create + (const struct sieve_runtime_env *renv, struct sieve_stringlist *source, + int index); + #endif /* __SIEVE_STRINGLIST_H */