/* elmo - ELectronic Mail Operator Copyright (C) 2002, 2003, 2004 rzyjontko This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ---------------------------------------------------------------------- Perform operations on strings arrays. */ /**************************************************************************** * IMPLEMENTATION HEADERS ****************************************************************************/ #include #include #include #include #include #include #include #include "xmalloc.h" #include "rarray.h" #include "rstring.h" #include "error.h" #include #include "memchunk.h" #include "str.h" /**************************************************************************** * IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID) ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE DATA ****************************************************************************/ static regmatch_t matches[1]; /**************************************************************************** * INTERFACE DATA ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES ****************************************************************************/ static char *search_line_end (char *txt, size_t line_len); /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTIONS ****************************************************************************/ static char * search_line_end (char *txt, size_t line_len) { char *last_space = NULL; char *seek; for (seek = txt; *seek && seek - txt < line_len; seek++){ switch (*seek){ case ' ': case '\t': last_space = seek; break; case '\n': return seek; } } if (*seek == '\0'){ return NULL; } if (last_space){ return last_space; } return seek; } /**************************************************************************** * INTERFACE FUNCTIONS ****************************************************************************/ rstring_t * rstring_create_size (int size) { return (rstring_t *) rarray_create_size (size); } rstring_t * rstring_create (void) { return (rstring_t *) rarray_create (); } void rstring_delete (rstring_t *ptr) { if (ptr->allocated_all){ rstring_free_strings (ptr); } else if (ptr->allocated_first && ptr->count > 0){ xfree (ptr->array[0]); } rarray_destroy ((rarray_t *) ptr); } void rstring_add (rstring_t *ptr, char *txt) { rarray_add ((rarray_t *) ptr, txt); } void rstring_sprintf (rstring_t *ptr, const char *fmt, ...) { va_list ap; str_t *str = str_create (); va_start (ap, fmt); str_vsprintf (str, fmt, ap); va_end (ap); rstring_add (ptr, str_finished (str)); } void rstring_remove (rstring_t *ptr, unsigned index) { rarray_remove ((rarray_t *) ptr, index); } void rstring_shrink (rstring_t *ptr) { rarray_shrink ((rarray_t *) ptr); } rstring_t * rstring_split (char *txt, const char *delimiter) { rstring_t *result; char *seek = txt; size_t len = strlen (delimiter); result = rstring_create (); while (seek && *seek){ rstring_add (result, seek); seek = strstr (seek, delimiter); if (seek){ *seek = '\0'; seek += len; } } return result; } rstring_t * rstring_split_re (char *txt, const char *regexp) { rstring_t *result; regex_t compiled; int ret; char *seek = txt; ret = regcomp (&compiled, regexp, REG_ICASE | REG_EXTENDED); if (ret){ result = NULL; error_regex (ret, &compiled, regexp); regfree (&compiled); return NULL; } result = rstring_create (); while (seek && *seek){ rstring_add (result, seek); ret = regexec (&compiled, seek, 1, matches, 0); if (ret && ret != REG_NOMATCH){ error_regex (ret, &compiled, regexp); rstring_delete (result); regfree (&compiled); return NULL; } if (ret == REG_NOMATCH) break; *(seek + matches[0].rm_so) = '\0'; seek += matches[0].rm_eo; } regfree (&compiled); return result; } rstring_t * rstring_split_lines (char *txt, size_t line_len) { rstring_t *result; char *seek = txt; if (txt == NULL) return NULL; result = rstring_create (); while (seek && *seek){ rstring_add (result, seek); seek = search_line_end (seek, line_len); if (seek){ *seek = '\0'; seek++; } } return result; } rstring_t * rstring_join (rstring_t *x, rstring_t *y) { return (rstring_t *) rarray_join ((rarray_t *) x, (rarray_t *) y); } rstring_t * rstring_copy (rstring_t *x) { rstring_t *result = rstring_create_size (x->count + 1); char **txt; for (txt = x->array; *txt; txt++){ rstring_add (result, xstrdup (*txt)); } result->allocated_all = 1; return result; } void rstring_free_firstn_strings (rstring_t *x, int n) { char **str; for (str = x->array; n && *str; str++){ xfree (*str); n--; } } void rstring_free_strings (rstring_t *x) { char **str; for (str = x->array; *str; str++) xfree (*str); } void rstring_dump (memchunk_t *memchunk, rstring_t *x) { int i; int zero = 0; if (x == NULL){ memchunk_intdump (memchunk, zero); return; } memchunk_intdump (memchunk, x->count); for (i = 0; i < x->count; i++) memchunk_strdump (memchunk, x->array[i]); } rstring_t * rstring_read (memchunk_t *memchunk) { int i; int size = memchunk_intget (memchunk); rstring_t *result; if (size == 0) return NULL; result = rstring_create_size (size + 1); for (i = 0; i < size; i++){ rstring_add (result, memchunk_strget (memchunk)); } result->allocated_all = 1; return result; } char * rstring_flatten (rstring_t *ptr, const char *delim) { int i; str_t *str = str_create (); for (i = 0; i < ptr->count - 1; i++){ str_sprintf (str, "%s%s", ptr->array[i], delim); } if (ptr->count > 0) str_sprintf (str, "%s", ptr->array[ptr->count - 1]); return str_finished (str); } /**************************************************************************** * INTERFACE CLASS BODIES ****************************************************************************/ /**************************************************************************** * * END MODULE rstring.c * ****************************************************************************/