@@ -24,6 +24,14 @@ extern "C" {
2424#define INI_MAX_LINE_LENGTH 256
2525#endif
2626
27+ #ifdef INI_ENABLE_CASE_SENSITIVITY
28+ #define STRCOMPARE (x , y ) strcmp(x, y)
29+ #else
30+ #define STRCOMPARE (x , y ) strcasecmp(x, y)
31+ #endif
32+
33+ #define INI_ALLOW_EMPTY_VALUES
34+
2735typedef enum
2836{
2937 INI_LINE_EMPTY ,
@@ -93,8 +101,51 @@ static void trimWhitespace(char *str)
93101 end -- ;
94102 }
95103
96- memmove (str , start , end - start + 1 );
97- str [end - start + 1 ] = '\0' ;
104+ size_t len = (end >= start ) ? (end - start + 1 ) : 0 ;
105+
106+ if (len > 0 )
107+ {
108+ memmove (str , start , len );
109+ }
110+
111+ str [len ] = '\0' ;
112+ }
113+
114+ static void unescapeString (char * str )
115+ {
116+ char * src = str ;
117+ char * dst = str ;
118+
119+ while (* src )
120+ {
121+ if (* src == '\\' )
122+ {
123+ src ++ ;
124+
125+ switch (* src )
126+ {
127+ case '=' :
128+ * dst ++ = '=' ;
129+ break ;
130+
131+ case '\\' :
132+ * dst ++ = '\\' ;
133+ break ;
134+
135+ default :
136+ * dst ++ = '\\' ;
137+ * dst ++ = * src ;
138+ }
139+ }
140+ else
141+ {
142+ * dst ++ = * src ;
143+ }
144+
145+ src ++ ;
146+ }
147+
148+ * dst = '\0' ;
98149}
99150
100151static ini_linetype_t parseLine (const char * line , char * section , char * key , char * value )
@@ -118,7 +169,7 @@ static ini_linetype_t parseLine(const char *line, char *section, char *key, char
118169 {
119170 const char * start = ++ line ;
120171
121- while (* line && * line != ']' )
172+ while (* line && * line != ']' && * line != '\n' )
122173 {
123174 line ++ ;
124175 }
@@ -153,7 +204,14 @@ static ini_linetype_t parseLine(const char *line, char *section, char *key, char
153204 keyLen = (keyLen < INI_MAX_LINE_LENGTH - 1 ) ? keyLen : INI_MAX_LINE_LENGTH - 1 ;
154205 memcpy (key , keyStart , keyLen );
155206 key [keyLen ] = '\0' ;
207+ unescapeString (key );
156208 trimWhitespace (key );
209+
210+ if (key [0 ] == '\0' )
211+ {
212+ return INI_LINE_INVALID ;
213+ }
214+
157215 line ++ ;
158216
159217 while (isspace ((unsigned char )* line ))
@@ -172,7 +230,23 @@ static ini_linetype_t parseLine(const char *line, char *section, char *key, char
172230 valueLen = (valueLen < INI_MAX_LINE_LENGTH - 1 ) ? valueLen : INI_MAX_LINE_LENGTH - 1 ;
173231 memcpy (value , valueStart , valueLen );
174232 value [valueLen ] = '\0' ;
233+ unescapeString (value );
234+ char * comment = strpbrk (value , ";#" );
235+
236+ if (comment )
237+ {
238+ * comment = '\0' ;
239+ }
240+
175241 trimWhitespace (value );
242+ #ifndef INI_ALLOW_EMPTY_VALUES
243+
244+ if (value [0 ] == '\0' )
245+ {
246+ return INI_LINE_INVALID ;
247+ }
248+
249+ #endif
176250 return INI_LINE_KEY_VALUE ;
177251 }
178252
@@ -186,7 +260,7 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
186260 return false;
187261 }
188262
189- ctx -> content = malloc ( length + 1 );
263+ ctx -> content = calloc ( 1 , length + 1 );
190264
191265 if (!ctx -> content )
192266 {
@@ -195,6 +269,7 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
195269
196270 memcpy (ctx -> content , content , length );
197271 ctx -> content [length ] = '\0' ;
272+ ctx -> sections = NULL ;
198273 ini_section_t * currentSection = NULL ;
199274 char line [INI_MAX_LINE_LENGTH ];
200275 const char * ptr = ctx -> content ;
@@ -225,7 +300,7 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
225300
226301 if (type == INI_LINE_SECTION )
227302 {
228- ini_section_t * newSection = malloc ( sizeof (ini_section_t ));
303+ ini_section_t * newSection = calloc ( 1 , sizeof (ini_section_t ));
229304
230305 if (!newSection )
231306 {
@@ -257,16 +332,18 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
257332 }
258333 else if (type == INI_LINE_KEY_VALUE && currentSection )
259334 {
260- ini_keyvalue_t * newKv = malloc ( sizeof (ini_keyvalue_t ));
335+ ini_keyvalue_t * newKv = calloc ( 1 , sizeof (ini_keyvalue_t ));
261336
262337 if (!newKv )
263338 {
264339 ini_cleanup (ctx );
265340 return false;
266341 }
267342
268- strncpy (newKv -> key , key , INI_MAX_LINE_LENGTH );
269- strncpy (newKv -> value , value , INI_MAX_LINE_LENGTH );
343+ strncpy (newKv -> key , key , INI_MAX_LINE_LENGTH - 1 );
344+ newKv -> key [INI_MAX_LINE_LENGTH - 1 ] = '\0' ;
345+ strncpy (newKv -> value , value , INI_MAX_LINE_LENGTH - 1 );
346+ newKv -> value [INI_MAX_LINE_LENGTH - 1 ] = '\0' ;
270347 newKv -> next = NULL ;
271348
272349 if (!currentSection -> keyValues )
@@ -335,7 +412,7 @@ bool ini_hasSection(const ini_context_t *ctx, const char *section)
335412
336413 while (current )
337414 {
338- if (strcasecmp (current -> name , section ) == 0 )
415+ if (STRCOMPARE (current -> name , section ) == 0 )
339416 {
340417 return true;
341418 }
@@ -357,13 +434,13 @@ bool ini_hasKey(const ini_context_t *ctx, const char *section, const char *key)
357434
358435 while (current )
359436 {
360- if (strcasecmp (current -> name , section ) == 0 )
437+ if (STRCOMPARE (current -> name , section ) == 0 )
361438 {
362439 ini_keyvalue_t * kv = current -> keyValues ;
363440
364441 while (kv )
365442 {
366- if (strcasecmp (kv -> key , key ) == 0 )
443+ if (STRCOMPARE (kv -> key , key ) == 0 )
367444 {
368445 return true;
369446 }
@@ -399,13 +476,13 @@ bool ini_getValue(const ini_context_t *ctx, const char *section, const char *key
399476
400477 while (current )
401478 {
402- if (strcasecmp (current -> name , section ) == 0 )
479+ if (STRCOMPARE (current -> name , section ) == 0 )
403480 {
404481 ini_keyvalue_t * kv = current -> keyValues ;
405482
406483 while (kv )
407484 {
408- if (strcasecmp (kv -> key , key ) == 0 )
485+ if (STRCOMPARE (kv -> key , key ) == 0 )
409486 {
410487 strncpy (value , kv -> value , maxLen );
411488 value [maxLen - 1 ] = '\0' ;
0 commit comments