3
3
* These routines are in part based on the article "Multiplatform .INI Files"
4
4
* by Joseph J. Graf in the March 1994 issue of Dr. Dobb's Journal.
5
5
*
6
- * Copyright (c) CompuPhase, 2008-2015
6
+ * Copyright (c) CompuPhase, 2008-2017
7
7
*
8
8
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
9
9
* use this file except in compliance with the License. You may obtain a copy
@@ -103,9 +103,8 @@ enum quote_option {
103
103
#if defined PORTABLE_STRNICMP
104
104
int strnicmp (const TCHAR * s1 , const TCHAR * s2 , size_t n )
105
105
{
106
- register int c1 , c2 ;
107
-
108
106
while (n -- != 0 && (* s1 || * s2 )) {
107
+ register int c1 , c2 ;
109
108
c1 = * s1 ++ ;
110
109
if ('a' <= c1 && c1 <= 'z' )
111
110
c1 += ('A' - 'a' );
@@ -144,12 +143,13 @@ static TCHAR *striptrailing(TCHAR *str)
144
143
return str ;
145
144
}
146
145
147
- static TCHAR * save_strncpy (TCHAR * dest , const TCHAR * source , size_t maxlen , enum quote_option option )
146
+ static TCHAR * ini_strncpy (TCHAR * dest , const TCHAR * source , size_t maxlen , enum quote_option option )
148
147
{
149
148
size_t d , s ;
150
149
151
150
assert (maxlen > 0 );
152
- assert (dest <= source || dest >= source + maxlen );
151
+ assert (source != NULL && dest != NULL );
152
+ assert ((dest < source || (dest == source && option != QUOTE_ENQUOTE )) || dest > source + strlen (source ));
153
153
if (option == QUOTE_ENQUOTE && maxlen < 3 )
154
154
option = QUOTE_NONE ; /* cannot store two quotes and a terminating zero in less than 3 characters */
155
155
@@ -234,23 +234,25 @@ static int getkeystring(INI_FILETYPE *fp, const TCHAR *Section, const TCHAR *Key
234
234
assert (fp != NULL );
235
235
/* Move through file 1 line at a time until a section is matched or EOF. If
236
236
* parameter Section is NULL, only look at keys above the first section. If
237
- * idxSection is positive , copy the relevant section name.
237
+ * idxSection is postive , copy the relevant section name.
238
238
*/
239
239
len = (Section != NULL ) ? (int )_tcslen (Section ) : 0 ;
240
240
if (len > 0 || idxSection >= 0 ) {
241
+ assert (idxSection >= 0 || Section != NULL );
241
242
idx = -1 ;
242
243
do {
243
244
if (!ini_read (LocalBuffer , INI_BUFFERSIZE , fp ))
244
245
return 0 ;
245
246
sp = skipleading (LocalBuffer );
246
- ep = _tcschr (sp , ']' );
247
- } while (* sp != '[' || ep == NULL || (((int )(ep - sp - 1 ) != len || _tcsnicmp (sp + 1 ,Section ,len ) != 0 ) && ++ idx != idxSection ));
247
+ ep = _tcsrchr (sp , ']' );
248
+ } while (* sp != '[' || ep == NULL ||
249
+ (((int )(ep - sp - 1 ) != len || Section == NULL || _tcsnicmp (sp + 1 ,Section ,len ) != 0 ) && ++ idx != idxSection ));
248
250
if (idxSection >= 0 ) {
249
251
if (idx == idxSection ) {
250
252
assert (ep != NULL );
251
253
assert (* ep == ']' );
252
254
* ep = '\0' ;
253
- save_strncpy (Buffer , sp + 1 , BufferSize , QUOTE_NONE );
255
+ ini_strncpy (Buffer , sp + 1 , BufferSize , QUOTE_NONE );
254
256
return 1 ;
255
257
} /* if */
256
258
return 0 ; /* no more section found */
@@ -280,7 +282,7 @@ static int getkeystring(INI_FILETYPE *fp, const TCHAR *Section, const TCHAR *Key
280
282
assert (* ep == '=' || * ep == ':' );
281
283
* ep = '\0' ;
282
284
striptrailing (sp );
283
- save_strncpy (Buffer , sp , BufferSize , QUOTE_NONE );
285
+ ini_strncpy (Buffer , sp , BufferSize , QUOTE_NONE );
284
286
return 1 ;
285
287
} /* if */
286
288
return 0 ; /* no more key found (in this section) */
@@ -291,7 +293,7 @@ static int getkeystring(INI_FILETYPE *fp, const TCHAR *Section, const TCHAR *Key
291
293
assert (* ep == '=' || * ep == ':' );
292
294
sp = skipleading (ep + 1 );
293
295
sp = cleanstring (sp , & quotes ); /* Remove a trailing comment */
294
- save_strncpy (Buffer , sp , BufferSize , quotes );
296
+ ini_strncpy (Buffer , sp , BufferSize , quotes );
295
297
return 1 ;
296
298
}
297
299
@@ -318,7 +320,7 @@ int ini_gets(const TCHAR *Section, const TCHAR *Key, const TCHAR *DefValue,
318
320
(void )ini_close (& fp );
319
321
} /* if */
320
322
if (!ok )
321
- save_strncpy (Buffer , (DefValue != NULL ) ? DefValue : __T ("" ), BufferSize , QUOTE_NONE );
323
+ ini_strncpy (Buffer , (DefValue != NULL ) ? DefValue : __T ("" ), BufferSize , QUOTE_NONE );
322
324
return (int )_tcslen (Buffer );
323
325
}
324
326
@@ -447,7 +449,7 @@ int ini_getkey(const TCHAR *Section, int idx, TCHAR *Buffer, int BufferSize, co
447
449
/** ini_browse()
448
450
* \param Callback a pointer to a function that will be called for every
449
451
* setting in the INI file.
450
- * \param UserData arbitrary data, which the function passes on the
452
+ * \param UserData arbitrary data, which the function passes on the the
451
453
* \c Callback function
452
454
* \param Filename the name and full path of the .ini file to read from
453
455
*
@@ -458,7 +460,7 @@ int ini_getkey(const TCHAR *Section, int idx, TCHAR *Buffer, int BufferSize, co
458
460
* callback stops the browsing, this function will return 1
459
461
* (for success).
460
462
*/
461
- int ini_browse (INI_CALLBACK Callback , const void * UserData , const TCHAR * Filename )
463
+ int ini_browse (INI_CALLBACK Callback , void * UserData , const TCHAR * Filename )
462
464
{
463
465
TCHAR LocalBuffer [INI_BUFFERSIZE ];
464
466
int lenSec , lenKey ;
@@ -481,10 +483,10 @@ int ini_browse(INI_CALLBACK Callback, const void *UserData, const TCHAR *Filena
481
483
if (* sp == '\0' || * sp == ';' || * sp == '#' )
482
484
continue ;
483
485
/* see whether we reached a new section */
484
- ep = _tcschr (sp , ']' );
486
+ ep = _tcsrchr (sp , ']' );
485
487
if (* sp == '[' && ep != NULL ) {
486
488
* ep = '\0' ;
487
- save_strncpy (LocalBuffer , sp + 1 , INI_BUFFERSIZE , QUOTE_NONE );
489
+ ini_strncpy (LocalBuffer , sp + 1 , INI_BUFFERSIZE , QUOTE_NONE );
488
490
lenSec = (int )_tcslen (LocalBuffer ) + 1 ;
489
491
continue ;
490
492
} /* if */
@@ -496,12 +498,12 @@ int ini_browse(INI_CALLBACK Callback, const void *UserData, const TCHAR *Filena
496
498
continue ; /* invalid line, ignore */
497
499
* ep ++ = '\0' ; /* split the key from the value */
498
500
striptrailing (sp );
499
- save_strncpy (LocalBuffer + lenSec , sp , INI_BUFFERSIZE - lenSec , QUOTE_NONE );
501
+ ini_strncpy (LocalBuffer + lenSec , sp , INI_BUFFERSIZE - lenSec , QUOTE_NONE );
500
502
lenKey = (int )_tcslen (LocalBuffer + lenSec ) + 1 ;
501
503
/* clean up the value */
502
504
sp = skipleading (ep );
503
505
sp = cleanstring (sp , & quotes ); /* Remove a trailing comment */
504
- save_strncpy (LocalBuffer + lenSec + lenKey , sp , INI_BUFFERSIZE - lenSec - lenKey , quotes );
506
+ ini_strncpy (LocalBuffer + lenSec + lenKey , sp , INI_BUFFERSIZE - lenSec - lenKey , quotes );
505
507
/* call the callback */
506
508
if (!Callback (LocalBuffer , LocalBuffer + lenSec , LocalBuffer + lenSec + lenKey , UserData ))
507
509
break ;
@@ -517,7 +519,7 @@ static void ini_tempname(TCHAR *dest, const TCHAR *source, int maxlength)
517
519
{
518
520
TCHAR * p ;
519
521
520
- save_strncpy (dest , source , maxlength , QUOTE_NONE );
522
+ ini_strncpy (dest , source , maxlength , QUOTE_NONE );
521
523
p = _tcsrchr (dest , '\0' );
522
524
assert (p != NULL );
523
525
* (p - 1 ) = '~' ;
@@ -541,7 +543,7 @@ static void writesection(TCHAR *LocalBuffer, const TCHAR *Section, INI_FILETYPE
541
543
if (Section != NULL && _tcslen (Section ) > 0 ) {
542
544
TCHAR * p ;
543
545
LocalBuffer [0 ] = '[' ;
544
- save_strncpy (LocalBuffer + 1 , Section , INI_BUFFERSIZE - 4 , QUOTE_NONE ); /* -1 for '[', -1 for ']', -2 for '\r\n' */
546
+ ini_strncpy (LocalBuffer + 1 , Section , INI_BUFFERSIZE - 4 , QUOTE_NONE ); /* -1 for '[', -1 for ']', -2 for '\r\n' */
545
547
p = _tcsrchr (LocalBuffer , '\0' );
546
548
assert (p != NULL );
547
549
* p ++ = ']' ;
@@ -555,11 +557,11 @@ static void writekey(TCHAR *LocalBuffer, const TCHAR *Key, const TCHAR *Value, I
555
557
{
556
558
TCHAR * p ;
557
559
enum quote_option option = check_enquote (Value );
558
- save_strncpy (LocalBuffer , Key , INI_BUFFERSIZE - 3 , QUOTE_NONE ); /* -1 for '=', -2 for '\r\n' */
560
+ ini_strncpy (LocalBuffer , Key , INI_BUFFERSIZE - 3 , QUOTE_NONE ); /* -1 for '=', -2 for '\r\n' */
559
561
p = _tcsrchr (LocalBuffer , '\0' );
560
562
assert (p != NULL );
561
563
* p ++ = '=' ;
562
- save_strncpy (p , Value , INI_BUFFERSIZE - (p - LocalBuffer ) - 2 , option ); /* -2 for '\r\n' */
564
+ ini_strncpy (p , Value , INI_BUFFERSIZE - (p - LocalBuffer ) - 2 , option ); /* -2 for '\r\n' */
563
565
p = _tcsrchr (LocalBuffer , '\0' );
564
566
assert (p != NULL );
565
567
_tcscpy (p , INI_LINETERM ); /* copy line terminator (typically "\n") */
@@ -697,7 +699,7 @@ int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const T
697
699
(void )ini_close (& rfp );
698
700
return 0 ;
699
701
} /* if */
700
- ini_tell (& rfp , & mark );
702
+ ( void ) ini_tell (& rfp , & mark );
701
703
cachelen = 0 ;
702
704
703
705
/* Move through the file one line at a time until a section is
@@ -721,7 +723,7 @@ int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const T
721
723
* we are looking for and this section must be removed
722
724
*/
723
725
sp = skipleading (LocalBuffer );
724
- ep = _tcschr (sp , ']' );
726
+ ep = _tcsrchr (sp , ']' );
725
727
match = (* sp == '[' && ep != NULL && (int )(ep - sp - 1 ) == len && _tcsnicmp (sp + 1 ,Section ,len ) == 0 );
726
728
if (!match || Key != NULL ) {
727
729
if (!cache_accum (LocalBuffer , & cachelen , INI_BUFFERSIZE )) {
@@ -740,7 +742,7 @@ int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const T
740
742
*/
741
743
if (Key == NULL ) {
742
744
(void )ini_read (LocalBuffer , INI_BUFFERSIZE , & rfp );
743
- ini_tell (& rfp , & mark );
745
+ ( void ) ini_tell (& rfp , & mark );
744
746
} /* if */
745
747
746
748
/* Now that the section has been found, find the entry. Stop searching
@@ -768,7 +770,7 @@ int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const T
768
770
break ; /* found the key, or found a new section */
769
771
/* copy other keys in the section */
770
772
if (Key == NULL ) {
771
- ini_tell (& rfp , & mark ); /* we are deleting the entire section, so update the read position */
773
+ ( void ) ini_tell (& rfp , & mark ); /* we are deleting the entire section, so update the read position */
772
774
} else {
773
775
if (!cache_accum (LocalBuffer , & cachelen , INI_BUFFERSIZE )) {
774
776
cache_flush (LocalBuffer , & cachelen , & rfp , & wfp , & mark );
@@ -796,7 +798,7 @@ int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const T
796
798
cache_accum (LocalBuffer , & cachelen , INI_BUFFERSIZE );
797
799
} else {
798
800
/* forget the old key line */
799
- ini_tell (& rfp , & mark );
801
+ ( void ) ini_tell (& rfp , & mark );
800
802
} /* if */
801
803
/* Copy the rest of the INI file */
802
804
while (ini_read (LocalBuffer , INI_BUFFERSIZE , & rfp )) {
@@ -827,11 +829,10 @@ static void long2str(long value, TCHAR *str)
827
829
{
828
830
int i = 0 ;
829
831
long sign = value ;
830
- int n ;
831
832
832
833
/* generate digits in reverse order */
833
834
do {
834
- n = (int )(value % 10 ); /* get next lowest digit */
835
+ int n = (int )(value % 10 ); /* get next lowest digit */
835
836
str [i ++ ] = (TCHAR )(ABS (n ) + '0' ); /* handle case of negative digit */
836
837
} while (value /= 10 ); /* delete the lowest digit */
837
838
if (sign < 0 )
0 commit comments