blob: 4a3f8f01948bb430e56e2f0b25f8b7c400dbf684 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <axutil_string.h>
#include <stdlib.h>
#include <ctype.h>
#include <axutil_utils.h>
#include <axutil_utils_defines.h>
#include <stdarg.h> /* NULL */
struct axutil_string
{
axis2_char_t *buffer;
unsigned int length;
unsigned int ref_count;
axis2_bool_t owns_buffer;
};
AXIS2_EXTERN axutil_string_t *AXIS2_CALL
axutil_string_create(
const axutil_env_t *env,
const axis2_char_t *str)
{
axutil_string_t *string = NULL;
AXIS2_ENV_CHECK(env, NULL);
/* str can't be null */
if(!str)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_NULL_PARAM, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"NULL parameter was passed when a non NULL parameter was expected");
return NULL;
}
string = (axutil_string_t *)AXIS2_MALLOC(env->allocator, sizeof(axutil_string_t));
if(!string)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
return NULL;
}
/* set properties */
string->buffer = NULL;
string->ref_count = 1;
string->owns_buffer = AXIS2_TRUE;
string->length = axutil_strlen(str);
if(string->length < 0)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_NULL_PARAM, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"NULL parameter was passed when a non NULL parameter was expected");
axutil_string_free(string, env);
return NULL;
}
string->buffer = (axis2_char_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t)
* (string->length + 1));
if(!(string->buffer))
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
axutil_string_free(string, env);
return NULL;
}
memcpy(string->buffer, str, string->length + 1);
return string;
}
AXIS2_EXTERN axutil_string_t *AXIS2_CALL
axutil_string_create_assume_ownership(
const axutil_env_t *env,
axis2_char_t **str)
{
axutil_string_t *string = NULL;
AXIS2_ENV_CHECK(env, NULL);
/* str can't be null */
if(!str || !(*str))
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_NULL_PARAM, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"NULL parameter was passed when a non NULL parameter was expected");
return NULL;
}
string = (axutil_string_t *)AXIS2_MALLOC(env->allocator, sizeof(axutil_string_t));
if(!string)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
return NULL;
}
/* set properties */
string->buffer = *str;
string->length = axutil_strlen(*str);
string->ref_count = 1;
string->owns_buffer = AXIS2_TRUE;
if(string->length < 0)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_NULL_PARAM, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"NULL parameter was passed when a non NULL parameter was expected");
axutil_string_free(string, env);
return NULL;
}
return string;
}
AXIS2_EXTERN axutil_string_t *AXIS2_CALL
axutil_string_create_const(
const axutil_env_t *env,
axis2_char_t **str)
{
axutil_string_t *string = NULL;
AXIS2_ENV_CHECK(env, NULL);
/* str can't be null */
if(!str)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_NULL_PARAM, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"NULL parameter was passed when a non NULL parameter was expected");
return NULL;
}
string = (axutil_string_t *)AXIS2_MALLOC(env->allocator, sizeof(axutil_string_t));
if(!string)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
return NULL;
}
/* set properties */
string->buffer = *str;
string->length = axutil_strlen(*str);
string->ref_count = 1;
string->owns_buffer = AXIS2_FALSE;
if(string->length < 0)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_NULL_PARAM, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"NULL parameter was passed when a non NULL parameter was expected");
axutil_string_free(string, env);
return NULL;
}
return string;
}
AXIS2_EXTERN void AXIS2_CALL
axutil_string_free(
struct axutil_string *string,
const axutil_env_t *env)
{
if(!string)
{
return;
}
string->ref_count--;
if(string->ref_count > 0)
{
return;
}
if(string->owns_buffer && string->buffer)
{
AXIS2_FREE(env->allocator, string->buffer);
}
AXIS2_FREE(env->allocator, string);
return;
}
AXIS2_EXTERN axis2_bool_t AXIS2_CALL
axutil_string_equals(
const struct axutil_string *string,
const axutil_env_t * env,
const struct axutil_string *string1)
{
if(!string || !string1)
{
return AXIS2_FALSE;
}
return (string->buffer == string1->buffer);
}
AXIS2_EXTERN struct axutil_string *AXIS2_CALL
axutil_string_clone(
struct axutil_string *string,
const axutil_env_t *env)
{
if(!string)
{
return NULL;
}
string->ref_count++;
return string;
}
AXIS2_EXTERN const axis2_char_t *AXIS2_CALL
axutil_string_get_buffer(
const struct axutil_string *string,
const axutil_env_t *env)
{
if(!string)
{
return NULL;
}
return string->buffer;
}
AXIS2_EXTERN unsigned int AXIS2_CALL
axutil_string_get_length(
const struct axutil_string *string,
const axutil_env_t *env)
{
int error_return = -1;
if(!string)
{
return error_return;
}
return string->length;
}
/* END of string struct implementation */
/** this is used to cache lengths in axutil_strcat */
#define MAX_SAVED_LENGTHS 6
AXIS2_EXTERN void *AXIS2_CALL
axutil_strdup(
const axutil_env_t *env,
const void *ptr)
{
if(ptr)
{
int len = axutil_strlen(ptr);
axis2_char_t *str = (axis2_char_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t)
* (len + 1));
if(!str)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
return NULL;
}
memcpy(str, ptr, len + 1);
return (void *)str;
}
else
{
return NULL;
}
}
AXIS2_EXTERN void *AXIS2_CALL
axutil_strmemdup(
const void *ptr,
size_t n,
const axutil_env_t *env)
{
axis2_char_t *str;
AXIS2_PARAM_CHECK(env->error, ptr, NULL);
str = (axis2_char_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (n + 1));
if(!str)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
return NULL;
}
memcpy(str, ptr, n);
str[n] = '\0';
return (void *)str;
}
AXIS2_EXTERN void *AXIS2_CALL
axutil_memchr(
const void *ptr,
int c,
size_t n)
{
const axis2_char_t *cp;
for(cp = ptr; n > 0; n--, cp++)
{
if(*cp == c)
return (char *)cp; /* Casting away the const here */
}
return NULL;
}
AXIS2_EXTERN void *AXIS2_CALL
axutil_strndup(
const axutil_env_t *env,
const void *ptr,
int n)
{
const axis2_char_t *end;
axis2_char_t *str;
AXIS2_PARAM_CHECK(env->error, ptr, NULL);
end = axutil_memchr(ptr, '\0', n);
if(end)
n = (int)(end - (axis2_char_t *)ptr);
/* We are sure that the difference lies within the int range */
str = (axis2_char_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (n + 1));
if(!str)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
return NULL;
}
memcpy(str, ptr, n);
str[n] = '\0';
return (void *)str;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_strcat(
const axutil_env_t *env,
...)
{
axis2_char_t *cp, *argp, *str;
size_t saved_lengths[MAX_SAVED_LENGTHS];
int nargs = 0;
int str_len = 0;
/* Pass one --- find length of required string */
size_t len = 0;
va_list adummy;
va_start(adummy, env);
cp = va_arg(adummy, axis2_char_t *);
while(cp)
{
size_t cplen = strlen(cp);
if(nargs < MAX_SAVED_LENGTHS)
{
saved_lengths[nargs++] = cplen;
}
len += cplen;
cp = va_arg(adummy, axis2_char_t *);
}
va_end(adummy);
/* Allocate the required string */
str_len = (int)(sizeof(axis2_char_t) * (len + 1));
/* We are sure that the difference lies within the int range */
str = (axis2_char_t *) AXIS2_MALLOC(env->allocator, str_len);
if (!str)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
return NULL;
}
cp = str;
/* Pass two --- copy the argument strings into the result space */
va_start(adummy, env);
nargs = 0;
argp = va_arg(adummy, axis2_char_t *);
while (argp)
{
if (nargs < MAX_SAVED_LENGTHS)
{
len = saved_lengths[nargs++];
}
else
{
len = strlen(argp);
}
memcpy(cp, argp, len);
cp += len;
argp = va_arg(adummy, axis2_char_t *);
}
va_end(adummy);
/* Return the result string */
*cp = '\0';
return str;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_stracat(
const axutil_env_t *env,
const axis2_char_t *s1,
const axis2_char_t *s2)
{
axis2_char_t *ret = NULL;
int alloc_len = -1;
int len1 = 0;
int len2 = 0;
if(!s1 && !s2)
{
return NULL;
}
if(!s1)
{
return (axis2_char_t *)axutil_strdup(env, s2);
}
if(!s2)
{
return (axis2_char_t *)axutil_strdup(env, s1);
}
len1 = axutil_strlen(s1);
len2 = axutil_strlen(s2);
alloc_len = len1 + len2 + 1;
ret = (axis2_char_t *)AXIS2_MALLOC(env->allocator, alloc_len * sizeof(axis2_char_t));
memcpy(ret, s1, len1 * sizeof(axis2_char_t));
memcpy((ret + len1 * sizeof(axis2_char_t)), s2, len2 * sizeof(axis2_char_t));
ret[alloc_len * sizeof(axis2_char_t) - sizeof(axis2_char_t)] = '\0';
return ret;
}
AXIS2_EXTERN int AXIS2_CALL
axutil_strcmp(
const axis2_char_t *s1,
const axis2_char_t *s2)
{
if(s1 && s2)
{
return strcmp(s1, s2);
}
else
{
return -1;
}
}
AXIS2_EXTERN int AXIS2_CALL
axutil_strncmp(
const axis2_char_t *s1,
const axis2_char_t *s2,
int n)
{
if(s1 && s2)
{
return strncmp(s1, s2, n);
}
else
{
return -1;
}
}
AXIS2_EXTERN axis2_ssize_t AXIS2_CALL
axutil_strlen(
const axis2_char_t *s)
{
int error_return = -1;
if(s)
{
return (axis2_ssize_t)strlen(s);
/* We are sure that the difference lies within the axis2_ssize_t range */
}
return error_return;
}
AXIS2_EXTERN int AXIS2_CALL
axutil_strcasecmp(
const axis2_char_t *s1,
const axis2_char_t *s2)
{
while(*s1 != '\0' && *s2 != '\0')
{
if(*s1 >= 'A' && *s1 <= 'Z' && *s2 >= 'a' && *s2 <= 'z')
{
if(*s2 - *s1 - (char)32 != 0)
{
return 1;
}
}
else if(*s1 >= 'a' && *s1 <= 'z' && *s2 >= 'A' && *s2 <= 'Z')
{
if(*s1 - *s2 - 32 != 0)
{
return 1;
}
}
else if(*s1 - *s2 != 0)
{
return 1;
}
s1++;
s2++;
}
if(*s1 != *s2)
{
return 1;
}
return 0;
}
AXIS2_EXTERN int AXIS2_CALL
axutil_strncasecmp(
const axis2_char_t *s1,
const axis2_char_t *s2,
const int n)
{
axis2_char_t *str1 = (axis2_char_t *)s1, *str2 = (axis2_char_t *)s2;
int i = (int)n;
while(--i >= 0 && toupper((int)*str1) == toupper((int)*str2++))
{
if(toupper((int)*str1++) == '\0')
{
return (0);
}
}
return (i < 0 ? 0 : toupper((int)*str1) - toupper((int)*--str2));
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_strstr(
const axis2_char_t *haystack,
const axis2_char_t *needle)
{
return strstr(haystack, needle);
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_strchr(
const axis2_char_t *s,
axis2_char_t ch)
{
return (axis2_char_t *)strchr(s, ch);
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_rindex(
const axis2_char_t *_s,
axis2_char_t _ch)
{
int i, ilen = axutil_strlen(_s);
if(ilen < 1)
{
return NULL;
}
for(i = ilen - 1; i >= 0; i--)
{
if(_s[i] == _ch)
{
return (axis2_char_t *)(_s + i);
}
}
return NULL;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_replace(
const axutil_env_t *env,
axis2_char_t *str,
int s1,
int s2)
{
axis2_char_t *newstr = NULL;
axis2_char_t *index = NULL;
if(!str)
{
return NULL;
}
newstr = axutil_strdup(env, str);
index = strchr(newstr, s1);
while(index)
{
newstr[index - newstr] = (axis2_char_t)s2;
/* We are sure that the conversion is safe */
index = strchr(newstr, s1);
}
return newstr;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_strltrim(
const axutil_env_t *env,
const axis2_char_t *_s,
const axis2_char_t *_trim)
{
axis2_char_t *_p = NULL;
axis2_char_t *ret = NULL;
if(!_s)
{
return NULL;
}
_p = (axis2_char_t *)_s;
if(!_trim)
{
_trim = " \t\r\n";
}
while(*_p)
{
if(!strchr(_trim, *_p))
{
ret = (axis2_char_t *)axutil_strdup(env, _p);
break;
}
++_p;
}
return ret;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_strrtrim(
const axutil_env_t *env,
const axis2_char_t *_in,
const axis2_char_t *_trim)
{
axis2_char_t *__tail;
axis2_char_t *_s = NULL;
axis2_char_t *ret = NULL;
if(_in)
{
_s = axutil_strdup(env, _in);
}
if(!_s)
{
return NULL;
}
__tail = _s + axutil_strlen(_s);
if(!_trim)
{
_trim = " \t\n\r";
}
while(_s < __tail--)
{
if(!strchr(_trim, *__tail))
{
ret = _s;
break;
}
*__tail = 0;
}
if(!ret && _s)
{
AXIS2_FREE(env->allocator, _s);
}
return ret;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_strtrim(
const axutil_env_t *env,
const axis2_char_t *_s,
const axis2_char_t *_trim)
{
axis2_char_t *_p = NULL;
axis2_char_t *_q = NULL;
_p = axutil_strltrim(env, _s, _trim);
_q = axutil_strrtrim(env, _p, _trim);
if(_p)
{
AXIS2_FREE(env->allocator, _p);
}
return _q;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_string_replace(
axis2_char_t *str,
axis2_char_t old,
axis2_char_t new)
{
axis2_char_t *str_returns = str;
for(; *str != '\0'; str++)
{
if(*str == old)
{
*str = new;
}
}
return str_returns;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_string_substring_starting_at(
axis2_char_t *str,
int s)
{
int len;
int pos_to_shift;
len = (int)strlen(str);
/* We are sure that the difference lies within the int range */
pos_to_shift = len - s + 1;
if(len <= s)
{
return NULL;
}
memmove(str, str + s, pos_to_shift);
return str;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_string_substring_ending_at(
axis2_char_t *str,
int e)
{
axis2_char_t *ptr = NULL;
int length = 0;
length = (int)strlen(str);
/* We are sure that the difference lies within the int range */
ptr = str;
if(length <= e)
{
return NULL;
}
ptr += e;
*ptr = '\0';
return str;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_string_tolower(
axis2_char_t *str)
{
axis2_char_t *temp_str = NULL;
for(temp_str = str; *temp_str != '\0'; temp_str++)
{
*temp_str = (axis2_char_t)tolower((int)*temp_str);
/* We are sure that the conversion is safe */
}
return str;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_string_toupper(
axis2_char_t *str)
{
axis2_char_t *temp_str = NULL;
for(temp_str = str; *temp_str != '\0'; temp_str++)
{
*temp_str = (axis2_char_t)toupper((int)*temp_str);
/* We are sure that the conversion is safe */
}
return str;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_strcasestr(
const axis2_char_t *haystack,
const axis2_char_t *needle)
{
axis2_char_t start, current;
size_t len;
if(!haystack || !needle)
{
return NULL;
}
if((start = *needle++))
{
len = strlen(needle);
do
{
do
{
if(!(current = *haystack++))
{
return NULL;
}
}
while(toupper((int)current) != toupper((int)start));
}
while(axutil_strncasecmp(haystack, needle, (int)len));
/* We are sure that the difference lies within the int range */
haystack--;
}
return (axis2_char_t *)haystack;
}