summaryrefslogtreecommitdiffstats
path: root/ini
diff options
context:
space:
mode:
authorDmitri Pal <dpal@dpal.csb>2009-02-23 10:38:06 -0500
committerDmitri Pal <dpal@dpal.csb>2009-02-23 10:38:06 -0500
commitd986aeb99fa33967374290bf7ce75eab76c6d446 (patch)
treee85af838cd95b43c4f1be5bc2203a1a3474ba589 /ini
downloadelapi_draft-d986aeb99fa33967374290bf7ce75eab76c6d446.tar.gz
elapi_draft-d986aeb99fa33967374290bf7ce75eab76c6d446.tar.xz
elapi_draft-d986aeb99fa33967374290bf7ce75eab76c6d446.zip
Initial commit.
Diffstat (limited to 'ini')
-rw-r--r--ini/elapi.conf41
-rw-r--r--ini/elapi.d/test.conf41
-rw-r--r--ini/elapi_ini.c626
-rw-r--r--ini/elapi_ini.h30
-rwxr-xr-xini/elapi_ini_utbin0 -> 7392 bytes
-rw-r--r--ini/elapi_ini_ut.c23
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,&current_section,INI_DEFAULT_SECTION);
+ if(error != EOK) {
+ /* Create default collection */
+ if((error=create_collection(&current_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,&current_section,key);
+ if(error != EOK) {
+ /* Create default collection */
+ if((error=create_collection(&current_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,&section_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
new file mode 100755
index 0000000..18deb77
--- /dev/null
+++ b/ini/elapi_ini_ut
Binary files differ
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;
+
+}