summaryrefslogtreecommitdiffstats
path: root/util/src/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/src/string.c')
-rw-r--r--util/src/string.c822
1 files changed, 822 insertions, 0 deletions
diff --git a/util/src/string.c b/util/src/string.c
new file mode 100644
index 0000000..4a3f8f0
--- /dev/null
+++ b/util/src/string.c
@@ -0,0 +1,822 @@
+/*
+ * 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;
+}