lib/cds/sstr.c
1c24f8eb
 /* 
  * Copyright (C) 2005 iptelorg GmbH
  *
  * This file is part of ser, a free SIP server.
  *
  * ser 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
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser 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
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
1c24f8eb
  */
 
 #include <cds/sstr.h>
 #include <cds/memory.h>
72048db6
 #include <cds/dstring.h>
1c24f8eb
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
72048db6
 #include <cds/logger.h>
1c24f8eb
 
 /** returns 1 if the string is empty */
 int is_str_empty(const str_t *s)
 {
 	if (!s) return 1;
 	if ((!s->s) || (s->len < 1)) return 1;
 	return 0;
 }
 
 int str_cmp_zt(const str_t *a, const char *b)
 {
 	int i;
 	
 	if (!a) {
 		if (b) return 1;
 		else return 0;
 	}
 	
 	for (i = 0; (i < a->len) && (b[i]); i++) {
 		if (a->s[i] < b[i]) return -1;
 		if (a->s[i] > b[i]) return 1;
 	}
 	if (i < a->len) return 1;
 	return 0;
 }
 
 int str_prefix(const str_t *a, const str_t *b)
 {
 	int i;
 	if (!b) return 0;
 	if (!a) return -1;
 
 	if (b->len > a->len) return -1;
 	for (i = 0; i < b->len; i++) {
 		if (a->s[i] != b->s[i]) return -1;
 	}
 	return 0;
 }
 
 str_t zt2str(char *str)
 {
 	str_t s;
 
 	s.s = str;
 	if (str) s.len = strlen(str);
 	else s.len = 0;
 	return s;
 }
 
0a643c8f
 int str_dup_dbg(str_t* dst, const str_t* src, const char *file, int line)
 {
 	if (!dst) return -1;
 
 	dst->len = 0;
 	dst->s = NULL;
 	if (!src) return 0;
 	if ( (!src->s) || (src->len < 1)) return 0;
 
 		/* ERROR_LOG("can't allocate memory (%d bytes)\n", src->len); */
e63e60ee
 	DEBUG_LOG("str_dup called from %s:%d\n", file, line);
0a643c8f
 	dst->s = cds_malloc(src->len);
 	if (!dst->s) {
 		/* ERROR_LOG("can't allocate memory (%d bytes)\n", src->len); */
 		return -1;
 	}
 	memcpy(dst->s, src->s, src->len);
 	dst->len = src->len;
 	return 0;
 }
 
 int str_dup_impl(str_t* dst, const str_t* src)
1c24f8eb
 {
 	if (!dst) return -1;
 
 	dst->len = 0;
 	dst->s = NULL;
 	if (!src) return 0;
 	if ( (!src->s) || (src->len < 1)) return 0;
 
 	dst->s = cds_malloc(src->len);
c0ce5c29
 	if (!dst->s) {
 		/* ERROR_LOG("can't allocate memory (%d bytes)\n", src->len); */
 		return -1;
 	}
1c24f8eb
 	memcpy(dst->s, src->s, src->len);
 	dst->len = src->len;
 	return 0;
 }
 
 str_t *str_dup_new(const str_t* src)
 {
 	str_t *dst = cds_malloc(sizeof(str_t));
 	if (dst) str_dup(dst, src);
 	return dst;
 }
 
 int str_dup_zt(str_t* dst, const char* src)
 {
 	int len;
 	if (!dst) return -1;
 
 	dst->len = 0;
 	dst->s = NULL;
 	if (!src) return 0;
 	len = strlen(src);
 	if (len < 1) return 0;
 
 	dst->s = cds_malloc(len);
 	if (!dst->s) return -1;
 	memcpy(dst->s, src, len);
 	dst->len = len;
 	return 0;
 }
 
 char *zt_strdup(const char* src)
 {
 	int len;
 	char *dst;
 
 	len = strlen(src);
 	if (len < 0) return NULL;
 
 	dst = cds_malloc(len + 1);
 	if (dst) memcpy(dst, src, len + 1);
 	return dst;
 }
 
 int str_nocase_equals(const str_t *a, const str_t *b)
 {
 	int i;
 	
 	if (!a) {
 		if (!b) return 0;
 		else return (b->len == 0) ? 0 : 1;
 	}
 	if (!b) return (a->len == 0) ? 0 : 1;
 	if (a->len != b->len) return 1;
 	
 	for (i = 0; i < a->len; i++) 
 		if (tolower(a->s[i]) != tolower(b->s[i])) return 1;
 	return 0;
 }
 
 int str_case_equals(const str_t *a, const str_t *b)
 {
 	int i;
 	
 	if (!a) {
 		if (!b) return 0;
 		else return (b->len == 0) ? 0 : 1;
 	}
 	if (!b) return (a->len == 0) ? 0 : 1;
 	if (a->len != b->len) return 1;
 	
 	for (i = 0; i < a->len; i++) 
 		if (a->s[i] != b->s[i]) return 1;
 	return 0;
 }
 
