diff options
Diffstat (limited to 'util/src/properties.c')
-rw-r--r-- | util/src/properties.c | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/util/src/properties.c b/util/src/properties.c new file mode 100644 index 0000000..265765e --- /dev/null +++ b/util/src/properties.c @@ -0,0 +1,363 @@ +/* + * 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_properties.h> +#include <axutil_string.h> +#include <axutil_utils.h> + +#define MAX_SIZE 1024 +#define MAX_ALLOC (MAX_SIZE * 64) + +axis2_char_t * +axutil_properties_read( + FILE *input, + const axutil_env_t *env); + +axis2_char_t * +axutil_properties_read_next( + axis2_char_t *cur); + +axis2_char_t * +axutil_properties_trunk_and_dup( + axis2_char_t *start, + axis2_char_t *end, + const axutil_env_t *env); + +struct axutil_properties +{ + axutil_hash_t *prop_hash; +}; + +AXIS2_EXTERN axutil_properties_t *AXIS2_CALL +axutil_properties_create( + const axutil_env_t *env) +{ + axutil_properties_t *properties = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + properties = (axutil_properties_t *)AXIS2_MALLOC(env->allocator, sizeof(axutil_properties_t)); + + if(!properties) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Not enough memory"); + return NULL; + } + properties->prop_hash = axutil_hash_make(env); + + return properties; +} + +AXIS2_EXTERN void AXIS2_CALL +axutil_properties_free( + axutil_properties_t *properties, + const axutil_env_t *env) +{ + axis2_char_t *key = NULL; + axis2_char_t *value = NULL; + axutil_hash_index_t *hi = NULL; + + if(properties->prop_hash) + { + for(hi = axutil_hash_first(properties->prop_hash, env); hi; hi = axutil_hash_next(env, hi)) + { + axutil_hash_this(hi, (void *)&key, NULL, (void *)&value); + if(key) + { + AXIS2_FREE(env->allocator, key); + } + if(value) + { + AXIS2_FREE(env->allocator, value); + } + } + axutil_hash_free(properties->prop_hash, env); + } + + if(properties) + { + AXIS2_FREE(env->allocator, properties); + } + return; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axutil_properties_get_property( + axutil_properties_t *properties, + const axutil_env_t *env, + axis2_char_t *key) +{ + AXIS2_PARAM_CHECK(env->error, key, NULL); + + return axutil_hash_get(properties->prop_hash, key, AXIS2_HASH_KEY_STRING); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_properties_set_property( + axutil_properties_t *properties, + const axutil_env_t *env, + axis2_char_t *key, + axis2_char_t *value) +{ + axis2_char_t *old = NULL; + AXIS2_PARAM_CHECK(env->error, key, AXIS2_FAILURE); + + old = axutil_properties_get_property(properties, env, key); + if(old) + { + AXIS2_FREE(env->allocator, old); + axutil_hash_set(properties->prop_hash, key, AXIS2_HASH_KEY_STRING, + axutil_strdup(env, value)); + return AXIS2_SUCCESS; + } + axutil_hash_set(properties->prop_hash, axutil_strdup(env, key), AXIS2_HASH_KEY_STRING, + axutil_strdup(env, value)); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axutil_hash_t *AXIS2_CALL +axutil_properties_get_all( + axutil_properties_t *properties, + const axutil_env_t *env) +{ + return properties->prop_hash; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_properties_store( + axutil_properties_t *properties, + const axutil_env_t *env, + FILE *output) +{ + axutil_hash_index_t *hi = NULL; + axis2_char_t *key = NULL; + axis2_char_t *value = NULL; + + AXIS2_PARAM_CHECK(env->error, output, AXIS2_FAILURE); + + if(properties->prop_hash) + { + for(hi = axutil_hash_first(properties->prop_hash, env); hi; hi = axutil_hash_next(env, hi)) + { + axutil_hash_this(hi, (void *)&key, NULL, (void *)&value); + if(key) + { + if(!value) + { + value = axutil_strdup(env, ""); + } + fprintf(output, "%s=%s\n", key, value); + } + } + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_properties_load( + axutil_properties_t *properties, + const axutil_env_t *env, + axis2_char_t *input_filename) +{ + FILE *input = NULL; + axis2_char_t *cur = NULL; + axis2_char_t *tag = NULL; + const int LINE_STARTED = -1; + const int LINE_MIDWAY = 0; + const int EQUAL_FOUND = 1; + const int LINE_HALFWAY = 2; + int status = LINE_STARTED; + + axis2_char_t *key = NULL; + axutil_hash_t *prop_hash = NULL; + axis2_char_t *buffer = NULL; + axis2_char_t loginfo[1024]; + + AXIS2_PARAM_CHECK(env->error, input_filename, AXIS2_FAILURE); + + prop_hash = properties->prop_hash; + + input = fopen(input_filename, "r+"); + if(!input) + { + return AXIS2_FAILURE; + } + buffer = axutil_properties_read(input, env); + + if(!buffer) + { + sprintf(loginfo, "error in reading file\n"); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, loginfo); + AXIS2_FREE(env->allocator, buffer); + return AXIS2_FAILURE; + } + + for(cur = axutil_properties_read_next(buffer); *cur; cur = axutil_properties_read_next(++cur)) + { + if(*cur == '\r') + { + *cur = '\0'; + } + else if(*cur != '\0' && *cur != '\n' && status == LINE_STARTED) + { + tag = cur; + status = LINE_MIDWAY; + } + /* equal found just create a property */ + else if(*cur == '=' && status == LINE_MIDWAY) + { + *cur = '\0'; + if(status != LINE_MIDWAY) + { + sprintf(loginfo, "equal apear in wrong place around %s\n", tag); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, loginfo); + AXIS2_FREE(env->allocator, buffer); + return AXIS2_FAILURE; + } + status = EQUAL_FOUND; + key = axutil_properties_trunk_and_dup(tag, cur, env); + } + /* right next to the equal found */ + else if(status == EQUAL_FOUND) + { + tag = cur; + status = LINE_HALFWAY; + } + + else if(*cur == '\n') + { + *cur = '\0'; + if(status == LINE_HALFWAY) + { + tag = axutil_properties_trunk_and_dup(tag, cur, env); + axutil_hash_set(prop_hash, key, AXIS2_HASH_KEY_STRING, tag); + } + status = LINE_STARTED; + } + } + if(status == LINE_HALFWAY) + { + *cur = '\0'; + tag = axutil_properties_trunk_and_dup(tag, cur, env); + axutil_hash_set(prop_hash, key, AXIS2_HASH_KEY_STRING, tag); + status = LINE_STARTED; + } + if(status != LINE_STARTED) + { + sprintf(loginfo, "error parsing properties\n"); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, loginfo); + AXIS2_FREE(env->allocator, buffer); + return AXIS2_FAILURE; + } + if(input) + { + fclose(input); + } + AXIS2_FREE(env->allocator, buffer); + return AXIS2_SUCCESS; +} + +axis2_char_t * +axutil_properties_read_next( + axis2_char_t *cur) +{ + /* ignore comment */ + if(*cur == '#') + { + for(; *cur != '\n' && *cur != '\0'; cur++) + ; + } + /* check '\\''\n' case */ + if(*cur == '\\' && *(cur + 1) == '\n') + { + /* ignore two axis2_char_ts */ + *(cur++) = ' '; + *(cur++) = ' '; + } + return cur; +} + +axis2_char_t * +axutil_properties_trunk_and_dup( + axis2_char_t *start, + axis2_char_t *end, + const axutil_env_t *env) +{ + for(; *start == ' '; start++) + ; /* remove front spaces */ + for(end--; *end == ' '; end--) + ; /* remove rear spaces */ + *(++end) = '\0'; + start = (axis2_char_t *)axutil_strdup(env, start); + return start; +} + +axis2_char_t * +axutil_properties_read( + FILE *input, + const axutil_env_t *env) +{ + size_t nread = 0; + axis2_char_t *out_stream = NULL; + size_t ncount = 0; + size_t curr_alloc = MAX_SIZE * 2; + size_t total_alloc = curr_alloc; + + out_stream = (axis2_char_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * curr_alloc); + if(!out_stream) + { + return NULL; + } + + do + { + nread = fread(out_stream + ncount, sizeof(axis2_char_t), MAX_SIZE, input); + ncount += nread; + + if(ncount + MAX_SIZE > total_alloc) + { + axis2_char_t *new_stream = NULL; + if(curr_alloc < MAX_ALLOC) + { + curr_alloc *= 2; + } + + total_alloc += curr_alloc; + new_stream = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * total_alloc); + if(!new_stream) + { + if(out_stream) + { + AXIS2_FREE(env->allocator, out_stream); + } + return NULL; + } + + memcpy(new_stream, out_stream, sizeof(axis2_char_t) * ncount); + if(out_stream) + { + AXIS2_FREE(env->allocator, out_stream); + } + out_stream = new_stream; + } + } + while(nread == MAX_SIZE); + + out_stream[ncount] = '\0'; + return out_stream; +} |