/***************************************
This is part of frox: A simple transparent FTP proxy
Copyright (C) 2000 James Hollingshead
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; either version 2 of the License, or
(at your option) any later version.
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
sstr.c
***************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <ctype.h>
#include "sstr.h"
#include "sstr_private.h"
static int sstr_cat_common(sstr * dest, const char *src, int len);
void (*on_error) (void) = NULL;
void sstr_setopts(void (*func) (void), int flags)
{
on_error = func;
}
/* ------------------------------------------------------------- **
** mlen=maximum no. of chars to hold. mlen=0 gives a dynamically
** growing string.
**
** NB. We malloc one extra byte to give space for a NUL termination,
** but we do not use one internally. However this allows us to NUL
** terminate our internal buffer before calling eg. atoi() on it, or
** returning a pointer to it.
** ------------------------------------------------------------- */
sstr *sstr_init(int mlen)
{
sstr *ret;
ret = malloc(sizeof(sstr));
if(ret == NULL) {
if(on_error)
on_error();
return (NULL);
}
if(mlen > 0) {
ret->maxlen = mlen;
ret->growable = 0;
} else {
ret->growable = 1;
ret->maxlen = 50;
}
ret->buf = malloc(ret->maxlen + 1);
if(ret->buf == NULL) {
free(ret);
if(on_error)
on_error();
return (NULL);
}
ret->len = 0;
return ret;
}
void sstr_free(sstr * p)
{
free(p->buf);
free(p);
}
void sstr_empty(sstr * p)
{
p->len = 0;
sstr_alloc_space(p, 0);
}
int sstr_len(const sstr * p)
{
return (p->len);
}
int sstr_cpy2(sstr * dest, const char *src)
{
dest->len = 0;
if(!src)
return (0);
return sstr_cat_common(dest, src, strlen(src));
}
int sstr_ncpy2(sstr * dest, const char *src, int len)
{
dest->len = 0;
return sstr_cat_common(dest, src, len);
}
int sstr_ncat2(sstr * dest, const char *src, int len)
{
return sstr_cat_common(dest, src, len);
}
int sstr_cat(sstr * dest, const sstr * src)
{
if(!src)
return (0);
return sstr_cat_common(dest, src->buf, src->len);
}
int sstr_ncat(sstr * dest, const sstr * src, int len)
{
if(!src)
return 0;
if(len > src->len)
len = src->len;
return sstr_cat_common(dest, src->buf, len);
}
int sstr_cpy(sstr * dest, const sstr * src)
{
dest->len = 0;
if(!src)
return (0);
return sstr_cat_common(dest, src->buf, src->len);
}
const char *sstr_buf(const sstr * p)
{
p->buf[p->len] = 0;
return p->buf;
}
sstr *sstr_dup(const sstr * buf)
{
sstr *ret;
ret = sstr_init(0);
sstr_cpy(ret, buf);
return (ret);
}
sstr *sstr_dup2(const char *buf)
{
sstr *ret;
ret = sstr_init(0);
sstr_cpy2(ret, buf);
return (ret);
}
int sstr_casecmp2(const sstr * s1, const char *s2)
{
if(!s2)
return (-1);
return (strcasecmp(sstr_buf(s1), s2));
}
int sstr_ncasecmp2(const sstr * s1, const char *s2, int len)
{
if(!s2)
return (-1);
return (strncasecmp(sstr_buf(s1), s2, len));
}
int sstr_cmp(const sstr * s1, const sstr * s2)
{
return (strcmp(sstr_buf(s1), sstr_buf(s2)));
}
int sstr_cmp2(const sstr * s1, const char *s2)
{
if(!s2)
return (-1);
return (strcmp(sstr_buf(s1), s2));
}
int sstr_atoi(const sstr * p)
{
return (atoi(sstr_buf(p)));
}
int sstr_chr(const sstr * p, int c)
{
int i;
if(c > 127)
c -= 256;
for(i = 0; i < p->len; i++)
if(p->buf[i] == c)
return (i);
return (-1);
}
int sstr_pbrk2(const sstr * p, const char *accept)
{
int i;
for(i = 0; i < p->len; i++)
if(strchr(accept, p->buf[i]))
return (i);
return (-1);
}
void sstr_strip(sstr * p, const char *strip)
{
int i;
for(i = 0; i < p->len && strchr(strip, p->buf[i]); i++);
sstr_split(p, NULL, 0, i);
}
int sstr_token(sstr * in, sstr * tok, const char *delim, int flags)
{
int sep, quote, i;
if(in->len == 0)
return (-1);
sstr_strip(in, delim);
if((flags & SSTR_QTOK) && (*in->buf == '"' || *in->buf == '\'')) {
quote = *in->buf;
for(i = 1; i < in->len && in->buf[i] != quote; i++);
if(i == in->len)
return (-1);
sstr_split(in, tok, 1, i - 1);
sstr_split(in, NULL, 0, 2); /* Remove quotes */
} else {
if((i = strcspn(sstr_buf(in), delim)) >= in->len)
return (-1);
sstr_split(in, tok, 0, i);
}
sep = *in->buf;
sstr_strip(in, delim);
return (sep);
}
int sstr_getchar(const sstr * p, int i)
{
if(i >= p->len || i < 0)
return (-1);
return (p->buf[i]);
}
int sstr_setchar(const sstr * p, int i, int c)
{
if(i >= p->len || i < 0)
return (-1);
p->buf[i] = c;
return (0);
}
int sstr_split(sstr * in, sstr * out, int start, int cnt)
{
sstr *tmp;
if(start + cnt > in->len || start < 0 || cnt < 0)
return (-1);
if(out)
sstr_empty(out);
if(!cnt)
return (0);
if(out)
sstr_cat_common(out, in->buf + start, cnt);
tmp = sstr_init(0);
sstr_cat_common(tmp, in->buf, start);
sstr_cat_common(tmp, in->buf + start + cnt, in->len - start - cnt);
sstr_cpy(in, tmp);
sstr_free(tmp);
return (0);
}
int sstr_makeprintable(sstr * p, int c)
{
int i, j = 0;
for(i = 0; i < p->len; i++) {
if(!isprint(p->buf[i])) {
p->buf[i] = c;
j++;
}
}
return (j);
}
/**************************************
* Memory management stuff. Be careful.
**************************************/
static int sstr_cat_common(sstr * dest, const char *src, int len)
{
int needed_bytes = dest->len + len;
if(src == NULL || len == 0)
return (0);
if(len < 0)
return (-1);
if(dest->growable)
sstr_alloc_space(dest, needed_bytes);
if(dest->maxlen < needed_bytes)
return -1;
memcpy(dest->buf + dest->len, src, len);
dest->len += len;
return (0);
}
/*Ensure we have enough space for len bytes in p. This involves
*allocating len+1 to allow space for null termination when needed. */
int sstr_alloc_space(sstr * p, int len)
{
char *tmp;
len++;
if(!p->growable && p->maxlen < len)
return -1;
if(!p->growable)
return 0;
if(p->maxlen >= len && p->maxlen - len < 50)
return 0;
tmp = realloc(p->buf, len + 25);
if(!tmp) {
if(on_error)
on_error();
return -1;
}
p->buf = tmp;
p->maxlen = len + 25;
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1