/*
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <errno.h>
#include <ctype.h>
#include "xmalloc.h"
#include "rarray.h"
#include "rstring.h"
#include "error.h"
#include <regex.h>
#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
*
****************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1