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