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