diff options
author | Dmitri Pal <dpal@dpal.csb> | 2009-02-23 10:38:06 -0500 |
---|---|---|
committer | Dmitri Pal <dpal@dpal.csb> | 2009-02-23 10:38:06 -0500 |
commit | d986aeb99fa33967374290bf7ce75eab76c6d446 (patch) | |
tree | e85af838cd95b43c4f1be5bc2203a1a3474ba589 /ini | |
download | elapi_draft-d986aeb99fa33967374290bf7ce75eab76c6d446.tar.gz elapi_draft-d986aeb99fa33967374290bf7ce75eab76c6d446.tar.xz elapi_draft-d986aeb99fa33967374290bf7ce75eab76c6d446.zip |
Initial commit.
Diffstat (limited to 'ini')
-rw-r--r-- | ini/elapi.conf | 41 | ||||
-rw-r--r-- | ini/elapi.d/test.conf | 41 | ||||
-rw-r--r-- | ini/elapi_ini.c | 626 | ||||
-rw-r--r-- | ini/elapi_ini.h | 30 | ||||
-rwxr-xr-x | ini/elapi_ini_ut | bin | 0 -> 7392 bytes | |||
-rw-r--r-- | ini/elapi_ini_ut.c | 23 |
6 files changed, 761 insertions, 0 deletions
diff --git a/ini/elapi.conf b/ini/elapi.conf new file mode 100644 index 0000000..d8553c6 --- /dev/null +++ b/ini/elapi.conf @@ -0,0 +1,41 @@ + +data = ds,mf.ds,mf.ds,m.ds,mds.,fmds. + dskjh = mdsmdssm ,md.sd, + C1 = "abcd" +;test data + + + +;more data + + = "nmjdsbfmsdn" + s = "nmjdsbfmsdn + + HEX1 = 'ABV1' + HEX2 = 'ABV' + [ ttt ] + +C2 ='Ab' + +int=-44i44 +int2=-66U + +c = + + + [ dddd ] + +DC1 = 123U + +f=-9.0.0 +DC2 = -235L +DC3 = -345.8907 + + + [ ttt ] + +v=55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 +v1=55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555.55555555555555555555555555555555 + +C3 = -34756.56 +C4 = .9 diff --git a/ini/elapi.d/test.conf b/ini/elapi.d/test.conf new file mode 100644 index 0000000..68e9c67 --- /dev/null +++ b/ini/elapi.d/test.conf @@ -0,0 +1,41 @@ + +data = ds,mf.ds,mf.ds,m.ds,mds.,fmds. + dskjh = mdsmdssm ,md.sd, + C1 = "abcd" +;test data + + + +;more data + + = "nmjdsbfmsdn" + s = "nmjdsbfmsdn + + HEX1 = 'ABV1' + HEX2 = 'ABV' + [ ttt ] + +C2 ='AbBB' + +int=-44i44 +int2=-66U + +c = + + + [ dddd1 ] + +DC1 = 123U + +f=-9.0.0 +DC2 = -235L +DC3 = -345.8907 + + + [ ttt2 ] + +v=55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 +v1=55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555.55555555555555555555555555555555 + +C3 = -34756.56 +C4 = .9 diff --git a/ini/elapi_ini.c b/ini/elapi_ini.c new file mode 100644 index 0000000..acea402 --- /dev/null +++ b/ini/elapi_ini.c @@ -0,0 +1,626 @@ +/* Copyright */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include "elapi_collection.h" +#include "elapi_debug.h" +#include "elapi_ini.h" + +/* STATIC INTERNAL FUNCTIONS */ + +#define RET_PAIR 0 +#define RET_COMMENT 1 +#define RET_SECTION 2 +#define RET_INVALID 3 +#define RET_EMPTY 4 +#define RET_EOF 5 +#define RET_ERROR 6 + + +#define NAME_OVERHEAD 10 +#define MAX_KEY 65535 +#define MAX_VALUE 65535 +#define BUFFER_SIZE MAX_KEY + MAX_VALUE + 3 + +#define SLASH "/" + + +/* Special handler to extract configuration value */ +static int value_extractor(char *property, + int property_len, + int type, + void *data, + int length, + void *custom_data, + int *stop) +{ + void *allocated = NULL; + + DEBUG_STRING("value_extractor","Entry."); + DEBUG_STRING("Property:",property); + DEBUG_NUMBER("Property length:",property_len); + DEBUG_NUMBER("Type:",type); + DEBUG_NUMBER("Length:",length); + + allocated = malloc(length); + if(allocated == NULL) return errno; + memcpy(allocated, data, length); + + *((int **)(custom_data)) = allocated; + *stop = 1; + + DEBUG_STRING("value_extractor","Success Exit."); + + return EOK; +} + + +/* Process value */ +static int process_value(char *buff, void *value, int *length, int *type) +{ + int len = 0; + int i = 0; + int esc = 0; + unsigned char hex = 0; + int mod = 0; + char *dp = NULL; + char *dp2 = NULL; + int use_long = 0; + int use_unsigned = 0; + long l_result = 0; + unsigned long ul_result = 0; + unsigned u_result = 0; + int result = 0; + double dbl = 0.; + char *errconv = NULL; + + DEBUG_STRING("process_value","Entry") + + len = strlen(buff); + if(len == 0) { + DEBUG_STRING("Empty value","") + return RET_INVALID; + } + + if(len >= MAX_VALUE) { + DEBUG_STRING("Value too big","") + return RET_INVALID; + } + + /* Is this a string ? */ + if((*buff == '"') && (*(buff+len-1) == '"')) { + buff++; + len-=2; + *length = 0; + *type = ELAPI_TYPE_STRING; + esc = 0; + for(i=0;i<len;i++) { + if(esc == 1) { + esc = 0; + } + else if(*(buff+i)=='\\') { + esc = 1; + continue; + } + *((char *)(value+(*length))) = *(buff+i); + (*length)++; + } + *((char *)(value+(*length))) = '\0'; + (*length)++; + return RET_PAIR; + } + + /* Is this a binary ? */ + if((*buff == '\'') && (*(buff+len-1) == '\'')) { + buff++; + len-=2; + if((len/2) *2 != len) { + DEBUG_STRING("Invalid length for binary data","") + return RET_INVALID; + } + *length = 0; + *type = ELAPI_TYPE_BINARY; + for(i=0;i<len;i+=2) { + if((!isxdigit(*(buff+i))) || (!isxdigit(*(buff+i+1)))) { + DEBUG_STRING("Invalid encoding for binary data","") + return RET_INVALID; + } + + if(isdigit(*(buff+i))) { + if(isdigit(*(buff+i+1))) hex = 16 * (*(buff+i) - '0') + (*(buff+i+1) - '0'); + else hex = 16 * (*(buff+i) - '0') + (tolower(*(buff+i+1)) - 'a' + 10); + } + else { + if(isdigit(*(buff+i+1))) hex = 16 * (tolower(*(buff+i)) - 'a') + (*(buff+i+1) - '0'); + else hex = 16 * (tolower(*(buff+i)) - 'a' + 10) + (tolower(*(buff+i+1)) - 'a' + 10); + } + + *((char *)(value+(*length))) = (char)(hex); + (*length)++; + } + return RET_PAIR; + } + + /* Is this a positive or negative number? */ + if(*buff == '-') { + mod = -1; + buff++; + len--; + use_unsigned = 0; + } + + /* Check for decimal point */ + dp = strchr(buff,'.'); + if(dp != NULL) { + dp2 = strchr(dp+1,'.'); + if(dp2 != NULL) { + DEBUG_STRING("More than one decimal point for double","") + return RET_INVALID; + } + } + else { + /* No decimal point so check for long */ + if(*(buff+len-1) == 'L') { + use_long = 1; + *(buff+len-1) = '\0'; + len--; + } + + if(*(buff+len-1) == 'U') { + if(mod < 0) { + DEBUG_STRING("Signed/unsigned missmatch","") + return RET_INVALID; + } + use_unsigned = 1; + *(buff+len-1) = '\0'; + len--; + } + } + + /* Check that the rest are digits */ + for(i=0;i<len;i++) { + if(!(isdigit(*(buff+i)) || (*(buff+i) == '.'))) { + DEBUG_STRING("Invalid symbol in the number","") + return RET_INVALID; + } + } + + if(mod == -1) { + buff--; + len++; + *buff = '-'; + } + + /* Copy longs and ints */ + if(dp == NULL) { + errno = 0; + if(use_unsigned) { + if(use_long) { + *type = ELAPI_TYPE_ULONG; + ul_result = (unsigned long) strtol(buff,(char **)(NULL),10); + if(errno != 0) { + DEBUG_STRING("Number is probably too long",""); + return RET_INVALID; + } + *length = sizeof(long); + memcpy(value, (void *)(&ul_result),*length); + } + else { + *type = ELAPI_TYPE_UNSIGNED; + u_result = (unsigned int) strtol(buff,(char **)(NULL),10); + if(errno != 0) { + DEBUG_STRING("Number is probably too long",""); + return RET_INVALID; + } + *length = sizeof(unsigned); + memcpy(value, (void *)(&u_result),*length); + } + } + else { + if(use_long) { + *type = ELAPI_TYPE_LONG; + l_result = (long) strtol(buff,(char **)(NULL),10); + if(errno != 0) { + DEBUG_STRING("Number is probably too long",""); + return RET_INVALID; + } + *length = sizeof(long); + memcpy(value, (void *)(&l_result),*length); + } + else { + *type = ELAPI_TYPE_INTEGER; + result = (int) strtol(buff,(char **)(NULL),10); + if(errno != 0) { + DEBUG_STRING("Number is probably too long",""); + return RET_INVALID; + } + *length = sizeof(int); + memcpy(value, (void *)(&result),*length); + } + } + } + /* Deal with double */ + else { + if(len > 20) { + DEBUG_STRING("Number is too long",""); + return RET_INVALID; + } + + errno = 0; + dbl = (double)(strtod(buff,&errconv)); + if(errno != 0) { + DEBUG_STRING("Invalid double",""); + return RET_INVALID; + } + DEBUG_STRING("Value to convert:",buff); + DEBUG_DOUBLE("Got double:",dbl) + *type = ELAPI_TYPE_DOUBLE; + *length = sizeof(double); + memcpy(value, (void *)(&dbl),*length); + } + + + DEBUG_STRING("process_value","Success"); + + return RET_PAIR; + + +} +/* Reads a line from the file */ +static int read_line(FILE *file,char *key,void *value, int *length, int *type) +{ + + char *res = NULL; + char buf[BUFFER_SIZE+1]; + int len = 0; + char *buffer = NULL; + int i = 0; + int status = RET_INVALID; + char *eq = NULL; + + DEBUG_STRING("read_line","Entry") + + buffer = buf; + + /* Get data from file */ + res = fgets(buffer,BUFFER_SIZE,file); + if(res == NULL) { + DEBUG_STRING("Read nothing","") + return RET_EOF; + } + + len = strlen(buffer); + if(len == 0) { + DEBUG_STRING("Nothing was read.","") + return RET_EMPTY; + } + + /* Added \r just in case we deal with Windows in future */ + if((*(buffer + len - 1) != '\n') && (*(buffer + len - 1) != '\r')) { + DEBUG_STRING("String it too big!","") + return RET_INVALID; + } + + /* Ingnore comments */ + if(*buffer == ';') { + DEBUG_STRING("Comment",buf) + return RET_INVALID; + } + + /* Empty line */ + if(*buffer == '\n') { + DEBUG_STRING("Empty line",buf) + return RET_INVALID; + } + + /* Trucate trailing spaces and CRs */ + while(isspace(*(buffer + len - 1))) { + *(buffer + len - 1) = '\0'; + len--; + } + + /* Trucate leading spaces */ + while(isspace(*buffer)) { + buffer++; + len--; + } + + /* Section */ + if(*buffer == '[') { + if(*(buffer+len-1) != ']') { + DEBUG_STRING("Invalid format for section",buf) + return RET_ERROR; + } + buffer++; + len--; + while(isspace(*(buffer))) { + buffer++; + len--; + } + if(len == 0) { + DEBUG_STRING("Invalid format for section",buf) + return RET_ERROR; + } + + *(buffer + len - 1) = '\0'; + len--; + while(isspace(*(buffer + len - 1))) { + *(buffer + len - 1) = '\0'; + len--; + } + if(len >= MAX_KEY) { + DEBUG_STRING("Section name is too long",buf) + return RET_ERROR; + } + + memcpy(key,buffer,len+1); + return RET_SECTION; + } + + /* Assume we are dealing with the K-V here */ + /* Find "=" */ + eq = strchr(buffer,'='); + if(eq == NULL) { + DEBUG_STRING("No equal sign",buf) + return RET_INVALID; + } + + /* Strip spaces around "=" */ + i = eq - buffer - 1; + while((i >= 0) && isspace(*(buffer + i))) i--; + if(i<0) { + DEBUG_STRING("No key",buf) + return RET_INVALID; + } + + /* Copy key into provided buffer */ + if(i >= MAX_KEY) { + DEBUG_STRING("Section name is too long",buf) + return RET_INVALID; + } + memcpy(key,buffer,i+1); + *(key+i+1) = '\0'; + DEBUG_STRING("KEY:",key); + + eq++; + while(isspace(*eq)) eq++; + DEBUG_STRING("VALUE:",eq); + + /* Now process value */ + status = process_value(eq,value,length,type); + + DEBUG_NUMBER("Type:",*type); + DEBUG_NUMBER("Data length:",*length); + + return status; +} + + + +/* Add to collection or update */ +static int add_or_update(struct collection_item *current_section, + char *key, + void *value, + int length, + int type) +{ + int found = ELAPI_NOMATCH; + int error = EOK; + + DEBUG_STRING("add_or_update", "Entry"); + + (void)is_item_in_collection(current_section,key,ELAPI_TYPE_ANY,ELAPI_TRAVERSE_IGNORE,&found); + + if(found == ELAPI_MATCH) { + DEBUG_STRING("Updating...", ""); + error = update_property(current_section,key,type,value,length,ELAPI_TRAVERSE_IGNORE); + } + else { + DEBUG_STRING("Adding...", ""); + error = add_any_property(current_section,NULL,key,type,value,length); + } + + DEBUG_NUMBER("add_or_update returning", error); + return error; +} +/***************************************************************************/ +/* Function to read single ini file and pupulate + * the provided collection with subcollcetions from the file */ +int ini_to_collection(char *filename, struct collection_item *ini_config) +{ + FILE *file; + int error; + int status; + int section_count = 0; + char key[MAX_KEY]; + char value[MAX_VALUE]; + struct collection_item *current_section = (struct collection_item *)(NULL); + int length; + int type; + + DEBUG_STRING("ini_to_collection", "Entry"); + + /* Open file for reading */ + file = fopen(filename,"r"); + if(file == NULL) { + error = errno; + DEBUG_NUMBER("Failed to open file - but this is OK", error); + return EOK; + } + + /* Read file lines */ + while((status = read_line(file,key,(void *)(value),&length,&type)) != RET_EOF) { + + switch(status) { + case RET_PAIR: + /* Do we have a section at the top of the file ? */ + if(section_count == 0) { + /* Check if collection already exists */ + error = get_collection_reference(ini_config,¤t_section,INI_DEFAULT_SECTION); + if(error != EOK) { + /* Create default collection */ + if((error=create_collection(¤t_section,INI_DEFAULT_SECTION)) || + (error=add_collection_to_collection(ini_config,NULL,NULL, + current_section, + ELAPI_ADD_MODE_REFERENCE))) { + DEBUG_NUMBER("Failed to create collection", error); + fclose(file); + destroy_collection(current_section); + return error; + } + } + section_count++; + } + + /* Put value into the collection */ + if((error=add_or_update(current_section,key,value,length,type))) { + DEBUG_NUMBER("Failed to add pair to collection", error); + fclose(file); + destroy_collection(current_section); + return error; + } + break; + + case RET_SECTION: + /* Read a new section */ + destroy_collection(current_section); + current_section = (struct collection_item *)(NULL); + + error = get_collection_reference(ini_config,¤t_section,key); + if(error != EOK) { + /* Create default collection */ + if((error=create_collection(¤t_section,key)) || + (error=add_collection_to_collection(ini_config,NULL,NULL, + current_section, + ELAPI_ADD_MODE_REFERENCE))) { + DEBUG_NUMBER("Failed to add collection", error); + fclose(file); + destroy_collection(current_section); + return error; + } + } + section_count++; + break; + + case RET_EMPTY: + DEBUG_STRING("Empty string", ""); + break; + + case RET_COMMENT: + DEBUG_STRING("Comment", ""); + break; + + case RET_ERROR: + DEBUG_STRING("Invalid section format", ""); + return EINVAL; + + case RET_INVALID: + default: + DEBUG_STRING("Invalid string", ""); + break; + } + } + + /* Close file */ + fclose(file); + destroy_collection(current_section); + + DEBUG_STRING("ini_to_collection", "Success Exit"); + + return EOK; +} + + +/*********************************************************************/ + +/* read ini file and create collection out of it */ +int config_to_collection(char *application, char *config_file, char *config_dir, struct collection_item **ini_config) +{ + int error=EOK; + char *file_name; + + DEBUG_STRING("config_to_collection", "Entry"); + + *ini_config = (struct collection_item *)(NULL); + + /* Create collection */ + if((error=create_collection(ini_config,application))) { + DEBUG_NUMBER("Failed to create collection", error); + destroy_collection(*ini_config); + return error; + } + + /* Read master file */ + if((error = ini_to_collection(config_file,*ini_config))) { + DEBUG_NUMBER("Failed to read master file", error); + destroy_collection(*ini_config); + return error; + } + + /* Get specific application file */ + file_name = malloc(strlen(config_dir) + strlen(application) + NAME_OVERHEAD); + if(file_name == NULL) { + error = errno; + DEBUG_NUMBER("Failed to allocate memory for file name", error); + destroy_collection(*ini_config); + return error; + } + + sprintf(file_name,"%s%s%s.conf",config_dir, SLASH, application); + DEBUG_STRING("Opening file:", file_name); + + /* Read master file */ + error = ini_to_collection(file_name,*ini_config); + free(file_name); + if(error) { + DEBUG_NUMBER("Failed to read specific application file", error); + destroy_collection(*ini_config); + return error; + } + + DEBUG_STRING("config_to_collection", "Exit"); + return EOK; +} + +/* Function to get value from the configration handle */ +int get_value_from_config(void *value, + int type, + char *section, + char *name, + struct collection_item *ini_config, + int &found) +{ + int error = EOK; + struct collection_item *section_handle = (struct collection_item *)(NULL); + char *to_find; + char default_section[] = INI_DEFAULT_SECTION; + struct val_extruct pass_in; + + DEBUG_STRING("get_value_from_config", "Entry"); + + if(section == NULL) to_find = default_section; + else to_find = section; + + /* Get Subcollection */ + error = get_collection_reference(ini_config,§ion_handle,to_find); + if(section_handle == (struct collection_item *)(NULL)) { + /* We have not found section - return success */ + DEBUG_STRING("get_value_from_config", "No such section"); + return EOK; + } + + /* If we have the section then get the data */ + error = get_item_and_do(ini_config, name,type, ELAPI_TRAVERSE_ONELEVEL, value_extractor, value); + + DEBUG_STRING("get_value_from_config", "Exit"); + return error; +} + + + + + + diff --git a/ini/elapi_ini.h b/ini/elapi_ini.h new file mode 100644 index 0000000..450105b --- /dev/null +++ b/ini/elapi_ini.h @@ -0,0 +1,30 @@ +/* Copyright */ + +#ifndef ELAPI_INI_H +#define ELAPI_INI_H + +#include "elapi_collection.h" + +#define INI_DEFAULT_SECTION "default" + +/* Read configuration ini file and create collection out of it */ +int config_to_collection(char *application, /* Name of the application that will be used to get config for */ + char *config_file, /* Name of the configuration file with default sessings for all apps */ + char *config_dir, /* Name of the directory where the configuration files for different apps will be dropped */ + struct collection_item **ini_config); /* New config object */ + +/* Function to get value from the config */ +int get_value_from_config(void *value, /* Pointer to the memory that will point to the retrieved result. + * The memory will always be preallocated. */ + int type, /* Expected type of the result */ + char *section, /* Section to search in */ + char *name, /* Value to look for */ + struct collection_item *ini_config, /* Config handle */ + int *found); /* Will update the provided location with 1 in the property was found. */ + +/* read ini file and create collection out of it factoring in the env variables */ +/* int ini_to_collection_env(char *filename, struct collection_item **ini_config, char *ENV prefix); */ + + + +#endif diff --git a/ini/elapi_ini_ut b/ini/elapi_ini_ut Binary files differnew file mode 100755 index 0000000..18deb77 --- /dev/null +++ b/ini/elapi_ini_ut diff --git a/ini/elapi_ini_ut.c b/ini/elapi_ini_ut.c new file mode 100644 index 0000000..7b783dc --- /dev/null +++ b/ini/elapi_ini_ut.c @@ -0,0 +1,23 @@ +/* Copyright */ + +#include <stdio.h> +#include "elapi_ini.h" +#include "elapi_tools.h" + +int main() +{ + int error; + struct collection_item *ini_config; + + error = config_to_collection("test", "elapi.conf", "./elapi.d", &ini_config); + if(error) { + printf("Attempt to read configuration returned error: %d\n",error); + return error; + } + + debug_collection(ini_config,ELAPI_TRAVERSE_DEFAULT); + print_collection(ini_config); + destroy_collection(ini_config); + return 0; + +} |