UDI/udibuild - Added trim of leading/trailing spaces to inifile
[tpg/acess2.git] / UDI / Tools / udibuild_src / inifile.c
1 /*
2  * udibuild - UDI Compilation Utility
3  * - By John Hodge (thePowersGang)
4  * Part of the Acess2 OS Project
5  *
6  * inifile.c
7  * - .ini file parsing
8  */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <assert.h>
13 #include <ctype.h>
14 #include "include/inifile.h"
15
16 typedef struct sInifile_Section tIniFile_Section;
17 typedef struct sInifile_Value   tIniFile_Value;
18
19 struct sInifile_Value
20 {
21         tIniFile_Value  *Next;
22         const char      *Key;
23         const char      *Value;
24 };
25
26 struct sInifile_Section
27 {
28         tIniFile_Section        *Next;
29         const char *Name;
30         tIniFile_Value  *FirstValue;
31 };
32
33 struct sInifile
34 {
35         tIniFile_Section        RootSection;
36 };
37
38 // === CODE ===
39 static void rtrim(char *str)
40 {
41         char *pos = str;
42         while( *pos )
43                 pos ++;
44         while( pos != str && isspace(pos[-1]) )
45                 *--pos = '\0';
46 }
47
48 tIniFile *IniFile_Load(const char *Path)
49 {
50         FILE    *fp = fopen(Path, "r");
51         if( !fp )
52                 return NULL;
53         
54         tIniFile        *ret = malloc( sizeof(tIniFile) );
55         assert(ret);
56
57         ret->RootSection.Name = "";
58         ret->RootSection.FirstValue = NULL;
59
60         tIniFile_Section        *curSect = &ret->RootSection;
61         char buf[512];
62         while( fgets(buf, sizeof(buf)-1, fp) )
63         {
64                 if( strchr(buf, '#') )
65                         *strchr(buf, '#') = '\0';
66                 rtrim(buf);
67                 char name[64];
68                 size_t ofs = 0;
69                 if( sscanf(buf, "[%[^]]]", name) == 1 ) {
70                         //printf("section %s\n", name);
71                         // new section
72                         tIniFile_Section *new_sect = malloc(sizeof(tIniFile_Section)+strlen(name)+1);
73                         new_sect->Next = NULL;
74                         new_sect->Name = (const char*)(new_sect+1);
75                         new_sect->FirstValue = NULL;
76                         strcpy( (char*)new_sect->Name, name );
77                         curSect->Next = new_sect;
78                         curSect = new_sect;
79                 }
80                 else if( sscanf(buf, "%[^=]=%n", name, &ofs) >= 1 ) {
81                         rtrim(name);
82                         while( isspace(buf[ofs]) )      ofs ++;
83                         //printf("key %s equals %s\n", name, value);
84                         const char *value = buf + ofs;
85                         tIniFile_Value *val = malloc(sizeof(tIniFile_Value)+strlen(name)+1+strlen(value)+1);
86                         val->Next = curSect->FirstValue;
87                         curSect->FirstValue = val;
88                         
89                         val->Key = (char*)(val+1);
90                         strcpy((char*)val->Key, name);
91                         val->Value = val->Key + strlen(val->Key) + 1;
92                         strcpy((char*)val->Value, value);
93                 }
94                 else {
95                         //printf("ignore %s\n", buf);
96                         // ignore
97                 }
98         }
99
100         fclose(fp);     
101
102         return ret;
103 }
104
105 const char *IniFile_Get(tIniFile *File, const char *Sect, const char *Key, const char *Default)
106 {
107         if( !File )
108                 return Default;
109         
110         tIniFile_Section        *sect;
111         for( sect = &File->RootSection; sect; sect = sect->Next )
112         {
113                 if( strcmp(sect->Name, Sect) == 0 )
114                         break;
115         }
116         if( !sect )
117                 return Default;
118         
119         tIniFile_Value  *val;
120         for( val = sect->FirstValue; val; val = val->Next )
121         {
122                 if( strcmp(val->Key, Key) == 0 )
123                         break;
124         }
125         if( !val )
126                 return Default;
127         
128         return val->Value;
129 }
130
131 void IniFile_Free(tIniFile *File)
132 {
133         // TODO:
134 }

UCC git Repository :: git.ucc.asn.au