blob: 995f1a0992af1b6aa996a8178bdbaaa00ff08373 [file] [log] [blame]
/* $Id$
*
* 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.
*/
/*
* etch_config.c
* config items and config file parse.
* config file is formatted as a java-style properties file expected as ansi or utf-8.
*/
#include "etch.h"
#include "etch_config.h"
#include "etch_general.h"
#define ETCH_CONFIG_LINE_MAX 1024
/*
static const char* ETCH_CONFIG_CATEGORY = "etch_config";
*/
struct etch_config_t
{
struct etch_config_entry* data;
uint16 length;
uint16 size;
};
struct etch_config_entry
{
char* name;
char* value;
};
etch_status_t etch_config_create(etch_config_t** config)
{
etch_config_t* newconfig = NULL;
if(config == NULL) {
return ETCH_EINVAL;
}
newconfig = etch_malloc(sizeof(etch_config_t), 0);
if(newconfig == NULL) {
return ETCH_ENOMEM;
}
memset(newconfig, 0, sizeof(etch_config_t));
*config = newconfig;
// default properties
etch_config_set_property(*config, "etch.validate.write", "1");
etch_config_set_property(*config, "etch.validate.read", "1");
etch_config_set_property(*config, "etch.mailbox.timeout.read", "3000");
etch_config_set_property(*config, "etch.mailbox.timeout.write", "3000");
// destroy message with mailbox
etch_config_set_property(*config, "etch.mailbox.destroy.message", "1");
// TODO: add default values
etch_config_set_property(*config, "etch.log", "error");
etch_config_set_property(*config, "etch.log.consoleappender", "consoleappender");
etch_config_set_property(*config, "etch.log.fileappender", "fileappender");
etch_config_set_property(*config, "etch.log.fileappender.file", "C:/dfdr.log");
etch_config_set_property(*config, "etch.maxconnections", "40");
return ETCH_SUCCESS;
}
etch_status_t etch_config_open(struct etch_config_t* config, const char* filepath)
{
FILE *file = NULL;
int c = 0;
char linebuf[ETCH_CONFIG_LINE_MAX];
int16 linepos = 0;
char lineend = 0;
if(config == NULL) {
return ETCH_EINVAL;
}
file = fopen(filepath, "r");
if(file == NULL) {
return ETCH_EFILENOTFOUND;
}
while(c != EOF) {
char ch = 0;
c = fgetc(file);
ch = c;
// determine end of config line
if(c == EOF || c == '\n') {
ch = '\0';
if(linepos > 0 && linebuf[linepos - 1] == '\r') {
linepos--;
}
lineend = 1;
}
if(linepos >= ETCH_CONFIG_LINE_MAX - 1) {
// error
lineend = 0;
linepos = 0;
continue;
}
linebuf[linepos++] = ch;
if(lineend) {
char *name = NULL;
char *value = NULL;
char *line = strtrim(linebuf);
// check for comments or empty lines
if(line[0] != '#' && line[0] != '\0') {
// parse line
name = strtok(line, "=");
name = strtrim(name);
if(name != NULL) {
value = strtok(NULL, "=");
value = strtrim(value);
}
etch_config_set_property(config, name, value);
}
lineend = 0;
linepos = 0;
}
}
fclose(file);
return ETCH_SUCCESS;
}
etch_status_t etch_config_set_property(etch_config_t* config, const char* name, const char* value)
{
int16 i = 0;
int16 index = -1;
if(config == NULL) {
return ETCH_EINVAL;
}
if(name == NULL || value == NULL) {
return ETCH_EINVAL;
}
// check if resize is neccesary
if(config->length == config->size) {
uint16 newsize = config->size + 10;
struct etch_config_entry* temp = etch_malloc(sizeof(struct etch_config_entry) * newsize, 0);
memset(temp, 0, sizeof(struct etch_config_entry) * newsize);
if(config->size > 0) {
memcpy(temp, config->data, sizeof(struct etch_config_entry) * config->size);
etch_free(config->data);
}
config->data = temp;
config->size = newsize;
}
// check if key exists
for(i = 0; i < config->length; i++) {
if(strcmp(config->data[i].name, name) == 0) {
index = i;
break;
}
}
// if index == -1 append new entry
if(index == -1) {
// write key
config->data[config->length].name = etch_malloc(strlen(name) + 1, 0);
memset(config->data[config->length].name, 0, (size_t)(strlen(name) + 1));
strcpy(config->data[config->length].name, name);
index = config->length++;
} else {
etch_free(config->data[index].value);
config->data[index].value = NULL;
}
// write value
config->data[index].value = etch_malloc(strlen(value) + 1, 0);
memset(config->data[index].value, 0, (size_t)(strlen(value) + 1));
strcpy(config->data[index].value, value);
return ETCH_SUCCESS;
}
int etch_config_has_property(struct etch_config_t* config, const char* name)
{
int16 i = 0;
if(config == NULL || name == NULL) {
return 0;
}
// check if key exists
for(i = 0; i < config->length; i++) {
if(strcmp(config->data[i].name, name) == 0) {
return 1;
}
}
return 0;
}
etch_status_t etch_config_get_property_string(struct etch_config_t* config, const char* name, char** value)
{
int16 i = 0;
int16 index = -1;
if(config == NULL || name == NULL|| value == NULL) {
return ETCH_EINVAL;
}
// check if key exists
for(i = 0; i < config->length; i++) {
if(strcmp(config->data[i].name, name) == 0) {
index = i;
break;
}
}
if(index != -1) {
*value = config->data[i].value;
} else {
*value = NULL;
}
return ETCH_SUCCESS;
}
etch_status_t etch_config_get_property_int(struct etch_config_t* config, const char* name, int32* value)
{
int16 i = 0;
int16 index = -1;
if(config == NULL || name == NULL|| value == NULL) {
return ETCH_EINVAL;
}
// check if key exists
for(i = 0; i < config->length; i++) {
if(strcmp(config->data[i].name, name) == 0) {
index = i;
break;
}
}
if(index != -1) {
*value = atoi(config->data[i].value);
} else {
*value = 0;
}
return ETCH_SUCCESS;
}
etch_status_t etch_config_get_property_by_index(struct etch_config_t* config, uint16 index, char** value)
{
if(config == NULL || value == NULL) {
return ETCH_EINVAL;
}
if(index < config->length) {
*value = config->data[index].value;
} else {
*value = NULL;
}
return ETCH_SUCCESS;
}
etch_status_t etch_config_clear(etch_config_t* config)
{
int16 i = 0;
if(config == NULL) {
return ETCH_EINVAL;
}
// check if key exists
for(i = 0; i < config->length; i++) {
etch_free(config->data[i].name);
etch_free(config->data[i].value);
}
config->length = 0;
return ETCH_SUCCESS;
}
uint16 etch_config_get_length(struct etch_config_t* config)
{
if(config == NULL) {
return 0;
}
return config->length;
}
uint16 etch_config_get_size(struct etch_config_t* config)
{
if(config == NULL) {
return 0;
}
return config->size;
}
etch_status_t etch_config_destroy(etch_config_t* config)
{
if(config == NULL) {
return ETCH_EINVAL;
}
etch_config_clear(config);
etch_free(config->data);
etch_free(config);
return ETCH_SUCCESS;
}