From 08645f8eeaa60f1b8c6bd30d9871389ad18196bf Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Fri, 11 Apr 2014 16:20:05 +0200 Subject: [PATCH] Add lp_config_new_from_buffer --- coreapi/lpconfig.c | 206 +++++++++++++++++++++++------------------- coreapi/lpconfig.h | 40 +++++--- tester/setup_tester.c | 45 ++++++--- 3 files changed, 171 insertions(+), 120 deletions(-) diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index 8df196df2..6e51d257c 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -177,101 +177,107 @@ LpItem *lp_section_find_item(const LpSection *sec, const char *name){ return NULL; } -void lp_config_parse(LpConfig *lpconfig, FILE *file){ - char tmp[MAX_LEN]= {'\0'}; - LpSection *cur=NULL; +static LpSection* lp_config_parse_line(LpConfig* lpconfig, const char* line, LpSection* cur) { LpSectionParam *params = NULL; char *pos1,*pos2; int nbs; - char secname[MAX_LEN]; - char key[MAX_LEN]; - char value[MAX_LEN]; + static char secname[MAX_LEN]; + static char key[MAX_LEN]; + static char value[MAX_LEN]; LpItem *item; + pos1=strchr(line,'['); + if (pos1!=NULL && is_first_char(line,pos1) ){ + pos2=strchr(pos1,']'); + if (pos2!=NULL){ + secname[0]='\0'; + /* found section */ + *pos2='\0'; + nbs = sscanf(pos1+1, "%s", secname); + if (nbs >= 1) { + if (strlen(secname) > 0) { + cur = lp_config_find_section (lpconfig,secname); + if (cur == NULL) { + cur = lp_section_new(secname); + lp_config_add_section(lpconfig, cur); + } + + if (pos2 > pos1 + 1 + strlen(secname)) { + /* found at least one section param */ + pos2 = pos1 + 1 + strlen(secname) + 1; // Remove the white space after the secname + pos1 = strchr(pos2, '='); + while (pos1 != NULL) { + /* for each section param */ + key[0] = '\0'; + value[0] = '\0'; + *pos1 = ' '; + if (sscanf(pos2, "%s %s", key, value) == 2) { + params = lp_section_param_new(key, value); + lp_config_add_section_param(cur, params); + + pos2 += strlen(key) + strlen(value) + 2; // Remove the = sign + the white space after each param + pos1 = strchr(pos2, '='); + } else { + ms_warning("parse section params error !"); + pos1 = NULL; + } + } + } + } + } else { + ms_warning("parse error!"); + } + } + }else { + pos1=strchr(line,'='); + if (pos1!=NULL){ + key[0]='\0'; + + *pos1='\0'; + if (sscanf(line,"%s",key)>0){ + + pos1++; + pos2=strchr(pos1,'\r'); + if (pos2==NULL) + pos2=strchr(pos1,'\n'); + if (pos2==NULL) pos2=pos1+strlen(pos1); + else { + *pos2='\0'; /*replace the '\n' */ + } + /* remove ending white spaces */ + for (; pos2>pos1 && pos2[-1]==' ';pos2--) pos2[-1]='\0'; + + if (pos2-pos1>=0){ + /* found a pair key,value */ + + if (cur!=NULL){ + item=lp_section_find_item(cur,key); + if (item==NULL){ + lp_section_add_item(cur,lp_item_new(key,pos1)); + }else{ + ortp_free(item->value); + item->value=ortp_strdup(pos1); + } + /*ms_message("Found %s=%s",key,pos1);*/ + }else{ + ms_warning("found key,item but no sections"); + } + } + } + } + } + return cur; +} + +void lp_config_parse(LpConfig *lpconfig, FILE *file){ + char tmp[MAX_LEN]= {'\0'}; + LpSection* current_section = NULL; + if (file==NULL) return; while(fgets(tmp,MAX_LEN,file)!=NULL){ tmp[sizeof(tmp) -1] = '\0'; - pos1=strchr(tmp,'['); - if (pos1!=NULL && is_first_char(tmp,pos1) ){ - pos2=strchr(pos1,']'); - if (pos2!=NULL){ - secname[0]='\0'; - /* found section */ - *pos2='\0'; - nbs = sscanf(pos1+1, "%s", secname); - if (nbs >= 1) { - if (strlen(secname) > 0) { - cur = lp_config_find_section (lpconfig,secname); - if (cur == NULL) { - cur = lp_section_new(secname); - lp_config_add_section(lpconfig, cur); - } - - if (pos2 > pos1 + 1 + strlen(secname)) { - /* found at least one section param */ - pos2 = pos1 + 1 + strlen(secname) + 1; // Remove the white space after the secname - pos1 = strchr(pos2, '='); - while (pos1 != NULL) { - /* for each section param */ - key[0] = '\0'; - value[0] = '\0'; - *pos1 = ' '; - if (sscanf(pos2, "%s %s", key, value) == 2) { - params = lp_section_param_new(key, value); - lp_config_add_section_param(cur, params); - - pos2 += strlen(key) + strlen(value) + 2; // Remove the = sign + the white space after each param - pos1 = strchr(pos2, '='); - } else { - ms_warning("parse section params error !"); - pos1 = NULL; - } - } - } - } - } else { - ms_warning("parse error!"); - } - } - }else { - pos1=strchr(tmp,'='); - if (pos1!=NULL){ - key[0]='\0'; - - *pos1='\0'; - if (sscanf(tmp,"%s",key)>0){ - - pos1++; - pos2=strchr(pos1,'\r'); - if (pos2==NULL) - pos2=strchr(pos1,'\n'); - if (pos2==NULL) pos2=pos1+strlen(pos1); - else { - *pos2='\0'; /*replace the '\n' */ - } - /* remove ending white spaces */ - for (; pos2>pos1 && pos2[-1]==' ';pos2--) pos2[-1]='\0'; - - if (pos2-pos1>=0){ - /* found a pair key,value */ - - if (cur!=NULL){ - item=lp_section_find_item(cur,key); - if (item==NULL){ - lp_section_add_item(cur,lp_item_new(key,pos1)); - }else{ - ortp_free(item->value); - item->value=ortp_strdup(pos1); - } - /*ms_message("Found %s=%s",key,pos1);*/ - }else{ - ms_warning("found key,item but no sections"); - } - } - } - } - } + current_section = lp_config_parse_line(lpconfig, tmp, current_section); } } @@ -279,9 +285,27 @@ LpConfig * lp_config_new(const char *filename){ return lp_config_new_with_factory(filename, NULL); } +LpConfig * lp_config_new_from_buffer(const char *buffer){ + LpConfig* conf = lp_new0(LpConfig,1); + LpSection* current_section = NULL; + + char* ptr = ms_strdup(buffer); + char* strtok_storage = NULL; + char* line = strtok_r(ptr, "\n", &strtok_storage); + + while( line != NULL ){ + current_section = lp_config_parse_line(conf,line,current_section); + line = strtok_r(NULL, "\n", &strtok_storage); + } + + ms_free(ptr); + + return conf; +} + LpConfig *lp_config_new_with_factory(const char *config_filename, const char *factory_config_filename) { LpConfig *lpconfig=lp_new0(LpConfig,1); - + if (config_filename!=NULL){ ms_message("Using (r/w) config information from %s", config_filename); lpconfig->filename=ortp_strdup(config_filename); @@ -547,7 +571,7 @@ int lp_config_get_default_int(const LpConfig *lpconfig, const char *section, con char default_section[MAX_LEN]; strcpy(default_section, section); strcat(default_section, DEFAULT_VALUES_SUFFIX); - + return lp_config_get_int(lpconfig, default_section, key, default_value); } @@ -555,7 +579,7 @@ int64_t lp_config_get_default_int64(const LpConfig *lpconfig, const char *sectio char default_section[MAX_LEN]; strcpy(default_section, section); strcat(default_section, DEFAULT_VALUES_SUFFIX); - + return lp_config_get_int64(lpconfig, default_section, key, default_value); } @@ -563,7 +587,7 @@ float lp_config_get_default_float(const LpConfig *lpconfig, const char *section, char default_section[MAX_LEN]; strcpy(default_section, section); strcat(default_section, DEFAULT_VALUES_SUFFIX); - + return lp_config_get_float(lpconfig, default_section, key, default_value); } @@ -571,6 +595,6 @@ const char* lp_config_get_default_string(const LpConfig *lpconfig, const char *s char default_section[MAX_LEN]; strcpy(default_section, section); strcat(default_section, DEFAULT_VALUES_SUFFIX); - + return lp_config_get_string(lpconfig, default_section, key, default_value); } diff --git a/coreapi/lpconfig.h b/coreapi/lpconfig.h index 0e735c1a7..f0f330c18 100644 --- a/coreapi/lpconfig.h +++ b/coreapi/lpconfig.h @@ -21,7 +21,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - + #ifndef LPCONFIG_H #define LPCONFIG_H #include @@ -33,7 +33,7 @@ /** * The LpConfig object is used to manipulate a configuration file. - * + * * @ingroup misc * The format of the configuration file is a .ini like format: * - sections are defined in [] @@ -64,6 +64,16 @@ extern "C" { */ LINPHONE_PUBLIC LpConfig * lp_config_new(const char *filename); +/** + * Instantiates a LpConfig object from a user provided buffer. + * + * @ingroup misc + * @param buffer the buffer from which the lpconfig will be retrieved. We expect the buffer to be null-terminated. + * @see lp_config_new_with_factory + * @see lp_config_new + */ +LINPHONE_PUBLIC LpConfig * lp_config_new_from_buffer(const char *buffer); + /** * Instantiates a LpConfig object from a user config file and a factory config file. * @@ -88,7 +98,7 @@ LINPHONE_PUBLIC int lp_config_read_file(LpConfig *lpconfig, const char *filename /** * Retrieves a configuration item as a string, given its section, key, and default value. - * + * * @ingroup misc * The default value string is returned if the config item isn't found. **/ @@ -105,7 +115,7 @@ LINPHONE_PUBLIC bool_t lp_config_get_range(const LpConfig *lpconfig, const char /** * Retrieves a configuration item as an integer, given its section, key, and default value. - * + * * @ingroup misc * The default integer value is returned if the config item isn't found. **/ @@ -113,7 +123,7 @@ LINPHONE_PUBLIC int lp_config_get_int(const LpConfig *lpconfig,const char *secti /** * Retrieves a configuration item as a 64 bit integer, given its section, key, and default value. - * + * * @ingroup misc * The default integer value is returned if the config item isn't found. **/ @@ -121,14 +131,14 @@ LINPHONE_PUBLIC int64_t lp_config_get_int64(const LpConfig *lpconfig,const char /** * Retrieves a configuration item as a float, given its section, key, and default value. - * + * * @ingroup misc * The default float value is returned if the config item isn't found. **/ LINPHONE_PUBLIC float lp_config_get_float(const LpConfig *lpconfig,const char *section, const char *key, float default_value); /** - * Sets a string config item + * Sets a string config item * * @ingroup misc **/ @@ -167,11 +177,11 @@ LINPHONE_PUBLIC void lp_config_set_int64(LpConfig *lpconfig,const char *section, * * @ingroup misc **/ -LINPHONE_PUBLIC void lp_config_set_float(LpConfig *lpconfig,const char *section, const char *key, float value); +LINPHONE_PUBLIC void lp_config_set_float(LpConfig *lpconfig,const char *section, const char *key, float value); /** * Writes the config file to disk. - * + * * @ingroup misc **/ LINPHONE_PUBLIC int lp_config_sync(LpConfig *lpconfig); @@ -211,7 +221,7 @@ LINPHONE_PUBLIC void lp_config_destroy(LpConfig *cfg); /** * Retrieves a default configuration item as an integer, given its section, key, and default value. - * + * * @ingroup misc * The default integer value is returned if the config item isn't found. **/ @@ -219,7 +229,7 @@ LINPHONE_PUBLIC int lp_config_get_default_int(const LpConfig *lpconfig, const ch /** * Retrieves a default configuration item as a 64 bit integer, given its section, key, and default value. - * + * * @ingroup misc * The default integer value is returned if the config item isn't found. **/ @@ -227,7 +237,7 @@ LINPHONE_PUBLIC int64_t lp_config_get_default_int64(const LpConfig *lpconfig, co /** * Retrieves a default configuration item as a float, given its section, key, and default value. - * + * * @ingroup misc * The default float value is returned if the config item isn't found. **/ @@ -235,7 +245,7 @@ LINPHONE_PUBLIC float lp_config_get_default_float(const LpConfig *lpconfig, cons /** * Retrieves a default configuration item as a string, given its section, key, and default value. - * + * * @ingroup misc * The default value string is returned if the config item isn't found. **/ @@ -243,12 +253,12 @@ LINPHONE_PUBLIC const char* lp_config_get_default_string(const LpConfig *lpconfi /** * Retrieves a section parameter item as a string, given its section and key. - * + * * @ingroup misc * The default value string is returned if the config item isn't found. **/ LINPHONE_PUBLIC const char* lp_config_get_section_param_string(const LpConfig *lpconfig, const char *section, const char *key, const char *default_value); - + #ifdef __cplusplus } #endif diff --git a/tester/setup_tester.c b/tester/setup_tester.c index 0e4299dbc..dc30e058e 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -1,19 +1,19 @@ /* - liblinphone_tester - liblinphone test suite - Copyright (C) 2013 Belledonne Communications SARL + liblinphone_tester - liblinphone test suite + Copyright (C) 2013 Belledonne Communications SARL - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include @@ -72,7 +72,7 @@ static void linphone_interpret_url_test() LinphoneCore* lc; const char* sips_address = "sips:margaux@sip.linphone.org"; LinphoneAddress* address; - + memset ( &v_table,0,sizeof ( v_table ) ); lc = linphone_core_new ( &v_table,NULL,NULL,NULL ); CU_ASSERT_PTR_NOT_NULL_FATAL ( lc ); @@ -89,12 +89,29 @@ static void linphone_interpret_url_test() linphone_core_destroy ( lc ); } +static void linphone_lpconfig_from_buffer(){ + + static const char* buffer = "[buffer]\ntest=ok"; + static const char* buffer_linebreaks = "[buffer_linebreaks]\n\n\n\r\n\n\r\ntest=ok"; + LpConfig* conf; + + conf = lp_config_new_from_buffer(buffer); + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"buffer","test",""),"ok"); + lp_config_destroy(conf); + + conf = lp_config_new_from_buffer(buffer_linebreaks); + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"buffer_linebreaks","test",""),"ok"); + lp_config_destroy(conf); + +} + test_t setup_tests[] = { { "Linphone Address", linphone_address_test }, { "Linphone core init/uninit", core_init_test }, { "Linphone random transport port",core_sip_transport_test}, - { "Linphone interpret url", linphone_interpret_url_test } + { "Linphone interpret url", linphone_interpret_url_test }, + { "LPConfig from buffer", linphone_lpconfig_from_buffer } }; test_suite_t setup_test_suite = {