/* * 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 #include #include #include #include #include /* 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; }