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

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