LCOV - code coverage report
Current view: top level - utils - configfile.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 190 227 83.7 %
Date: 2021-04-29 23:48:07 Functions: 19 19 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / common tools sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/config_file.h>
      27             : #include <gpac/list.h>
      28             : 
      29             : #define MAX_INI_LINE                    2046
      30             : 
      31             : typedef struct
      32             : {
      33             :         Bool do_restrict;
      34             :         char *name;
      35             :         char *value;
      36             : } IniKey;
      37             : 
      38             : typedef struct
      39             : {
      40             :         char *section_name;
      41             :         GF_List *keys;
      42             : } IniSection;
      43             : 
      44             : struct __tag_config
      45             : {
      46             :         char *fileName;
      47             :         GF_List *sections;
      48             :         Bool hasChanged, skip_changes;
      49             : };
      50             : 
      51             : 
      52       47166 : static void DelSection(IniSection *ptr)
      53             : {
      54       47166 :         if (!ptr) return;
      55       47166 :         if (ptr->keys) {
      56      365385 :                 while (gf_list_count(ptr->keys)) {
      57      318219 :                         IniKey *k = (IniKey *) gf_list_get(ptr->keys, 0);
      58      318219 :                         if (k->value) gf_free(k->value);
      59      318219 :                         if (k->name) gf_free(k->name);
      60      318219 :                         gf_free(k);
      61      318219 :                         gf_list_rem(ptr->keys, 0);
      62             :                 }
      63       47166 :                 gf_list_del(ptr->keys);
      64             :         }
      65       47166 :         if (ptr->section_name) gf_free(ptr->section_name);
      66       47166 :         gf_free(ptr);
      67             : }
      68             : 
      69             : /*!
      70             :  * \brief Clear the structure
      71             : \param iniFile The structure to clear
      72             :  */
      73       31375 : static void gf_cfg_clear(GF_Config * iniFile)
      74             : {
      75       31375 :         if (!iniFile) return;
      76       31375 :         if (iniFile->sections) {
      77       65957 :                 while (gf_list_count(iniFile->sections)) {
      78       47166 :                         IniSection *p = (IniSection *) gf_list_get(iniFile->sections, 0);
      79       47166 :                         DelSection(p);
      80       47166 :                         gf_list_rem(iniFile->sections, 0);
      81             :                 }
      82       18791 :                 gf_list_del(iniFile->sections);
      83             :         }
      84       31375 :         if (iniFile->fileName)
      85       18791 :                 gf_free(iniFile->fileName);
      86             :         memset((void *)iniFile, 0, sizeof(GF_Config));
      87             : }
      88             : 
      89             : /*!
      90             :  * \brief Parses the config file if any and clears the existing structure
      91             :  */
      92       12584 : GF_Err gf_cfg_parse_config_file(GF_Config * tmp, const char * filePath, const char * file_name)
      93             : {
      94             :         IniSection *p;
      95             :         IniKey *k=NULL;
      96             :         FILE *file;
      97             :         char *line;
      98             :         u32 line_alloc = MAX_INI_LINE;
      99             :         char fileName[GF_MAX_PATH];
     100             :         Bool line_done = GF_FALSE;
     101             :         u32 nb_empty_lines=0;
     102             :         Bool is_opts_probe = GF_FALSE;
     103             :         Bool in_multiline = GF_FALSE;;
     104       12584 :         gf_cfg_clear(tmp);
     105             : 
     106       12584 :         if (strstr(file_name, "/all_opts.txt")) {
     107          26 :                 if (filePath && !strcmp(filePath, "probe")) {
     108             :                         filePath = NULL;
     109             :                         is_opts_probe = GF_TRUE;
     110             :                 }
     111             :         }
     112             : 
     113       12558 :         if (filePath && ((filePath[strlen(filePath)-1] == '/') || (filePath[strlen(filePath)-1] == '\\')) ) {
     114             :                 strcpy(fileName, filePath);
     115             :                 strcat(fileName, file_name);
     116       12519 :         } else if (filePath) {
     117             :                 sprintf(fileName, "%s%c%s", filePath, GF_PATH_SEPARATOR, file_name);
     118             :         } else {
     119             :                 strcpy(fileName, file_name);
     120             :         }
     121             : 
     122       12584 :         tmp->fileName = gf_strdup(fileName);
     123       12584 :         tmp->sections = gf_list_new();
     124       12584 :         file = gf_fopen(fileName, "rt");
     125       12584 :         if (!file)
     126             :                 return GF_IO_ERR;
     127             :         /* load the file */
     128             :         p = NULL;
     129        6316 :         line = (char*)gf_malloc(sizeof(char)*line_alloc);
     130             :         memset(line, 0, sizeof(char)*line_alloc);
     131             : 
     132             : #define FLUSH_EMPTY_LINES \
     133             :                         if (k&& nb_empty_lines) {\
     134             :                                 u32 klen = (u32) strlen(k->value)+1+nb_empty_lines;\
     135             :                                 k->value = gf_realloc(k->value, sizeof(char)*klen);\
     136             :                                 while (nb_empty_lines) {\
     137             :                                         nb_empty_lines--;\
     138             :                                         strcat(k->value, "\n");\
     139             :                                 }\
     140             :                                 k=NULL;\
     141             :                         }\
     142             :                         nb_empty_lines=0;\
     143             : 
     144      114134 :         while (!gf_feof(file)) {
     145             :                 char *ret;
     146             :                 u32 read, nb_pass;
     147             :                 char *fsep;
     148      107842 :                 ret = gf_fgets(line, line_alloc, file);
     149      107842 :                 read = (u32) strlen(line);
     150             : 
     151             :                 nb_pass = 1;
     152      215684 :                 while (read + nb_pass == line_alloc) {
     153           0 :                         line_alloc += MAX_INI_LINE;
     154           0 :                         line = (char*)gf_realloc(line, sizeof(char)*line_alloc);
     155           0 :                         ret = gf_fgets(line+read, MAX_INI_LINE, file);
     156           0 :                         read = (u32) strlen(line);
     157           0 :                         nb_pass++;
     158             :                 }
     159      107842 :                 if (!ret) continue;
     160             : 
     161             :                 /* get rid of the end of line stuff */
     162      101550 :                 fsep = strchr(line, '=');
     163      101550 :                 if (!fsep || (fsep[1]!='@')) {
     164      203100 :                         while (!in_multiline) {
     165      203100 :                                 u32 len = (u32) strlen(line);
     166      203100 :                                 if (!len) break;
     167      203100 :                                 if ((line[len-1] != '\n') && (line[len-1] != '\r')) break;
     168      101550 :                                 line[len-1] = 0;
     169             :                         }
     170             :                 }
     171      101550 :                 if (!strlen(line)) {
     172           0 :                         if (k) nb_empty_lines++;
     173           0 :                         continue;
     174             :                 }
     175      101550 :                 if (line[0] == '#') {
     176           0 :                         FLUSH_EMPTY_LINES
     177           0 :                         continue;
     178             :                 }
     179             : 
     180             :                 /* new section */
     181      101550 :                 if (line[0] == '[') {
     182             :                         //compat with old arch
     183       12691 :                         if (nb_empty_lines) nb_empty_lines--;
     184             : 
     185       12691 :                         FLUSH_EMPTY_LINES
     186             : 
     187       12691 :                         p = (IniSection *) gf_malloc(sizeof(IniSection));
     188       12691 :                         p->keys = gf_list_new();
     189       12691 :                         p->section_name = gf_strdup(line + 1);
     190       12691 :                         p->section_name[strlen(line) - 2] = 0;
     191       12691 :                         while (p->section_name[strlen(p->section_name) - 1] == ']' || p->section_name[strlen(p->section_name) - 1] == ' ') p->section_name[strlen(p->section_name) - 1] = 0;
     192       12691 :                         gf_list_add(tmp->sections, p);
     193             :                 }
     194       88859 :                 else if (strlen(line) && !in_multiline && (strchr(line, '=') != NULL) ) {
     195       88859 :                         if (!p) {
     196           0 :                                 gf_fclose(file);
     197           0 :                                 gf_free(line);
     198           0 :                                 gf_cfg_clear(tmp);
     199           0 :                                 return GF_IO_ERR;
     200             :                         }
     201       88859 :                         FLUSH_EMPTY_LINES
     202             : 
     203       88859 :                         k = (IniKey *) gf_malloc(sizeof(IniKey));
     204             :                         memset((void *)k, 0, sizeof(IniKey));
     205       88859 :                         ret = strchr(line, '=');
     206       88859 :                         if (ret) {
     207       88859 :                                 ret[0] = 0;
     208       88859 :                                 k->name = gf_strdup(line);
     209       88859 :                                 while (k->name[strlen(k->name) - 1] == ' ') k->name[strlen(k->name) - 1] = 0;
     210       88859 :                                 ret[0] = '=';
     211       88859 :                                 ret += 1;
     212       88859 :                                 while (ret[0] == ' ') ret++;
     213       88859 :                                 if (ret[0]=='@') {
     214           0 :                                         ret++;
     215             :                                         in_multiline = GF_TRUE;
     216             :                                 }
     217       88859 :                                 if ( ret[0] != 0) {
     218       88859 :                                         k->value = gf_strdup(ret);
     219       88859 :                                         while (k->value[strlen(k->value) - 1] == ' ') k->value[strlen(k->value) - 1] = 0;
     220             :                                 } else {
     221           0 :                                         k->value = gf_strdup("");
     222             :                                 }
     223             :                                 line_done = GF_FALSE;
     224             :                         }
     225       88859 :                         gf_list_add(p->keys, k);
     226             :                         if (line_done) k=NULL;
     227             :                         line_done=GF_FALSE;
     228             : 
     229       88859 :                         if (is_opts_probe) {
     230          24 :                                 if (!strcmp(p->section_name, "version") && !strcmp(k->name, "version")) {
     231             :                                         break;
     232             :                                 }
     233             :                         }
     234             : 
     235           0 :                 } else if (k) {
     236           0 :                         u32 l1 = (u32) strlen(k->value);
     237           0 :                         u32 l2 = (u32) strlen(line);
     238           0 :                         k->value = gf_realloc(k->value, sizeof(char) * (l1 + l2 + 1 + nb_empty_lines) );
     239           0 :                         l2 += l1 + nb_empty_lines;
     240           0 :                         while (nb_empty_lines) {
     241           0 :                                 strcat(k->value, "\n");
     242           0 :                                 nb_empty_lines--;
     243             :                         }
     244           0 :                         strcat(k->value, line);
     245           0 :                         l2 -= 2; //@ and \n
     246           0 :                         if (k->value[l2] == '@') {
     247           0 :                                 k->value[l2] = 0;
     248             :                                 k=NULL;
     249             :                                 in_multiline = GF_FALSE;
     250             :                         }
     251             :                 } else {
     252             :                         k = NULL;
     253             :                 }
     254             :         }
     255        6316 :         gf_free(line);
     256        6316 :         gf_fclose(file);
     257        6316 :         return GF_OK;
     258             : }
     259             : 
     260             : GF_EXPORT
     261          96 : GF_Config *gf_cfg_force_new(const char *filePath, const char* file_name) {
     262          96 :         GF_Config *tmp = (GF_Config *)gf_malloc(sizeof(GF_Config));
     263             :         memset((void *)tmp, 0, sizeof(GF_Config));
     264          96 :         gf_cfg_parse_config_file(tmp, filePath, file_name);
     265          96 :         return tmp;
     266             : }
     267             : 
     268             : 
     269             : GF_EXPORT
     270       18697 : GF_Config *gf_cfg_new(const char *filePath, const char* file_name)
     271             : {
     272       18697 :         GF_Config *tmp = (GF_Config *)gf_malloc(sizeof(GF_Config));
     273             :         memset((void *)tmp, 0, sizeof(GF_Config));
     274       18697 :         if (!filePath && !file_name) {
     275        6209 :                 tmp->sections = gf_list_new();
     276        6209 :                 return tmp;
     277             :         }
     278             : 
     279       12488 :         if (gf_cfg_parse_config_file(tmp, filePath, file_name)) {
     280        6223 :                 gf_cfg_clear(tmp);
     281        6223 :                 gf_free(tmp);
     282             :                 tmp = NULL;
     283             :         }
     284             :         return tmp;
     285             : }
     286             : 
     287             : GF_EXPORT
     288          55 : const char * gf_cfg_get_filename(GF_Config *iniFile)
     289             : {
     290          55 :         if (!iniFile)
     291             :                 return NULL;
     292          55 :         return iniFile->fileName;
     293             : }
     294             : 
     295             : GF_EXPORT
     296       12710 : GF_Err gf_cfg_save(GF_Config *iniFile)
     297             : {
     298             :         u32 i, j;
     299             :         IniSection *sec;
     300             :         IniKey *key;
     301             :         FILE *file;
     302             : 
     303       12710 :         if (!iniFile->hasChanged) return GF_OK;
     304        6366 :         if (iniFile->skip_changes) return GF_OK;
     305         157 :         if (!iniFile->fileName) return GF_OK;
     306             : 
     307         157 :         file = gf_fopen(iniFile->fileName, "wt");
     308         157 :         if (!file) return GF_IO_ERR;
     309             : 
     310         157 :         i=0;
     311         625 :         while ( (sec = (IniSection *) gf_list_enum(iniFile->sections, &i)) ) {
     312             :                 /*Temporary sections are not saved*/
     313         311 :                 if (!strnicmp(sec->section_name, "temp", 4)) continue;
     314             : 
     315         310 :                 gf_fprintf(file, "[%s]\n", sec->section_name);
     316         310 :                 j=0;
     317        7085 :                 while ( (key = (IniKey *) gf_list_enum(sec->keys, &j)) ) {
     318        6465 :                         if (strchr(key->value, '\n')) {
     319         160 :                                 gf_fprintf(file, "%s=@%s@\n", key->name, key->value);
     320             :                         } else {
     321        6305 :                                 gf_fprintf(file, "%s=%s\n", key->name, key->value);
     322             :                         }
     323             :                 }
     324             :         }
     325         157 :         gf_fclose(file);
     326         157 :         return GF_OK;
     327             : }
     328             : 
     329             : GF_EXPORT
     330        6212 : GF_Err gf_cfg_discard_changes(GF_Config *iniFile)
     331             : {
     332        6212 :         if (!iniFile) return GF_BAD_PARAM;
     333        6212 :         iniFile->skip_changes = GF_TRUE;
     334        6212 :         return GF_OK;
     335             : }
     336             : 
     337             : GF_EXPORT
     338       12568 : void gf_cfg_del(GF_Config *iniFile)
     339             : {
     340       12568 :         if (!iniFile) return;
     341       12568 :         gf_cfg_save(iniFile);
     342       12568 :         gf_cfg_clear(iniFile);
     343       12568 :         gf_free(iniFile);
     344             : }
     345             : 
     346             : #if 0 //unused
     347             : void gf_cfg_remove(GF_Config *iniFile)
     348             : {
     349             :         if (!iniFile) return;
     350             :         gf_file_delete(iniFile->fileName);
     351             :         gf_cfg_clear(iniFile);
     352             :         gf_free(iniFile);
     353             : }
     354             : #endif
     355             : 
     356      708544 : const char *gf_cfg_get_key_internal(GF_Config *iniFile, const char *secName, const char *keyName, Bool restricted_only)
     357             : {
     358             :         u32 i;
     359             :         IniSection *sec;
     360             :         IniKey *key;
     361             : 
     362      708544 :         i=0;
     363     4163633 :         while ( (sec = (IniSection *) gf_list_enum(iniFile->sections, &i)) ) {
     364     3160694 :                 if (!strcmp(secName, sec->section_name)) goto get_key;
     365             :         }
     366             :         return NULL;
     367             : 
     368      414149 : get_key:
     369      414149 :         i=0;
     370     8153502 :         while ( (key = (IniKey *) gf_list_enum(sec->keys, &i)) ) {
     371     7484529 :                 if (!strcmp(key->name, keyName)) {
     372      159325 :                         if (!restricted_only || key->do_restrict)
     373      159322 :                                 return key->value;
     374             :                         return NULL;
     375             :                 }
     376             :         }
     377             :         return NULL;
     378             : }
     379             : GF_EXPORT
     380      690484 : const char *gf_cfg_get_key(GF_Config *iniFile, const char *secName, const char *keyName)
     381             : {
     382      690484 :         return gf_cfg_get_key_internal(iniFile, secName, keyName, GF_FALSE);
     383             : }
     384             : 
     385             : #if 0 //unused
     386             : const char *gf_cfg_get_ikey(GF_Config *iniFile, const char *secName, const char *keyName)
     387             : {
     388             :         u32 i;
     389             :         IniSection *sec;
     390             :         IniKey *key;
     391             : 
     392             :         i=0;
     393             :         while ( (sec = (IniSection *) gf_list_enum(iniFile->sections, &i)) ) {
     394             :                 if (!stricmp(secName, sec->section_name)) goto get_key;
     395             :         }
     396             :         return NULL;
     397             : 
     398             : get_key:
     399             :         i=0;
     400             :         while ( (key = (IniKey *) gf_list_enum(sec->keys, &i)) ) {
     401             :                 if (!stricmp(key->name, keyName)) return key->value;
     402             :         }
     403             :         return NULL;
     404             : }
     405             : #endif
     406             : 
     407      240439 : GF_Err gf_cfg_set_key_internal(GF_Config *iniFile, const char *secName, const char *keyName, const char *keyValue, Bool is_restrict)
     408             : {
     409             :         u32 i;
     410             :         Bool has_changed = GF_TRUE;
     411             :         IniSection *sec;
     412             :         IniKey *key;
     413             : 
     414      240439 :         if (!iniFile || !secName || !keyName) return GF_BAD_PARAM;
     415             : 
     416      240439 :         if (!strnicmp(secName, "temp", 4)) has_changed = GF_FALSE;
     417             : 
     418      240439 :         i=0;
     419     1183333 :         while ((sec = (IniSection *) gf_list_enum(iniFile->sections, &i)) ) {
     420      908409 :                 if (!strcmp(secName, sec->section_name)) goto get_key;
     421             :         }
     422             :         /* need a new key */
     423       34485 :         sec = (IniSection *) gf_malloc(sizeof(IniSection));
     424       34485 :         sec->section_name = gf_strdup(secName);
     425       34485 :         sec->keys = gf_list_new();
     426       34485 :         if (has_changed)
     427       32703 :                 iniFile->hasChanged = GF_TRUE;
     428       34485 :         gf_list_add(iniFile->sections, sec);
     429             : 
     430      446393 : get_key:
     431      240439 :         i=0;
     432     6321617 :         while ( (key = (IniKey *) gf_list_enum(sec->keys, &i) ) ) {
     433     5851723 :                 if (!strcmp(key->name, keyName)) goto set_value;
     434             :         }
     435      229455 :         if (!keyValue) return GF_OK;
     436             :         /* need a new key */
     437      229443 :         key = (IniKey *) gf_malloc(sizeof(IniKey));
     438      229443 :         key->name = gf_strdup(keyName);
     439      229443 :         key->value = gf_strdup("");
     440      229443 :         if (has_changed)
     441      226805 :                 iniFile->hasChanged = GF_TRUE;
     442      229443 :         gf_list_add(sec->keys, key);
     443             : 
     444      251411 : set_value:
     445      240427 :         if (!keyValue) {
     446           0 :                 gf_list_del_item(sec->keys, key);
     447           0 :                 if (key->name) gf_free(key->name);
     448           0 :                 if (key->value) gf_free(key->value);
     449           0 :                 gf_free(key);
     450           0 :                 if (has_changed)
     451           0 :                         iniFile->hasChanged = GF_TRUE;
     452             :                 return GF_OK;
     453             :         }
     454      240427 :         key->do_restrict = is_restrict;
     455             :         /* same value, don't update */
     456      240427 :         if (!strcmp(key->value, keyValue)) return GF_OK;
     457             : 
     458      233769 :         if (key->value) gf_free(key->value);
     459      233769 :         key->value = gf_strdup(keyValue);
     460      233769 :         if (has_changed)
     461      231120 :                 iniFile->hasChanged = GF_TRUE;
     462             :         return GF_OK;
     463             : }
     464             : 
     465             : GF_EXPORT
     466      240439 : GF_Err gf_cfg_set_key(GF_Config *iniFile, const char *secName, const char *keyName, const char *keyValue)
     467             : {
     468      240439 :         return gf_cfg_set_key_internal(iniFile, secName, keyName, keyValue, GF_FALSE);
     469             : 
     470             : }
     471             : 
     472             : GF_EXPORT
     473        6480 : u32 gf_cfg_get_section_count(GF_Config *iniFile)
     474             : {
     475        6480 :         return gf_list_count(iniFile->sections);
     476             : }
     477             : 
     478             : GF_EXPORT
     479       14696 : const char *gf_cfg_get_section_name(GF_Config *iniFile, u32 secIndex)
     480             : {
     481       14696 :         IniSection *is = (IniSection *) gf_list_get(iniFile->sections, secIndex);
     482       14696 :         if (!is) return NULL;
     483       14696 :         return is->section_name;
     484             : }
     485             : 
     486             : GF_EXPORT
     487       17696 : u32 gf_cfg_get_key_count(GF_Config *iniFile, const char *secName)
     488             : {
     489       17696 :         u32 i = 0;
     490             :         IniSection *sec;
     491       72166 :         while ( (sec = (IniSection *) gf_list_enum(iniFile->sections, &i)) ) {
     492       51617 :                 if (!strcmp(secName, sec->section_name)) return gf_list_count(sec->keys);
     493             :         }
     494             :         return 0;
     495             : }
     496             : 
     497             : GF_EXPORT
     498       99677 : const char *gf_cfg_get_key_name(GF_Config *iniFile, const char *secName, u32 keyIndex)
     499             : {
     500       99677 :         u32 i = 0;
     501             :         IniSection *sec;
     502      334002 :         while ( (sec = (IniSection *) gf_list_enum(iniFile->sections, &i) ) ) {
     503      234325 :                 if (!strcmp(secName, sec->section_name)) {
     504       99677 :                         IniKey *key = (IniKey *) gf_list_get(sec->keys, keyIndex);
     505       99677 :                         return key ? key->name : NULL;
     506             :                 }
     507             :         }
     508             :         return NULL;
     509             : }
     510             : 
     511             : GF_EXPORT
     512        7503 : void gf_cfg_del_section(GF_Config *iniFile, const char *secName)
     513             : {
     514             :         u32 i;
     515             :         IniSection *p;
     516        7503 :         if (!iniFile) return;
     517             : 
     518        7503 :         i = 0;
     519       55345 :         while ((p = (IniSection*)gf_list_enum(iniFile->sections, &i))) {
     520       40339 :                 if (!strcmp(secName, p->section_name)) {
     521           0 :                         DelSection(p);
     522           0 :                         gf_list_rem(iniFile->sections, i-1);
     523           0 :                         iniFile->hasChanged = GF_TRUE;
     524           0 :                         return;
     525             :                 }
     526             :         }
     527             : }
     528             : 
     529             : #if 0 //unused
     530             : GF_Err gf_cfg_insert_key(GF_Config *iniFile, const char *secName, const char *keyName, const char *keyValue, u32 index)
     531             : {
     532             :         u32 i;
     533             :         IniSection *sec;
     534             :         IniKey *key;
     535             : 
     536             :         if (!iniFile || !secName || !keyName|| !keyValue) return GF_BAD_PARAM;
     537             : 
     538             :         i=0;
     539             :         while ( (sec = (IniSection *) gf_list_enum(iniFile->sections, &i) ) ) {
     540             :                 if (!strcmp(secName, sec->section_name)) break;
     541             :         }
     542             :         if (!sec) return GF_BAD_PARAM;
     543             : 
     544             :         i=0;
     545             :         while ( (key = (IniKey *) gf_list_enum(sec->keys, &i) ) ) {
     546             :                 if (!strcmp(key->name, keyName)) return GF_BAD_PARAM;
     547             :         }
     548             : 
     549             :         key = (IniKey *) gf_malloc(sizeof(IniKey));
     550             :         key->name = gf_strdup(keyName);
     551             :         key->value = gf_strdup(keyValue);
     552             :         gf_list_insert(sec->keys, key, index);
     553             :         iniFile->hasChanged = GF_TRUE;
     554             :         return GF_OK;
     555             : }
     556             : #endif
     557             : 
     558             : #if 0 //unused
     559             : const char *gf_cfg_get_sub_key(GF_Config *iniFile, const char *secName, const char *keyName, u32 sub_index)
     560             : {
     561             :         u32 j;
     562             :         char *subKeyValue, *returnKey;
     563             :         char *keyValue;
     564             : 
     565             : 
     566             :         keyValue = gf_strdup(gf_cfg_get_key(iniFile, secName, keyName));
     567             :         if (!keyValue) {
     568             :                 return NULL;
     569             :         }
     570             : 
     571             :         j = 0;
     572             :         subKeyValue = strtok((char*)keyValue,";");
     573             :         while (subKeyValue!=NULL) {
     574             :                 if (j==sub_index) {
     575             :                         returnKey = gf_strdup(subKeyValue);
     576             :                         gf_free(keyValue);
     577             :                         return returnKey;
     578             :                 }
     579             :                 j++;
     580             :                 subKeyValue = strtok (NULL, ";");
     581             :         }
     582             :         gf_free(keyValue);
     583             :         return NULL;
     584             : }
     585             : #endif
     586             : 
     587        6209 : GF_Err gf_cfg_set_filename(GF_Config *iniFile, const char * fileName)
     588             : {
     589        6209 :         if (!fileName) return GF_OK;
     590        6209 :         if (iniFile->fileName) gf_free(iniFile->fileName);
     591        6209 :         iniFile->fileName = gf_strdup(fileName);
     592        6209 :         return iniFile->fileName ? GF_OK : GF_OUT_OF_MEM;
     593             : }
     594             : 
     595             : 

Generated by: LCOV version 1.13