1 /***************************************************************************
2                           types.i - Libini supported data types
3                                     Use readString for others
4 
5                              -------------------
6     begin                : Fri Apr 21 2000
7     copyright            : (C) 2000 by Simon White
8     email                : s_a_white@email.com
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *   This program is free software; you can redistribute it and/or modify  *
14  *   it under the terms of the GNU General Public License as published by  *
15  *   the Free Software Foundation; either version 2 of the License, or     *
16  *   (at your option) any later version.                                   *
17  *                                                                         *
18  ***************************************************************************/
19 
20 #include <ctype.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include "ini.h"
25 
26 
27 /********************************************************************************************************************
28  * Function          : __ini_read
29  * Parameters        : ini - pointer to ini file database, size - key length returned here
30  * Returns           : -1 for Error and 0 on success.
31  * Globals Used      :
32  * Globals Modified  :
33  * Description       : Common read functionality
34  ********************************************************************************************************************
35  *  Rev   |   Date   |  By   | Comment
36  * ----------------------------------------------------------------------------------------------------------------
37  ********************************************************************************************************************/
__ini_read(ini_t * ini,size_t * size)38 static int __ini_read (ini_t *ini, size_t *size)
39 {
40     struct key_tag *_key;
41 
42     if (!ini->selected)
43         return -1;
44     // Locate and read keys value
45     _key = ini->selected->selected;
46     if (!_key)
47         return -1;
48 
49     if (_key->length)
50     {   // Locate and read back keys data
51         fseek (ini->ftmp, _key->pos, SEEK_SET);
52     }
53     else if (_key == &ini->tmpKey)
54         return -1; // Can't read tmpKey
55     *size = _key->length;
56     return 0;
57 }
58 
59 
60 #ifdef INI_ADD_LIST_SUPPORT
61 /********************************************************************************************************************
62  * Function          : __ini_readList
63  * Parameters        : ini - pointer to ini file database.
64  * Returns           : Pointer to buffer holding data.
65  * Globals Used      :
66  * Globals Modified  :
67  * Description       : Common read functionality from a list
68  ********************************************************************************************************************
69  *  Rev   |   Date   |  By   | Comment
70  * ----------------------------------------------------------------------------------------------------------------
71  ********************************************************************************************************************/
__ini_readList(ini_t * ini)72 static char *__ini_readList (ini_t *ini)
73 {
74     if (!ini->selected)
75         return NULL;
76     // Locate and read keys value
77     if (!ini->selected->selected)
78         return NULL;
79     return __ini_listRead (ini);
80 }
81 #endif // INI_ADD_LIST_SUPPORT
82 
83 
84 /********************************************************************************************************************
85  * Function          : __ini_write
86  * Parameters        : ini - pointer to ini file database.  heading - heading name.  key - key name.
87  * Returns           : Pointer to new key.
88  * Globals Used      :
89  * Globals Modified  :
90  * Description       : Make calls to add a new key and appends a description of changes in the backup file
91  ********************************************************************************************************************
92  *  Rev   |   Date   |  By   | Comment
93  * ----------------------------------------------------------------------------------------------------------------
94  ********************************************************************************************************************/
__ini_write(ini_t * ini)95 static struct key_tag *__ini_write (ini_t *ini)
96 {
97     struct section_tag *section;
98     struct key_tag     *key;
99 
100     // Is file read only?
101     if (ini->mode == INI_READ)
102         return NULL;
103 
104     // Check to make sure a section/key has
105     // been asked for by the user
106     section = ini->selected;
107     if (!section)
108         return NULL;
109     key = section->selected;
110     if (!key)
111         return NULL;
112 
113     // Add or replace key
114     if (!__ini_addHeading (ini, section->heading))
115         return NULL;
116     return __ini_addKey (ini, key->key);
117 }
118 
119 
120 /********************************************************************************************************************
121  * Function          : ini_readString
122  * Parameters        : ini - pointer to ini file database.
123  *                   : value - keys data
124  * Returns           : -1 for error or the number of chars read.
125  * Globals Used      :
126  * Globals Modified  :
127  * Description       : Reads data part from a key and returns it as a string
128  ********************************************************************************************************************
129  *  Rev   |   Date   |  By   | Comment
130  * ----------------------------------------------------------------------------------------------------------------
131  ********************************************************************************************************************/
ini_readString(ini_fd_t fd,char * str,size_t size)132 int INI_LINKAGE ini_readString (ini_fd_t fd, char *str, size_t size)
133 {
134     ini_t *ini = (ini_t *) fd;
135 
136     // Check size and reserve space for NULL
137     if (size-- <= 0)
138         return -1;
139 
140 #ifdef INI_ADD_LIST_SUPPORT
141     if (ini->listDelims)
142     {
143         char  *data = __ini_readList (ini);
144         if (!data)
145             return -1;
146 		strncpy (str, data, size);
147     }
148     else
149 #endif // INI_ADD_LIST_SUPPORT
150     {   // Locate and read back keys data (Index ignored)
151         // Check to make sure size is correct
152         size_t length;
153         if (__ini_read (ini, &length) < 0)
154             return -1;
155         if (size > length)
156             size = length;
157         size = fread (str, sizeof(char), size, ini->ftmp);
158     }
159 
160     str[size] = '\0';
161     __ini_strtrim (str);
162     return (int) size;
163 }
164 
165 
166 /********************************************************************************************************************
167  * Function          : ini_writeString
168  * Parameters        : ini - pointer to ini file database.
169  *                   : value - keys data
170  * Returns           : -1 for Error and 0 on success
171  * Globals Used      :
172  * Globals Modified  :
173  * Description       : Writes data part to a key.
174  *                   : Conforms to Microsoft API call.  E.g. use NULLS to remove headings/keys
175  *                   : Headings and keys will be created as necessary
176  ********************************************************************************************************************
177  *  Rev   |   Date   |  By   | Comment
178  * ----------------------------------------------------------------------------------------------------------------
179  ********************************************************************************************************************/
ini_writeString(ini_fd_t fd,const char * str)180 int INI_LINKAGE ini_writeString (ini_fd_t fd, const char *str)
181 {
182     ini_t *ini = (ini_t *) fd;
183     struct key_tag *_key;
184 
185     _key = __ini_write (ini);
186     if (!_key)
187         return -1;
188 
189     // Write data to bottom of backup file
190     _key->length = strlen (str);
191     fprintf (ini->ftmp, "%s\n", str);
192     return 0;
193 }
194 
195 
196 /********************************************************************************************************************
197  * Function          : ini_readInt
198  * Parameters        : ini - pointer to ini file database.
199  *                   : value - keys data
200  * Returns           : -1 for error or the number of values read.
201  * Globals Used      :
202  * Globals Modified  :
203  * Description       : Reads data part from a key and returns it as a int
204  ********************************************************************************************************************
205  *  Rev   |   Date   |  By   | Comment
206  * ----------------------------------------------------------------------------------------------------------------
207  ********************************************************************************************************************/
ini_readInt(ini_fd_t fd,int * value)208 int INI_LINKAGE ini_readInt (ini_fd_t fd, int *value)
209 {
210     ini_t *ini = (ini_t *) fd;
211 
212 #ifdef INI_ADD_LIST_SUPPORT
213     if (ini->listDelims)
214     {
215         char *data = __ini_readList (ini);
216         if (!data)
217             return -1;
218         sscanf (data, "%d", value);
219     }
220     else
221 #endif // INI_ADD_LIST_SUPPORT
222     {
223         size_t length;
224         if (__ini_read (ini, &length) < 0)
225             return -1;
226         if (length > 0)
227             fscanf (ini->ftmp, "%d", value);
228     }
229     return 0;
230 }
231 
232 
233 #ifdef INI_ADD_EXTRAS
234 
235 /********************************************************************************************************************
236  * Function          : ini_readLong
237  * Parameters        : ini - pointer to ini file database.
238  *                   : value - keys data
239  * Returns           : -1 for error or the number of values read.
240  * Globals Used      :
241  * Globals Modified  :
242  * Description       : Reads data part from a key and returns it as a long
243  ********************************************************************************************************************
244  *  Rev   |   Date   |  By   | Comment
245  * ----------------------------------------------------------------------------------------------------------------
246  ********************************************************************************************************************/
ini_readLong(ini_fd_t fd,long * value)247 int INI_LINKAGE ini_readLong (ini_fd_t fd, long *value)
248 {
249     ini_t *ini = (ini_t *) fd;
250 
251 #ifdef INI_ADD_LIST_SUPPORT
252     if (ini->listDelims)
253     {
254         char *data = __ini_readList (ini);
255         if (!data)
256             return -1;
257         sscanf (data, "%ld", value);
258     }
259     else
260 #endif // INI_ADD_LIST_SUPPORT
261     {
262         size_t length;
263         if (__ini_read (ini, &length) < 0)
264             return -1;
265         if (length > 0)
266             fscanf (ini->ftmp, "%ld", value);
267     }
268     return 0;
269 }
270 
271 
272 /********************************************************************************************************************
273  * Function          : ini_readDouble
274  * Parameters        : ini - pointer to ini file database.
275  *                   : value - keys data
276  * Returns           : -1 for error or the number of values read.
277  * Globals Used      :
278  * Globals Modified  :
279  * Description       : Reads data part from a key and returns it as a double (real)
280  ********************************************************************************************************************
281  *  Rev   |   Date   |  By   | Comment
282  * ----------------------------------------------------------------------------------------------------------------
283  ********************************************************************************************************************/
ini_readDouble(ini_fd_t fd,double * value)284 int INI_LINKAGE ini_readDouble (ini_fd_t fd, double *value)
285 {
286     ini_t *ini = (ini_t *) fd;
287 
288 #ifdef INI_ADD_LIST_SUPPORT
289     if (ini->listDelims)
290     {
291         char *data = __ini_readList (ini);
292         if (!data)
293             return -1;
294         sscanf (data, "%lf", value);
295     }
296     else
297 #endif // INI_ADD_LIST_SUPPORT
298     {
299         size_t length;
300         if (__ini_read (ini, &length) < 0)
301             return -1;
302         if (length > 0)
303             fscanf (ini->ftmp, "%lf", value);
304     }
305     return 0;
306 }
307 
308 
309 /********************************************************************************************************************
310  * Function          : ini_readBool
311  * Parameters        : ini - pointer to ini file database.
312  *                   : value - keys data
313  * Returns           : -1 for error or the number of values read.
314  * Globals Used      :
315  * Globals Modified  :
316  * Description       : Reads data part from a key and returns it as a int.  Supported bool strings are 0, 1, true
317  *                   : false.
318  ********************************************************************************************************************
319  *  Rev   |   Date   |  By   | Comment
320  * ----------------------------------------------------------------------------------------------------------------
321  ********************************************************************************************************************/
ini_readBool(ini_fd_t fd,int * value)322 int INI_LINKAGE ini_readBool (ini_fd_t fd, int *value)
323 {
324     ini_t *ini = (ini_t *) fd;
325     char   buffer[6] = "";
326 
327 #ifdef INI_ADD_LIST_SUPPORT
328     if (ini->listDelims)
329     {
330         char *data = __ini_readList (ini);
331         if (!data)
332             return -1;
333         sscanf (data, "%5s", buffer);
334     }
335     else
336 #endif // INI_ADD_LIST_SUPPORT
337     {
338         size_t length;
339         if (__ini_read (ini, &length) < 0)
340             return -1;
341         if (length > 0)
342             fscanf (ini->ftmp, "%5s", buffer);
343     }
344 
345     {   // Convert string to lower case
346         char *p = buffer;
347         while (*p != '\0')
348         {
349             *p = (char) tolower (*p);
350             p++;
351         }
352     }
353 
354     // Decode supported bool types
355     switch (*buffer)
356     {
357     case '0':
358     case '1':
359         if (buffer[1] != '\0')
360             return -1;
361         *value = *buffer - '0';
362         break;
363     case 't':
364         if (strcmp (buffer, "true"))
365             return -1;
366         *value = 1;
367         break;
368     case 'f':
369         if (strcmp (buffer, "false"))
370             return -1;
371         *value = 0;
372         break;
373     default:
374         // No match
375         return -1;
376     }
377     return 0;
378 }
379 
380 
381 /********************************************************************************************************************
382  * Function          : ini_writeInt
383  * Parameters        : ini - pointer to ini file database.
384  *                   : value - keys data
385  * Returns           : -1 for Error and 0 on success
386  * Globals Used      :
387  * Globals Modified  :
388  * Description       : Writes data part to a key.
389  *                   : Headings and keys will be created as necessary
390  ********************************************************************************************************************
391  *  Rev   |   Date   |  By   | Comment
392  * ----------------------------------------------------------------------------------------------------------------
393  ********************************************************************************************************************/
ini_writeInt(ini_fd_t fd,int value)394 int INI_LINKAGE ini_writeInt (ini_fd_t fd, int value)
395 {
396     ini_t *ini = (ini_t *) fd;
397     struct key_tag *_key;
398     long   pos;
399 
400     _key = __ini_write (ini);
401     if (!_key)
402         return -1;
403 
404     // Write data to bottom of backup file
405     fprintf (ini->ftmp, "%d", value);
406     pos = ftell (ini->ftmp);
407     _key->length = (size_t) (pos - _key->pos);
408     fprintf (ini->ftmp, "\n");
409     return 0;
410 }
411 
412 
413 /********************************************************************************************************************
414  * Function          : ini_writeLong
415  * Parameters        : ini - pointer to ini file database.
416  *                   : value - keys data
417  * Returns           : -1 for Error and 0 on success
418  * Globals Used      :
419  * Globals Modified  :
420  * Description       : Writes data part to a key.
421  *                   : Headings and keys will be created as necessary
422  ********************************************************************************************************************
423  *  Rev   |   Date   |  By   | Comment
424  * ----------------------------------------------------------------------------------------------------------------
425  ********************************************************************************************************************/
ini_writeLong(ini_fd_t fd,long value)426 int INI_LINKAGE ini_writeLong (ini_fd_t fd, long value)
427 {
428     ini_t *ini = (ini_t *) fd;
429     struct key_tag *_key;
430     long   pos;
431 
432     _key = __ini_write (ini);
433     if (!_key)
434         return -1;
435 
436     // Write data to bottom of backup file
437     fprintf (ini->ftmp, "%ld", value);
438     pos = ftell (ini->ftmp);
439     _key->length = (size_t) (pos - _key->pos);
440     fprintf (ini->ftmp, "\n");
441     return 0;
442 }
443 
444 
445 /********************************************************************************************************************
446  * Function          : ini_writeDouble
447  * Parameters        : ini - pointer to ini file database.
448  *                   : value - keys data
449  * Returns           : -1 for Error and 0 on success
450  * Globals Used      :
451  * Globals Modified  :
452  * Description       : Writes data part to a key.
453  *                   : Headings and keys will be created as necessary
454  ********************************************************************************************************************
455  *  Rev   |   Date   |  By   | Comment
456  * ----------------------------------------------------------------------------------------------------------------
457  ********************************************************************************************************************/
ini_writeDouble(ini_fd_t fd,double value)458 int INI_LINKAGE ini_writeDouble (ini_fd_t fd, double value)
459 {
460     ini_t *ini = (ini_t *) fd;
461     struct key_tag *_key;
462     long   pos;
463 
464     _key = __ini_write (ini);
465     if (!_key)
466         return -1;
467 
468     // Write data to bottom of backup file
469     fprintf (ini->ftmp, "%f", value);
470     pos = ftell (ini->ftmp);
471     _key->length = (size_t) (pos - _key->pos);
472     fprintf (ini->ftmp, "\n");
473     return 0;
474 }
475 
476 
477 /********************************************************************************************************************
478  * Function          : ini_writeBool
479  * Parameters        : ini - pointer to ini file database.
480  *                   : value - keys data
481  * Returns           : -1 for Error and 0 on success
482  * Globals Used      :
483  * Globals Modified  :
484  * Description       : Writes data part to a key.
485  *                   : Headings and keys will be created as necessary
486  ********************************************************************************************************************
487  *  Rev   |   Date   |  By   | Comment
488  * ----------------------------------------------------------------------------------------------------------------
489  ********************************************************************************************************************/
ini_writeBool(ini_fd_t fd,int value)490 int INI_LINKAGE ini_writeBool (ini_fd_t fd, int value)
491 {
492     ini_t *ini = (ini_t *) fd;
493     struct key_tag *_key;
494     long   pos;
495 
496     // Check if value is legal
497     if ((value < 0) || (value > 1))
498         return -1;
499 
500     _key = __ini_write (ini);
501     if (!_key)
502         return -1;
503 
504     // Write data to bottom of backup file
505     if (value)
506         fprintf (ini->ftmp, "true");
507     else
508         fprintf (ini->ftmp, "false");
509     pos = ftell (ini->ftmp);
510     _key->length = (size_t) (pos - _key->pos);
511     fprintf (ini->ftmp, "\n");
512     return 0;
513 }
514 
515 #endif // INI_ADD_EXTRAS
516