tizen 2.4 release
[framework/convergence/service/service-plugin-client.git] / src / pluginConfig.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /**
18  * @file pluginConfig.c
19  * @author Dawid Kozinski (d.kozinski@samsung.com)
20  *
21  * @brief Plugin configuration parser done in C99.
22  */
23
24 /* threads */
25 #include <glib.h>
26 #include "pluginConfig.h"
27
28 #include <string.h>
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <stdlib.h>
32 #include <limits.h>
33 #include <float.h>
34
35 #include "pluginConfigLog.h"
36
37 #define UNUSED(x) (void)(x)
38
39 /*********************************************************************************
40  *  C99 implementation
41  ******************************************************************************/
42 /*bool a = true; */
43
44 /******************************************************************************
45  *
46  *  Implicit Declarations of trimming functions
47  *  this only describes and assumes allocated elsewhere (trimming.c)
48  *
49  ******************************************************************************/
50 /**
51 * @brief trim from start, i.e. left side
52 * Trimming leading whitespace from string
53 *
54 * @param s ...
55 * @return :char*
56 **/
57 extern char *plugin_internal_ltrim(char *s);
58
59 /**
60 * @brief trim from end, i.e. right side
61 * Trimming trailing whitespace from string
62 *
63 * @param s ...
64 * @return :char*
65 **/
66 extern char *plugin_internal_rtrim(char *s);
67
68 /**
69 * @brief trim from both ends
70 * Trimming leading and trailing whitespace from string
71 * @param s ...
72 * @return :string&
73 **/
74 extern char *plugin_internal_trim(char *s);
75
76 /******************************************************************************
77  * Typedefs
78  ******************************************************************************/
79
80 /******************************************************************************
81  * [unique name][cloud_adaptor_handle*]
82  ******************************************************************************/
83 /**
84 * @typedef plugin_internal_MapStrStr
85 * Section data
86 * |---------------------------|-----------------------------------------------|
87 * | KEY : char*               | VALUE : char*                                 |
88 * |---------------------------|-----------------------------------------------|
89 * |         KEY1              |    VAL1                                       |
90 * |---------------------------|-----------------------------------------------|
91 * |         KEY2              |    VAL2                                       |
92 * |---------------------------|-----------------------------------------------|
93 * |         KEY3              |    VAL3                                       |
94 * |---------------------------|-----------------------------------------------|
95 */
96 typedef GHashTable plugin_internal_MapStrStr;
97
98 /**
99 * @typedef plugin_internal_MapStrSection
100 * Sections
101 * |---------------------------|-----------------------------------------------|
102 * | SECTION NAME : char*      | SECTION PTR      : MapStrStr *                |
103 * |---------------------------|-----------------------------------------------|
104 * |         SN1               |    SP1                                        |
105 * |---------------------------|-----------------------------------------------|
106 * |         SN2               |    SP2                                        |
107 * |---------------------------|-----------------------------------------------|
108 * |         SN3               |    SP3                                        |
109 * |---------------------------|-----------------------------------------------|
110 */
111 typedef GHashTable plugin_internal_MapStrSection;
112
113 /**
114 * @typedef plugin_internal_ListSection
115 * Sections
116 * |------------------------------------------|
117 * | SECTION PTR : MapStrStr *                |
118 * |------------------------------------------|
119 * |         SP1                              |
120 * |------------------------------------------|
121 * |         SP2                              |
122 * |------------------------------------------|
123 * |         SN3                              |
124 * |------------------------------------------|
125 */
126 typedef GList plugin_internal_ListSection;
127
128 /******************************************************************************
129  * ConfigParserState struct
130  ******************************************************************************/
131 typedef struct plugin_internal_ConfigParserState {
132         char *current_section_name;
133         plugin_internal_MapStrStr *current_section;
134 } ConfigParserState;
135
136 /******************************************************************************
137  * ConfigData class
138  ******************************************************************************/
139 typedef struct plugin_internal_ConfigData {
140         GMutex *data_mutex;
141
142         /**
143         * @brief Filepath to the read configuration file.
144         **/
145         char  *filepath;
146
147         /**
148         * @brief Describes layout of the data in the file.
149         **/
150         PluginConfigType type;
151
152         /**
153         * @brief Variable that stores the all sections of configuration,
154         * meant to be accessed through the field 'configuration'.
155         **/
156         plugin_internal_ListSection *sections;
157
158         /**
159         * @brief Variable that stores the whole configuration.
160         **/
161         plugin_internal_MapStrSection *configuration;
162 } plugin_internal_ConfigData;
163
164 /******************************************************************************
165  * Declarations (methods of ConfigData class)
166  ******************************************************************************/
167
168 /******************************************************************************
169  * Calbacks
170  ******************************************************************************/
171
172 /**
173  * @brief Function which is called when a data element of configuration map
174  * being a member of plugin_internal_ConfigData struct
175  * (@see plugin_internal_ConfigData) is destroyed.
176  * @see plugin_internal_MapStrSection
177  *
178  * @param data pointer to the user data
179  * @return void
180  **/
181 static
182 void plugin_internal_ConfigData_cbMapStrSectionFreeData(gpointer data);
183
184 /**
185  * @brief Function passed to g_hash_table_foreach().
186  * Function is called for each key/value pair.
187  *
188  * @param key a key
189  * @param value the value corresponding to the key
190  * @param user_data user data passed to g_hash_table_foreach()
191  * @return void
192  **/
193 static
194 void plugin_internal_ConfigData_cbMapStrSectionEntryCopy(gpointer key,
195         gpointer value,
196         gpointer user_data);
197
198 /**
199  * @brief Function passed to g_hash_table_foreach().
200  * Function is called for each key/value pair.
201  *
202  * @param key a key
203  * @param value the value corresponding to the key
204  * @param user_data user data passed to g_hash_table_foreach()
205  * @return void
206  **/
207 static
208 void plugin_internal_ConfigData_cbMapStrSectionCopy(gpointer key,
209         gpointer value,
210         gpointer user_data);
211 /**
212  * @brief Function passed to g_list_foreach().
213  * The function called for each element's data.
214  *
215  * @param data the element's data.
216  * @param user_data user data passed to g_list_foreach() or g_slist_foreach().
217  * @return gpointer
218  **/
219 static
220 gpointer plugin_internal_ConfigData_cbListSectionCopy(gconstpointer data,
221         gpointer user_data);
222
223 /**
224  * @brief The function to be called to free each element's data.
225  * The function which is called when a data element is destroyed.
226  * It is passed the pointer to the data element and should free any memory and
227  * resources allocated for it.
228  *
229  * @param data the data element.
230  * @return void
231  **/
232 static
233 void plugin_internal_ConfigData_cbDestroySectionsList(gpointer data);
234
235 /******************************************************************************
236  * Constructing object
237  ******************************************************************************/
238 /**
239  * @brief Contruct object of type plugin_internal_ConfigData
240  * @return plugin_internal_ConfigData*
241  **/
242 /*plugin_internal_ConfigData *plugin_internal_ConfigData_new(); */
243
244 /**
245 * @brief Contruct object of type plugin_internal_ConfigData and loads
246 * configuration from the specified file.
247 *
248 * @param filepath a path to the configuration file
249 * @param type expected type of configuration file, this value
250 * determines how the file is parsed
251 **/
252 static
253 plugin_internal_ConfigData *
254 plugin_internal_ConfigData_new(const char *filepath, PluginConfigType type);
255
256 /**
257 * @brief Copy constructor.
258 *
259 * @param source ...
260 **/
261 #if 0
262 static
263 plugin_internal_ConfigData *
264 plugin_internal_ConfigData_copy(const plugin_internal_ConfigData *source);
265 #endif
266
267 /******************************************************************************
268  * Destroying obect
269  ******************************************************************************/
270 /**
271 * @brief Removes configuration from memory, rendering this configuration invalid.
272 *
273 * @return void
274 **/
275 static
276 void plugin_internal_ConfigData_clear(plugin_internal_ConfigData *self);
277
278 /**
279 * @brief Destructor.
280 *
281 **/
282 static
283 void plugin_internal_ConfigData_delete(plugin_internal_ConfigData *self);
284
285 /******************************************************************************
286  * private methods
287  ******************************************************************************/
288
289 /**
290  * @brief parse line of INI file
291  *
292  * @param self pointer to object of type plugin_internal_ConfigData
293  * @param state ...
294  * @param line pointer to the string containing line of file
295  * @return void
296  **/
297 static
298 void plugin_internal_ConfigData_parseLineIni(plugin_internal_ConfigData *self,
299         ConfigParserState *state,
300         const char *line);
301
302 /* TODO Provide implementation */
303 /**
304  * @todo Provide implementation
305  *
306  * @brief parse line of GIT config file
307  *
308  * @param self pointer to object of type plugin_internal_ConfigData
309  * @param state ...
310  * @param line pointer to the string containing line of file
311  * @return void
312  **/
313 static
314 void plugin_internal_ConfigData_parseLineGit(plugin_internal_ConfigData *self,
315         ConfigParserState *state,
316         const char *line);
317
318 /* TODO Provide implementation */
319 /**
320  * @todo Provide implementation
321  *
322  * @brief parse line of CSV config file
323  *
324  * @param self pointer to object of type plugin_internal_ConfigData
325  * @param state ...
326  * @param line pointer to the string containing line of file
327  * @param separator ...
328  * @return void
329  **/
330 static
331 void plugin_internal_ConfigData_parseLineCsv(plugin_internal_ConfigData *self,
332         ConfigParserState *state,
333         const char *line,
334         char separator);
335
336 /* Public */
337 /**
338  * @brief ...
339  *
340  * @param self pointer to object of type plugin_internal_ConfigData
341  * @param section ...
342  * @return int
343  **/
344 static
345 bool
346 plugin_internal_ConfigData_hasSection(const plugin_internal_ConfigData *self,
347                                                 const char *section);
348
349 /**
350 * @brief This method assumes that the given section exists. Use hasSection()
351 * first, or use hasSectionAndKey() instead.
352 *
353 * @param self pointer to object of type plugin_internal_ConfigData
354 * @param section name of the configuration section
355 * @param key name of the key within that section
356 * @return int 1 if such key exists
357 **/
358 static
359 bool
360 plugin_internal_ConfigData_hasKey(const plugin_internal_ConfigData *self,
361                                                 const char *section,
362                                                 const char *key);
363
364 /**
365  * @brief ...
366  *
367  * @param self pointer to object of type plugin_internal_ConfigData
368  * @param section ...
369  * @param key ...
370  * @return int
371  **/
372 static
373 bool
374 plugin_internal_ConfigData_hasSectionAndKey(const plugin_internal_ConfigData *self,
375                                                 const char *section,
376                                                 const char *key);
377
378 /**
379  * @brief ...
380  *
381  * @param self pointer to object of type plugin_internal_ConfigData
382  * @return const char*
383  **/
384 static
385 const char *
386 plugin_internal_ConfigData_getFilepath(const plugin_internal_ConfigData *self);
387
388 /**
389  * @brief ...
390  *
391  * @param self pointer to object of type plugin_internal_ConfigData
392  * @return PluginConfigType
393  **/
394 static
395 PluginConfigType
396 plugin_internal_ConfigData_getType(const plugin_internal_ConfigData *self);
397
398 /**
399  * @brief ...
400  *
401  * @param self pointer to object of type plugin_internal_ConfigData
402  * @param section_name ...
403  * @param section_key ...
404  * @return const char*
405  **/
406 static
407 const char *
408 plugin_internal_ConfigData_getEntry(const plugin_internal_ConfigData *self,
409                                                 const char *section_name,
410                                                 const char *section_key);
411
412 /******************************************************************************
413  * Definitions (methods of ConfigData class)
414  ******************************************************************************/
415
416 /******************************************************************************/
417 static
418 void plugin_internal_ConfigData_cbMapStrSectionFreeData(gpointer data)
419 {
420         /* TODO Is it enough ? */
421         /* free(data); */
422         /* data = NULL; */
423 }
424
425 #if 0
426 /******************************************************************************/
427 plugin_internal_ConfigData *plugin_internal_ConfigData_new()
428 {
429         plugin_internal_ConfigData *self;
430         self = (plugin_internal_ConfigData *)calloc(1, sizeof(plugin_internal_ConfigData));
431
432         GMutex *data_mutex = (GMutex *)calloc(1, sizeof(GMutex));
433         g_mutex_init(data_mutex);
434
435         self->data_mutex = data_mutex;
436         self->filepath = NULL;
437         self->type = CCT_INI;
438         self->sections = NULL;
439         self->configuration = NULL;
440
441         self->configuration =  g_hash_table_new_full(g_str_hash,   /* Hash function  */
442                                                 g_str_equal,    /* Comparator */
443                                                 plugin_internal_ConfigData_cbMapStrSectionFreeData,   /* Key destructor */
444                                                 plugin_internal_ConfigData_cbMapStrSectionFreeData);  /* Val destructor */
445
446         return self;
447 }
448 #endif
449
450 /******************************************************************************/
451 static
452 plugin_internal_ConfigData *
453 plugin_internal_ConfigData_new(const char *filepath, PluginConfigType type)
454 {
455         startfunc;
456
457         if (NULL == filepath) {
458                 return NULL;
459         }
460
461         if (CCT_INVALID == type) {
462                 return NULL;
463         }
464
465         plugin_internal_ConfigData *self;
466         self = (plugin_internal_ConfigData *)calloc(1, sizeof(plugin_internal_ConfigData));
467
468         if (NULL == self) {
469                 return NULL;
470         }
471
472         GMutex *data_mutex = (GMutex *)calloc(1, sizeof(GMutex));
473         if (NULL == data_mutex) {
474                 free(self);
475                 return NULL;
476         }
477
478         g_mutex_init(data_mutex);
479
480         self->data_mutex = data_mutex;
481         self->filepath = strdup(filepath);
482         self->type = CCT_INI;
483         self->sections = NULL; /* sections.reserve(128); */
484         self->configuration = NULL;
485
486         self->configuration =
487                 g_hash_table_new_full(g_str_hash,  /* Hash function  */
488                                                 g_str_equal, /* Comparator     */
489                                                 plugin_internal_ConfigData_cbMapStrSectionFreeData, /* Key destructor */
490                                                 plugin_internal_ConfigData_cbMapStrSectionFreeData);/* Val destructor */
491
492         FILE *fp;
493         char *line;
494         size_t len = 0;
495         ssize_t read;
496
497         fp = fopen(filepath, "r");
498
499         if (NULL == fp) {
500                 /* exit(EXIT_FAILURE); */
501                 if (self) {
502                         if (self->data_mutex) {
503                                 g_mutex_clear(self->data_mutex);
504                                 free(self->data_mutex);
505                         }
506                         if (self->filepath)
507                                 free(self->filepath);
508                         if (self->configuration)
509                                 g_hash_table_destroy(self->configuration);
510                         free(self);
511                 }
512                 return NULL;
513         }
514
515         ConfigParserState state;
516
517         while ((read = getline(&line, &len, fp)) != -1) {
518                 /* printf("Retrieved line of length %zu :\n", read); */
519                 /* printf("%s", line); */
520
521                 if (strlen(line) == 0)
522                         continue;
523
524                 switch (type) {
525                 case CCT_INI:
526                         plugin_internal_ConfigData_parseLineIni(self, &state, line);
527                         break;
528                 case CCT_GIT:
529                         plugin_internal_ConfigData_parseLineGit(self, &state, line);
530                         break;
531                 case CCT_CSV_COMMA:
532                         plugin_internal_ConfigData_parseLineCsv(self, &state, line, ',');
533                         break;
534                 case CCT_CSV_TAB:
535                         plugin_internal_ConfigData_parseLineCsv(self, &state, line, '\t');
536                         break;
537                 case CCT_CSV_COLON:
538                         plugin_internal_ConfigData_parseLineCsv(self, &state, line, ':');
539                         break;
540                 case CCT_CSV_SEMICOLON:
541                         plugin_internal_ConfigData_parseLineCsv(self, &state, line, ';');
542                         break;
543                 default:
544                         break;
545                 }
546
547                 free(line);
548                 line = NULL;
549         }
550
551 /*      printf("configuration file %s was loaded\n", filepath); */
552         fclose(fp);
553
554         endfunc;
555         return self;
556 }
557
558 /******************************************************************************/
559 static
560 void plugin_internal_ConfigData_cbMapStrSectionEntryCopy(gpointer key,
561         gpointer value,
562         gpointer user_data)
563 {
564         startfunc;
565
566         plugin_internal_MapStrStr *copy_section = (plugin_internal_MapStrStr *)user_data;
567         g_hash_table_insert(copy_section, strdup((char *)key), strdup((char *)value));
568
569         endfunc;
570 }
571
572 /******************************************************************************/
573 static
574 void plugin_internal_ConfigData_cbMapStrSectionCopy(gpointer key,
575         gpointer value,
576         gpointer user_data)
577 {
578         startfunc;
579
580         plugin_internal_MapStrSection *copy_configuration = (plugin_internal_MapStrSection *)user_data;
581
582         plugin_internal_MapStrStr *section = (plugin_internal_MapStrStr *)value;
583
584         plugin_internal_MapStrStr *copy_section =
585         g_hash_table_new_full(g_str_hash,   /* Hash function  */
586                                 g_str_equal, /* Comparator     */
587                                 plugin_internal_ConfigData_cbMapStrSectionFreeData,   /* Key destructor */
588                                 plugin_internal_ConfigData_cbMapStrSectionFreeData);  /* Val destructor */
589
590         g_hash_table_foreach(section, (GHFunc)plugin_internal_ConfigData_cbMapStrSectionEntryCopy, copy_section);
591
592         g_hash_table_insert(copy_configuration, strdup((char *)key), copy_section);
593
594         endfunc;
595 }
596
597 /******************************************************************************/
598 static
599 gpointer plugin_internal_ConfigData_cbListSectionCopy(gconstpointer src,
600         gpointer data)
601 {
602         startfunc;
603
604         UNUSED(data);
605
606         plugin_internal_MapStrStr *section = (plugin_internal_MapStrStr *)src;
607
608         plugin_internal_MapStrStr *copy_section =
609         g_hash_table_new_full(g_str_hash,   /* Hash function  */
610                                 g_str_equal, /* Comparator     */
611                                 plugin_internal_ConfigData_cbMapStrSectionFreeData,   /* Key destructor */
612                                 plugin_internal_ConfigData_cbMapStrSectionFreeData);  /* Val destructor */
613
614         g_hash_table_foreach(section,
615                                 (GHFunc)plugin_internal_ConfigData_cbMapStrSectionEntryCopy,
616                                 copy_section);
617
618         endfunc;
619         return copy_section;
620 }
621
622 /******************************************************************************/
623 #if 0
624 static
625 plugin_internal_ConfigData *
626 plugin_internal_ConfigData_copy(const plugin_internal_ConfigData *source)
627 {
628         startfunc;
629
630         if (NULL == source) {
631                 return NULL;
632         }
633
634         plugin_internal_ConfigData *self;
635         self = (plugin_internal_ConfigData *)calloc(1, sizeof(plugin_internal_ConfigData));
636
637         GMutex *data_mutex = (GMutex *)calloc(1, sizeof(GMutex));
638         g_mutex_init(data_mutex);
639
640         g_mutex_lock(source->data_mutex);
641
642         self->data_mutex = data_mutex;
643         self->filepath = strdup(source->filepath);
644         self->type = source->type;
645
646         self->sections = NULL;
647
648         self->configuration =
649         g_hash_table_new_full(g_str_hash,  /* Hash function  */
650                                 g_str_equal, /* Comparator     */
651                                 plugin_internal_ConfigData_cbMapStrSectionFreeData, /* Key destructor */
652                                 plugin_internal_ConfigData_cbMapStrSectionFreeData);/* Val destructor */
653
654         /* copy source->configuration to self->configuration */
655         g_hash_table_foreach(source->configuration,
656                                 (GHFunc)plugin_internal_ConfigData_cbMapStrSectionCopy,
657                                 self->configuration);
658
659         /* copy source->sections to self->sections */
660         self->sections = g_list_copy_deep(source->sections,
661                                 plugin_internal_ConfigData_cbListSectionCopy,
662                                 NULL);
663
664         g_mutex_unlock(source->data_mutex);
665
666         endfunc;
667         return NULL;
668 }
669 #endif
670 /******************************************************************************/
671 static
672 void plugin_internal_ConfigData_delete(plugin_internal_ConfigData *self)
673 {
674         startfunc;
675
676         if (self) {
677                 plugin_internal_ConfigData_clear(self);
678         }
679
680         endfunc;
681 }
682
683 /******************************************************************************
684  * PRIVATE
685  ******************************************************************************/
686 static
687 void
688 plugin_internal_ConfigData_parseLineIni(plugin_internal_ConfigData *self,
689         ConfigParserState *state,
690         const char *line)
691 {
692         startfunc;
693
694         if (NULL == self || NULL == line) {
695                 return;
696         }
697
698         if (line[0] == ';')
699                 return;
700
701         if (line[0] == '[') {
702                 line =  plugin_internal_trim((char *)line);
703
704                 char *begin = strchr((char *)line, '[');
705                 char *end = strrchr((char *)line, ']');
706
707                 if (NULL == end) {
708                         printf("Invalid section name %p\n", line);
709                         return;
710                 }
711
712                 int section_name_len = end - begin - 1;
713
714                 char *section_name = (char *)calloc(1, section_name_len + 1);
715                 if (NULL == section_name) {
716                         return;
717                 }
718
719                 strncpy(section_name, line + 1, section_name_len);
720                 section_name[section_name_len] = '\0';
721
722                 plugin_internal_MapStrStr *section =
723                 g_hash_table_new_full(g_str_hash,  /* Hash function  */
724                 g_str_equal, /* Comparator     */
725                 plugin_internal_ConfigData_cbMapStrSectionFreeData,   /* Key destructor */
726                 plugin_internal_ConfigData_cbMapStrSectionFreeData);  /* Val destructor */
727
728                 self->sections = g_list_append(self->sections, section);
729                 /*sections.push_back(MapStrStr()); */
730
731                 /*MapStrStr *section = &(sections[sections.size() - 1]); */
732                 g_hash_table_insert(self->configuration, strdup(section_name), section);
733
734                 /* configuration[section_name] = section; */
735
736                 state->current_section_name = section_name;
737                 state->current_section = section;
738         } else {
739                 /* ---------------------------------------------------------------------
740                 * |0|1|2|3|4|5|6|7|8|
741                 * ---------------------------------------------------------------------
742                 * |K|E|Y|1|=|V|A|L|1|
743                 * ---------------------------------------------------------------------
744                 * pch = 4
745                 * len_key = 4
746                 * len_val = 4
747                 * len = 9
748                 */
749                 line =  plugin_internal_trim((char *)line);
750                 const char *pch = strchr((char *)line, '=');
751
752                 if (pch != NULL) {
753                         int len = strlen(line);
754                         int key_len = pch - line + 1 ; /* +'\0' */
755                         int value_len = len - key_len + 1; /*  +'\0' */
756
757                         char *key = (char *)calloc(1, key_len);
758                         char *value = (char *)calloc(1, value_len);
759
760                         if (NULL != key && NULL != value) {
761                                 strncpy(key, line, key_len - 1);
762                                 key[key_len - 1] = '\0';
763
764                                 strncpy(value, pch + 1, value_len - 1);
765                                 value[value_len - 1] = '\0';
766
767                                 g_hash_table_insert(state->current_section, strdup(key), strdup(value));
768                         }
769                         if (NULL != key) {
770                                 free(key);
771                                 key = NULL;
772                         }
773                         if (NULL != value) {
774                                 free(value);
775                                 value = NULL;
776                         }
777                 }
778         }
779
780         endfunc;
781 }
782
783 /******************************************************************************/
784 static
785 void
786 plugin_internal_ConfigData_parseLineGit(plugin_internal_ConfigData *self,
787         ConfigParserState *state,
788         const char *line)
789 {
790         startfunc;
791
792         if (NULL == self) {
793                 return;
794         }
795
796         UNUSED(state);
797         UNUSED(line);
798
799         endfunc;
800 }
801
802 /******************************************************************************/
803 static
804 void
805 plugin_internal_ConfigData_parseLineCsv(plugin_internal_ConfigData *self,
806         ConfigParserState *state,
807         const char *line,
808         char separator)
809 {
810         startfunc;
811
812         if (NULL == self) {
813                 return;
814         }
815
816         UNUSED(state);
817         UNUSED(line);
818         UNUSED(separator);
819
820         endfunc;
821 }
822
823 /******************************************************************************/
824 static
825 void plugin_internal_ConfigData_cbDestroySectionsList(gpointer data)
826 {
827         startfunc;
828
829         plugin_internal_MapStrStr *section = (plugin_internal_MapStrStr *)data;
830         g_hash_table_destroy(section);
831
832         endfunc;
833 }
834
835 /******************************************************************************/
836 static
837 void plugin_internal_ConfigData_clear(plugin_internal_ConfigData *self)
838 {
839         startfunc;
840
841         if (NULL == self) {
842                 return;
843         }
844
845         free(self->filepath);
846
847         self->type = CCT_INVALID;
848
849         g_hash_table_destroy(self->configuration);
850         self->configuration = NULL;
851         g_list_free_full(self->sections, plugin_internal_ConfigData_cbDestroySectionsList);
852
853         endfunc;
854 }
855
856 /******************************************************************************/
857 static
858 bool
859 plugin_internal_ConfigData_hasKey(const plugin_internal_ConfigData *self,
860                                                 const char *section_name,
861                                                 const char *section_key)
862 {
863         startfunc;
864
865         if (NULL == self || NULL == self->configuration) {
866                 return false;
867         }
868
869         g_mutex_lock(self->data_mutex);
870
871         gconstpointer lookup_key = (gconstpointer)section_name;
872         gpointer orig_key = NULL; /* key of self->configuration */
873         gpointer value = NULL;    /* value of self->configuration */
874
875         gboolean result = g_hash_table_lookup_extended(self->configuration,
876                                                 lookup_key,
877                                                 &orig_key,
878                                                 &value);
879
880         if (TRUE == result && value) {
881                 plugin_internal_MapStrStr *ptrMapSection = (plugin_internal_MapStrStr *)value ;
882
883                 lookup_key = (gconstpointer)section_key;
884                 orig_key = NULL; /* key of ptrMapSection */
885                 value = NULL;    /* value of ptrMapSection */
886
887                 result = g_hash_table_lookup_extended(ptrMapSection,
888                                                 lookup_key,
889                                                 &orig_key,
890                                                 &value);
891         }
892
893         g_mutex_unlock(self->data_mutex);
894
895         endfunc;
896         return result;
897 }
898
899 /******************************************************************************
900  * PUBLIC
901  ******************************************************************************/
902 static
903 bool
904 plugin_internal_ConfigData_hasSection(const plugin_internal_ConfigData *self,
905                                                 const char *section_name)
906 {
907         startfunc;
908
909         if (NULL == self) {
910                 return false;
911         }
912
913         g_mutex_lock(self->data_mutex);
914
915         gconstpointer lookup_key = (gconstpointer)section_name;
916         gpointer orig_key = NULL; /* key of self->configuration */
917         gpointer value = NULL;    /* value of self->configuration */
918
919         gboolean result = g_hash_table_lookup_extended(self->configuration,
920                                                 lookup_key,
921                                                 &orig_key,
922                                                 &value);
923
924         g_mutex_unlock(self->data_mutex);
925
926         endfunc;
927         return result;
928 }
929
930 /******************************************************************************/
931 static
932 bool
933 plugin_internal_ConfigData_hasSectionAndKey(const plugin_internal_ConfigData *self,
934                                                 const char *section_name,
935                                                 const char *section_key)
936 {
937         startfunc;
938
939         if (NULL == self) {
940                 return false;
941         }
942
943         g_mutex_lock(self->data_mutex);
944
945         gconstpointer lookup_key = (gconstpointer)section_name;
946         gpointer orig_key = NULL; /* key of self->configuration */
947         gpointer value = NULL;    /* value of self->configuration */
948
949         gboolean result = g_hash_table_lookup_extended(self->configuration,
950                                                 lookup_key,
951                                                 &orig_key,
952                                                 &value);
953
954         if (TRUE == result && value) {
955                 plugin_internal_MapStrStr *ptrMapSection = (plugin_internal_MapStrStr *)value ;
956                                                 lookup_key = (gconstpointer)section_key;
957                                                 orig_key = NULL; /* key of ptrMapSection */
958                                                 value = NULL;    /* value of ptrMapSection */
959
960                 result = g_hash_table_lookup_extended(ptrMapSection,
961                                                 lookup_key,
962                                                 &orig_key,
963                                                 &value);
964         }
965
966         g_mutex_unlock(self->data_mutex);
967
968         endfunc;
969         return result;
970 }
971
972 /******************************************************************************/
973 static
974 const char *
975 plugin_internal_ConfigData_getFilepath(const plugin_internal_ConfigData *self)
976 {
977         startfunc;
978
979         if (NULL == self) {
980                 return NULL;
981         }
982
983         g_mutex_lock(self->data_mutex);
984
985         const char  *result = self->filepath;
986
987         g_mutex_unlock(self->data_mutex);
988
989         endfunc;
990         return result;
991 }
992
993 /******************************************************************************/
994 static
995 PluginConfigType
996 plugin_internal_ConfigData_getType(const plugin_internal_ConfigData *self)
997 {
998         startfunc;
999
1000         if (NULL == self) {
1001                 return CCT_INVALID;
1002         }
1003
1004         g_mutex_lock(self->data_mutex);
1005
1006         PluginConfigType result = self->type;
1007
1008         g_mutex_unlock(self->data_mutex);
1009
1010         endfunc;
1011         return result;
1012 }
1013
1014 /******************************************************************************/
1015 static
1016 const char *
1017 plugin_internal_ConfigData_getEntry(const plugin_internal_ConfigData *self,
1018                                                 const char *section_name,
1019                                                 const char *section_key)
1020 {
1021         startfunc;
1022
1023         if (NULL == self) {
1024                 return NULL;
1025         }
1026
1027         g_mutex_lock(self->data_mutex);
1028
1029         gconstpointer lookup_key = (gconstpointer)section_name;
1030         gpointer orig_key = NULL; /* key of self->configuration */
1031         gpointer value = NULL;    /* value of self->configuration */
1032
1033         gboolean result = g_hash_table_lookup_extended(self->configuration,
1034                                                 lookup_key,
1035                                                 &orig_key,
1036                                                 &value);
1037
1038         if (TRUE == result && value) {
1039                 plugin_internal_MapStrStr *ptrMapSection = (plugin_internal_MapStrStr *)value ;
1040
1041                 lookup_key = (gconstpointer)section_key;
1042                 orig_key = NULL; /* key of ptrMapSection */
1043                 value = NULL;    /* value of ptrMapSection */
1044
1045                 result = g_hash_table_lookup_extended(ptrMapSection,
1046                                                 lookup_key,
1047                                                 &orig_key,
1048                                                 &value);
1049         }
1050
1051         g_mutex_unlock(self->data_mutex);
1052
1053         endfunc;
1054         return (char *)value;
1055 }
1056
1057 /******************************************************************************
1058  * Config class
1059  ******************************************************************************/
1060 /**
1061  * @brief General-purpose, class for loading and reading configuration from
1062  * simple plaintext files.
1063  **/
1064 typedef struct plugin_Config {
1065         bool _loaded;
1066         plugin_internal_ConfigData *_configuration;
1067 } plugin_Config;
1068
1069 /******************************************************************************
1070  * Declarations (methods of Config class)
1071  ******************************************************************************/
1072
1073 /**
1074  * @brief Construct object of type plugin_Config
1075  *
1076  * @return plugin_Config*
1077  **/
1078 static
1079 plugin_Config *plugin_Config_new();
1080
1081 /**
1082  * @brief Destroy object of type plugin_Config
1083  *
1084  * @param self pointer to object of type plugin_Config
1085  * @return void
1086  **/
1087 static
1088 void plugin_Config_delete(plugin_Config *self);
1089
1090 /**
1091  * @brief Loads configuration to memory and/or gets raw data from configuration.
1092  *
1093  * @param self pointer to object of type plugin_Config
1094  * @param section will return value attached to a key from this section
1095  * @param key will return value attached to this key
1096  * @return char*
1097  **/
1098 static
1099 const char *
1100 plugin_Config_getRaw(plugin_Config *self, const char *section, const char *key);
1101
1102 /**
1103  * @brief Loads the configuration from a given file into memory.
1104  *
1105  * @param self pointer to object of type plugin_Config
1106  * @param filepath path to the configuration file that will be loaded
1107  * @param type expected type of configuration file, this value determines
1108  * how the file is parsed
1109  * @return int return 1 if successful, 0 otherwise
1110  */
1111 static
1112 int
1113 plugin_Config_load(plugin_Config *self, const char *filepath, PluginConfigType type);
1114
1115 /**
1116  * @brief Unloads the configuration from the memory.
1117  *
1118  * The configuration is automatically unloaded when the Config object is
1119  * destoyed, so this method does not have to be executed unless you need
1120  * to extremely lower memory usage and few bytes matter.
1121  *
1122  * @param self pointer to object of type plugin_Config
1123  * @return void
1124  **/
1125 static void plugin_Config_unload(plugin_Config *self);
1126
1127 /**
1128 * @brief Checks wheteher config file has been loaded.
1129 *
1130 * @return int return 1 if successful, 0 otherwise
1131 **/
1132 static bool plugin_Config_isLoaded(plugin_Config *self);
1133
1134 /**
1135  * @brief From loaded configuration, gets string value attached to given key.
1136  *
1137  * @param self pointer to object of type plugin_Config
1138  * @param section ...
1139  * @param key ...
1140  * @return char* value attached to the key from the section
1141  **/
1142 static
1143 const char *
1144 plugin_Config_getString(plugin_Config *self, const char *section, const char *key);
1145
1146 /**
1147  * @brief From loaded configuration, gets integer value attached to given key.
1148  *
1149  * @param self pointer to object of type plugin_Config
1150  * @param section will return value attached to a key from this section
1151  * @param key will return value attached to this key
1152  * @return int
1153  **/
1154 static
1155 int plugin_Config_getInt(plugin_Config *self, const char *section, const char *key);
1156
1157 /**
1158  * @brief From _loaded configuration, gets double value attached to given key.
1159  *
1160  * @param self pointer to object of type plugin_Config
1161  * @param section will return value attached to a key from this section
1162  * @param key will return value attached to this key
1163  * @return double
1164  **/
1165 static
1166 double getDouble(plugin_Config *self, const char *section, const char *key);
1167
1168 /******************************************************************************
1169  * Definitiions (methods of Config class)
1170  ******************************************************************************/
1171 static
1172 plugin_Config *plugin_Config_new()
1173 {
1174         startfunc;
1175
1176         plugin_Config *self;
1177         self = (plugin_Config *)calloc(1, sizeof(plugin_Config));
1178
1179         if (NULL == self) {
1180                 return NULL;
1181         }
1182
1183         self->_loaded = false;
1184         self->_configuration = NULL;
1185
1186         endfunc;
1187         return self;
1188 }
1189
1190 /******************************************************************************/
1191 static
1192 void plugin_Config_delete(plugin_Config *self)
1193 {
1194         startfunc;
1195
1196         if (self && self->_configuration) {
1197                 free(self->_configuration);
1198                 self->_configuration = NULL;
1199         } else {
1200                 plugin_config_error("Invalid parameter");
1201         }
1202         free(self);
1203
1204         endfunc;
1205 }
1206
1207 /******************************************************************************/
1208 static
1209 const char *
1210 plugin_Config_getRaw(plugin_Config *self, const char *section, const char *key)
1211 {
1212         startfunc;
1213
1214         const char *ret = NULL;
1215
1216         if (self && self->_configuration) {
1217                 if (plugin_internal_ConfigData_hasSectionAndKey(
1218                         (const plugin_internal_ConfigData *)self->_configuration, section, key)) {
1219                         ret = plugin_internal_ConfigData_getEntry((const plugin_internal_ConfigData *)self->_configuration,
1220                                                                         section,
1221                                                                         key);
1222                 }
1223         } else {
1224                 plugin_config_error("Invalid parameter");
1225         }
1226
1227         endfunc;
1228         return ret;
1229 }
1230
1231 /******************************************************************************/
1232 static
1233 int plugin_Config_load(plugin_Config *self, const char *filepath, PluginConfigType type)
1234 {
1235         startfunc;
1236         int ret = 0;
1237
1238         if (self) {
1239                 if (self->_configuration) {
1240                         plugin_internal_ConfigData_delete(self->_configuration);
1241                         self->_configuration = NULL;
1242                 }
1243
1244                 if (filepath && strlen(filepath) > 0) {
1245                         self->_configuration = plugin_internal_ConfigData_new(filepath, type);
1246
1247                         if (self->_configuration) {
1248                                 self->_loaded = 1;
1249                                 ret = 1;
1250                         }
1251                 }
1252         } else {
1253                 plugin_config_error("Invalid parameter");
1254         }
1255
1256         endfunc;
1257         return ret;
1258 }
1259
1260 /******************************************************************************/
1261 static
1262 void plugin_Config_unload(plugin_Config *self)
1263 {
1264         startfunc;
1265
1266         if (self && self->_configuration) {
1267                 plugin_internal_ConfigData_delete(self->_configuration);
1268                 self->_configuration = NULL;
1269                 self->_loaded = false;
1270         } else {
1271                 plugin_config_error("Invalid parameter");
1272         }
1273
1274         endfunc;
1275 }
1276
1277 /******************************************************************************/
1278 static
1279 bool plugin_Config_isLoaded(plugin_Config *self)
1280 {
1281         startfunc;
1282
1283         bool ret = false;
1284
1285         if (self) {
1286                 ret = self->_loaded;
1287         } else {
1288                 plugin_config_error("Invalid parameter");
1289         }
1290
1291         endfunc;
1292         return ret;
1293 }
1294
1295 /******************************************************************************/
1296 static
1297 const char *
1298 plugin_Config_getString(plugin_Config *self, const char *section, const char *key)
1299 {
1300         plugin_config_debug_func();
1301
1302         return plugin_Config_getRaw(self, section, key);
1303 }
1304
1305
1306 /******************************************************************************/
1307 static
1308 int plugin_Config_getInt(plugin_Config *self, const char *section, const char *key)
1309 {
1310         plugin_config_debug_func();
1311
1312         const char *result = plugin_Config_getRaw(self, section, key);
1313         if (NULL == result) {
1314                 return INT_MIN;
1315         }
1316
1317         return atoi(result);
1318
1319 }
1320
1321 /******************************************************************************/
1322 static
1323 double plugin_Config_getDouble(plugin_Config *self, const char *section, const char *key)
1324 {
1325         plugin_config_debug_func();
1326
1327         const char *result = plugin_Config_getRaw(self, section, key);
1328         if (NULL == result) {
1329                 return DBL_MIN;
1330         }
1331
1332         return atof(result);
1333 }
1334
1335 /******************************************************************************
1336  * C API implementation
1337  ******************************************************************************/
1338
1339 /******************************************************************************/
1340 ConfigHandle plugin_config_create()
1341 {
1342         plugin_config_debug_func();
1343
1344         return (ConfigHandle)plugin_Config_new();
1345 }
1346
1347 /******************************************************************************/
1348 void plugin_config_delete(ConfigHandle config_handle)
1349 {
1350         startfunc;
1351
1352         plugin_Config_delete((plugin_Config *)config_handle);
1353
1354         endfunc;
1355 }
1356
1357 /******************************************************************************/
1358 void plugin_config_load(ConfigHandle config_handle, const char *filepath,
1359                                                 PluginConfigType type)
1360 {
1361         startfunc;
1362
1363         if (config_handle) {
1364                 plugin_Config *pConfig = (plugin_Config *)(config_handle);
1365                 plugin_Config_load(pConfig, filepath, type);
1366         } else {
1367                 plugin_config_error("Invalid parameter");
1368         }
1369
1370         endfunc;
1371 }
1372
1373 /******************************************************************************/
1374 void plugin_config_unload(ConfigHandle config_handle)
1375 {
1376         startfunc;
1377
1378         if (config_handle) {
1379                 plugin_Config *pConfig = (plugin_Config *)(config_handle);
1380                 plugin_Config_unload(pConfig);
1381         } else {
1382                 plugin_config_error("Invalid parameter");
1383         }
1384
1385         endfunc;
1386 }
1387
1388 /******************************************************************************/
1389 const char *plugin_config_get_string(ConfigHandle config_handle,
1390                                                 const char *section, const char *key)
1391 {
1392         startfunc;
1393
1394         const char *val = NULL;
1395
1396         if (config_handle) {
1397                 plugin_Config *pConfig = (plugin_Config *)(config_handle);
1398                 val =  plugin_Config_getString(pConfig, section, key);
1399         } else {
1400                 plugin_config_error("Invalid parameter");
1401         }
1402
1403         endfunc;
1404         return val;
1405 }
1406
1407 /******************************************************************************/
1408 int plugin_config_get_int(ConfigHandle config_handle, const char *section, const char *key)
1409 {
1410         startfunc;
1411
1412         int ret = 0;
1413
1414         if (config_handle) {
1415                 plugin_Config *pConfig = (plugin_Config *)(config_handle);
1416                 ret = plugin_Config_getInt(pConfig, section, key);
1417         } else {
1418                 plugin_config_error("Invalid parameter");
1419         }
1420
1421         endfunc;
1422         return ret;
1423 }
1424
1425 /******************************************************************************/
1426 double plugin_config_get_double(ConfigHandle config_handle, const char *section, const char *key)
1427 {
1428         startfunc;
1429
1430         double ret = 0;
1431
1432         if (config_handle) {
1433                 plugin_Config *pConfig = (plugin_Config *)(config_handle);
1434                 ret = plugin_Config_getDouble(pConfig, section, key);
1435         } else {
1436                 plugin_config_error("Invalid parameter");
1437         }
1438
1439         endfunc;
1440         return ret;
1441 }
1442
1443 /******************************************************************************/
1444 bool plugin_config_is_loaded(ConfigHandle config_handle)
1445 {
1446         startfunc;
1447         bool ret = false;
1448
1449         if (config_handle) {
1450                 plugin_Config *pConfig = (plugin_Config *)(config_handle);
1451                 ret =  plugin_Config_isLoaded(pConfig);
1452         } else {
1453                 plugin_config_error("Invalid parameter");
1454         }
1455
1456         endfunc;
1457         return ret;
1458 }