abab9ea7
 /* void str_free_content(str_t *s)
1c24f8eb
 {
 	if (!s) return;
 	if ((s->len > 0) && (s->s)) cds_free(s->s);
 	s->len = 0;
 	s->s = NULL;
abab9ea7
 } 
1c24f8eb
 
 void str_free(str_t *s)
 {
 	if (s) {
 		str_free_content(s);
 		cds_free(s);
 	}
3bf618cc
 }
1c24f8eb
 
 void str_clear(str_t *s)
 {
 	if (s) {
 		s->s = NULL;
 		s->len = 0;
 	}
3bf618cc
 } */
1c24f8eb
 
54814b09
 char *str_strchr(const str_t *s, char c)
acdde225
 {
 	if (s) {
 		int i;
 		for (i = 0; i < s->len; i++)
 			if (s->s[i] == c) return s->s + i;
 	}
 	return NULL;
 }
 
2c82fd67
 char *str_str(const str_t *s, const str_t *search_for)
 {
 	int i, j;
 	/* FIXME: reimplement using better algorithm */
 
 	if (is_str_empty(search_for)) return s->s;
 	if (is_str_empty(s)) return NULL;
 	
 	if (search_for->len > s->len) return NULL;
 
 	j = 0;
 	i = 0;
 	while (i < s->len) {
 		if (s->s[i] == search_for->s[j]) {
 			j++;
 			i++;
72048db6
 			if (j == search_for->len) return s->s + i - j;
2c82fd67
 		}
 		else {
 			i = i - j + 1;
 			j = 0;
 		}
 	}
 	return NULL;
 }
 
01e5f9fc
 /* creates new string as concatenation of a and b */
 int str_concat(str_t *dst, str_t *a, str_t *b)
 {
 	int al;
 	int bl;
 	
 	if (!dst) return -1;
 	
 	al = str_len(a);
 	bl = str_len(b);
 	
 	dst->len = al + bl;
 	if (dst->len > 0) {
 		dst->s = (char *)cds_malloc(dst->len);
 		if (!dst->s) {
 			dst->len = 0;
 			return -1;
 		}
 	}
 	else {
 		dst->s = NULL;
 		dst->len = 0;
 		return 0;
 	}
 	
 	if (al) memcpy(dst->s, a->s, al);
 	if (bl) memcpy(dst->s + al, b->s, bl);
 	
 	return 0;
 }
72048db6
 
 int replace_str(const str_t *src, str_t *dst, const str_t *sample, const str_t *value)
 {
 	str_t s;
 	char *c;
 	dstring_t str;
 	int res, len;
 	
 	/* if (!dst) return -1;
 	 if (!src) {
 		str_clear(dst);
 		return -1; 
 	} */
 
 	if (is_str_empty(sample)) {
 		str_clear(dst);
 		return -1;
 	}
 
 	if (is_str_empty(src)) {
 		str_clear(dst);
 		return 0;
 	}
 	
 	s = *src;
 	dstr_init(&str, src->len + 32);
 	do {
 		c = str_str(&s, sample);
 		if (c) {
 			len = c - s.s;
 			dstr_append(&str, s.s, len);
 			dstr_append_str(&str, value);
 			s.len = s.len - len - sample->len;
 			s.s = c + sample->len;
 			if (s.len <= 0) break;
 		}
 		else dstr_append_str(&str, &s);
 	} while (c);
 	
 	res = dstr_get_str(&str, dst);
 	dstr_destroy(&str);
 	return res;
 }