ini_file.c 20.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/* ini_file.c */

/* Functions to parse ini files */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
11
 * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 *																			*
 * This library is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU Lesser General Public License		*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU Lesser General Public License for more details: lgpl.txt or	*
 * http://www.fsf.org/copyleft/lesser.html									*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include <stdlib.h>		/* strtol */
rob's avatar
rob committed
39
40
#include <string.h>		/* strlen */
#include <ctype.h>		/* isdigit */
41
42
43
#if !defined(NO_SOCKET_SUPPORT)
	#include "sockwrap.h"	/* inet_addr */
#endif
44
#include "dirwrap.h"	/* fexist */
rswindell's avatar
rswindell committed
45
#include "filewrap.h"	/* chsize */
46
47
#include "ini_file.h"

48
/* Maximum length of entire line, includes '\0' */
49
50
51
52
53
#define INI_MAX_LINE_LEN		(INI_MAX_VALUE_LEN*2)
#define INI_COMMENT_CHAR		';'
#define INI_OPEN_SECTION_CHAR	'['
#define INI_CLOSE_SECTION_CHAR	']'
#define INI_NEW_SECTION			((char*)~0)
54

55
56
static ini_style_t default_style;

57
58
59
60
61
static char* section_name(char* p)
{
	char*	tp;

	SKIP_WHITESPACE(p);
62
	if(*p!=INI_OPEN_SECTION_CHAR)
63
64
65
		return(NULL);
	p++;
	SKIP_WHITESPACE(p);
66
	tp=strrchr(p,INI_CLOSE_SECTION_CHAR);
67
68
69
70
71
72
73
74
	if(tp==NULL)
		return(NULL);
	*tp=0;
	truncsp(p);

	return(p);
}

75
static BOOL seek_section(FILE* fp, const char* section)
76
77
{
	char*	p;
78
	char	str[INI_MAX_LINE_LEN];
79
80
81

	rewind(fp);

rswindell's avatar
rswindell committed
82
	if(section==ROOT_SECTION)
83
84
		return(TRUE);

85
	while(!feof(fp)) {
86
		if(fgets(str,sizeof(str),fp)==NULL)
87
			break;
88
		if((p=section_name(str))==NULL)
89
			continue;
rswindell's avatar
rswindell committed
90
91
		if(stricmp(p,section)==0)
			return(TRUE);
92
93
94
95
	}
	return(FALSE);
}

96
97
98
99
100
101
102
103
104
static size_t find_section_index(str_list_t list, const char* section)
{
	char*	p;
	char	str[INI_MAX_VALUE_LEN];
	size_t	i;

	for(i=0; list[i]!=NULL; i++) {
		SAFECOPY(str,list[i]);
		if((p=section_name(str))!=NULL && stricmp(p,section)==0)
105
			return(i);
106
107
108
109
110
	}

	return(i);
}

111
static size_t find_section(str_list_t list, const char* section)
112
113
114
115
116
117
118
119
120
121
122
123
{
	size_t	i;

	if(section==ROOT_SECTION)
		return(0);

	i=find_section_index(list,section);
	if(list[i]!=NULL)
		i++;
	return(i);
}

124
125
static char* key_name(char* p, char** vp)
{
126
127
128
	char* equal;
	char* colon;

129
130
    *vp=NULL;
    
131
132
133
	if(p==NULL)
		return(NULL);

134
135
	/* Parse value name */
	SKIP_WHITESPACE(p);
136
	if(*p==INI_COMMENT_CHAR)
137
		return(NULL);
138
139
140
141
142
143
144
145
146
147
	if(*p==INI_OPEN_SECTION_CHAR)
		return(INI_NEW_SECTION);
	equal=strchr(p,'=');
	colon=strchr(p,':');
	if(colon==NULL || (equal!=NULL && equal<colon)) {
		*vp=equal;
		colon=NULL;
	} else
		*vp=colon;

148
149
	if(*vp==NULL)
		return(NULL);
150

151
152
153
154
155
156
	*(*vp)=0;
	truncsp(p);

	/* Parse value */
	(*vp)++;
	SKIP_WHITESPACE(*vp);
157
158
159
160
	if(colon!=NULL)			
		truncnl(*vp);		/* "key : value" - truncate new-line chars only */
	else	
		truncsp(*vp);		/* "key = value" - truncate all white-space chars */
161
162
163
164

	return(p);
}

165
static char* read_value(FILE* fp, const char* section, const char* key, char* value)
166
167
{
	char*	p;
168
	char*	vp=NULL;
169
	char	str[INI_MAX_LINE_LEN];
170

171
172
173
	if(fp==NULL)
		return(NULL);

174
	if(!seek_section(fp,section))
175
176
177
		return(NULL);

	while(!feof(fp)) {
178
		if(fgets(str,sizeof(str),fp)==NULL)
179
			break;
180
		if((p=key_name(str,&vp))==NULL)
181
			continue;
182
		if(p==INI_NEW_SECTION)
183
184
185
			break;
		if(stricmp(p,key)!=0)
			continue;
186
187
		if(vp==NULL)
			break;
188
		/* key found */
189
		sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,vp);
190
191
192
193
194
195
		return(value);
	}

	return(NULL);
}

196
static size_t get_value(str_list_t list, const char* section, const char* key, char* value)
197
198
199
200
201
202
{
	char	str[INI_MAX_LINE_LEN];
	char*	p;
	char*	vp;
	size_t	i;

203
	value[0]=0;
204
	for(i=find_section(list, section); list[i]!=NULL; i++) {
205
206
207
		SAFECOPY(str, list[i]);
		if((p=key_name(str,&vp))==NULL)
			continue;
208
		if(p==INI_NEW_SECTION)
209
			break;
210
211
		if(stricmp(p,key)!=0)
			continue;
212
		sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,vp);
213
		return(i);
214
215
216
217
218
	}

	return(i);
}

rswindell's avatar
rswindell committed
219
220
221
222
223
224
225
226
227
228
229
BOOL iniSectionExists(str_list_t* list, const char* section)
{
	size_t	i;

	if(section==ROOT_SECTION)
		return(TRUE);

	i=find_section_index(*list,section);
	return((*list)[i]!=NULL);
}

230
231
232
233
234
BOOL iniKeyExists(str_list_t* list, const char* section, const char* key)
{
	char	val[INI_MAX_VALUE_LEN];
	size_t	i;

235
	i=get_value(*list, section, key, val);
236
237
238
239
240
241
242
243
244
245
246

	if((*list)[i]==NULL || *(*list)[i]==INI_OPEN_SECTION_CHAR)
		return(FALSE);

	return(TRUE);
}

BOOL iniValueExists(str_list_t* list, const char* section, const char* key)
{
	char	val[INI_MAX_VALUE_LEN];

247
	get_value(*list, section, key, val);
248
249
250
251
252
253
254
255
256

	return(val[0]!=0);
}

BOOL iniRemoveKey(str_list_t* list, const char* section, const char* key)
{
	char	val[INI_MAX_VALUE_LEN];
	size_t	i;

257
	i=get_value(*list, section, key, val);
258
259
260
261
262
263
264

	if((*list)[i]==NULL || *(*list)[i]==INI_OPEN_SECTION_CHAR)
		return(FALSE);

	return(strListDelete(list,i));
}

265
266
267
268
BOOL iniRemoveValue(str_list_t* list, const char* section, const char* key)
{
	char	val[INI_MAX_VALUE_LEN];
	size_t	i;
269
	char*	vp=NULL;
270

271
	i=get_value(*list, section, key, val);
272

273
274
    key_name((*list)[i], &vp);
	if(vp==NULL)
275
276
277
278
279
280
		return(FALSE);

	*vp=0;	/* Terminate string at beginning of value */
	return(TRUE);
}

rswindell's avatar
rswindell committed
281
282
283
284
285
286
287
288
289
290
291
292
293
294
BOOL iniRemoveSection(str_list_t* list, const char* section)
{
	size_t	i;

	i=find_section_index(*list,section);
	if((*list)[i]==NULL)	/* not found */
		return(FALSE);
	do {
		strListDelete(list,i);
	} while((*list)[i]!=NULL && *(*list)[i]!=INI_OPEN_SECTION_CHAR);

	return(TRUE);
}

rswindell's avatar
rswindell committed
295
296
297
298
299
300
301
302
BOOL iniRenameSection(str_list_t* list, const char* section, const char* newname)
{
	char	str[INI_MAX_LINE_LEN];
	size_t	i;

	if(section==ROOT_SECTION)
		return(FALSE);

303
304
305
306
	i=find_section_index(*list,newname);
	if((*list)[i]!=NULL)	/* duplicate */
		return(FALSE);

rswindell's avatar
rswindell committed
307
308
309
310
	i=find_section_index(*list,section);
	if((*list)[i]==NULL)	/* not found */
		return(FALSE);

311
	SAFEPRINTF(str,"[%s]",newname);
rswindell's avatar
rswindell committed
312
313
314
	return(strListReplace(*list, i, str)!=NULL);
}

315
316
size_t iniAddSection(str_list_t* list, const char* section
					,ini_style_t* style)
317
318
319
320
{
	char	str[INI_MAX_LINE_LEN];
	size_t	i;

rswindell's avatar
rswindell committed
321
	if(section==ROOT_SECTION)
322
323
		return(0);

324
325
	i=find_section_index(*list, section);
	if((*list)[i]==NULL) {
326
327
		if(style==NULL)
			style=&default_style;
328
329
		if(style->section_separator!=NULL)
			strListAppend(list, style->section_separator, i++);
330
		SAFEPRINTF(str,"[%s]",section);
331
332
333
334
335
336
337
338
339
340
		strListAppend(list, str, i);
	}

	return(i);
}

char* iniSetString(str_list_t* list, const char* section, const char* key, const char* value
				 ,ini_style_t* style)
{
	char	str[INI_MAX_LINE_LEN];
341
	char	curval[INI_MAX_VALUE_LEN];
342
343
	size_t	i;

344
345
346
347
	if(style==NULL)
		style=&default_style;

	iniAddSection(list, section, style);
348
349
350
351
352
353
354

	if(key==NULL)
		return(NULL);
	if(style->key_prefix==NULL)
		style->key_prefix="";
	if(style->value_separator==NULL)
		style->value_separator="=";
355
356
	if(value==NULL)
		value="";
357
358
	safe_snprintf(str, sizeof(str), "%s%-*s%s%s"
		, style->key_prefix, style->key_len, key, style->value_separator, value);
359
	i=get_value(*list, section, key, curval);
360
361
	if((*list)[i]==NULL || *(*list)[i]==INI_OPEN_SECTION_CHAR) {
        while(i && *(*list)[i-1]==0) i--;   /* Insert before blank lines, not after */
362
		return strListInsert(list, str, i);
363
    }
364

365
366
367
	if(strcmp(curval,value)==0)
		return((*list)[i]);	/* no change */

368
369
370
371
372
373
374
375
	return strListReplace(*list, i, str);
}

char* iniSetInteger(str_list_t* list, const char* section, const char* key, long value
					,ini_style_t* style)
{
	char	str[INI_MAX_VALUE_LEN];

376
	SAFEPRINTF(str,"%ld",value);
377
378
379
380
381
382
383
384
	return iniSetString(list, section, key, str, style);
}

char* iniSetShortInt(str_list_t* list, const char* section, const char* key, ushort value
					,ini_style_t* style)
{
	char	str[INI_MAX_VALUE_LEN];

385
	SAFEPRINTF(str,"%hu",value);
386
387
388
389
390
391
392
393
	return iniSetString(list, section, key, str, style);
}

char* iniSetHexInt(str_list_t* list, const char* section, const char* key, ulong value
					,ini_style_t* style)
{
	char	str[INI_MAX_VALUE_LEN];

394
	SAFEPRINTF(str,"0x%lx",value);
395
396
397
398
399
400
401
402
	return iniSetString(list, section, key, str, style);
}

char* iniSetFloat(str_list_t* list, const char* section, const char* key, double value
					,ini_style_t* style)
{
	char	str[INI_MAX_VALUE_LEN];

403
	SAFEPRINTF(str,"%g",value);
404
405
406
	return iniSetString(list, section, key, str, style);
}

407
#if !defined(NO_SOCKET_SUPPORT)
408
409
410
411
char* iniSetIpAddress(str_list_t* list, const char* section, const char* key, ulong value
					,ini_style_t* style)
{
	struct in_addr in_addr;
412
	in_addr.s_addr=htonl(value);
413
414
	return iniSetString(list, section, key, inet_ntoa(in_addr), style);
}
415
#endif
416
417
418
419
420
421
422

char* iniSetBool(str_list_t* list, const char* section, const char* key, BOOL value
					,ini_style_t* style)
{
	return iniSetString(list, section, key, value ? "true":"false", style);
}

423
424
char* iniSetBitField(str_list_t* list, const char* section, const char* key
					 ,ini_bitdesc_t* bitdesc, ulong value, ini_style_t* style)
425
426
427
428
{
	char	str[INI_MAX_VALUE_LEN];
	int		i;

429
430
	if(style==NULL)
		style=&default_style;
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
	if(style->bit_separator==NULL)
		style->bit_separator="|";
	str[0]=0;
	for(i=0;bitdesc[i].name;i++) {
		if((value&bitdesc[i].bit)==0)
			continue;
		if(str[0])
			strcat(str,style->bit_separator);
		strcat(str,bitdesc[i].name);
		value&=~bitdesc[i].bit;
	}
	if(value) {	/* left over bits? */
		if(str[0])
			strcat(str,style->bit_separator);
		sprintf(str+strlen(str), "0x%lX", value);
	}
	return iniSetString(list, section, key, str, style);
}

450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
char* iniSetStringList(str_list_t* list, const char* section, const char* key
					,const char* sep, str_list_t val_list, ini_style_t* style)
{
	char	value[INI_MAX_VALUE_LEN];
	size_t	i;

	value[0]=0;

	if(sep==NULL)
		sep=",";

	if(val_list!=NULL)
		for(i=0; val_list[i]!=NULL; i++) {
			if(value[0])
				strcat(value,sep);
			strcat(value,val_list[i]);
		}

	return iniSetString(list, section, key, value, style);
}

471
char* iniReadString(FILE* fp, const char* section, const char* key, const char* deflt, char* value)
472
{
473
	if(read_value(fp,section,key,value)==NULL || *value==0 /* blank */) {
474
475
476
477
		if(deflt==NULL)
			return(NULL);
		sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,deflt);
	}
478

479
480
481
	return(value);
}

482
char* iniGetString(str_list_t* list, const char* section, const char* key, const char* deflt, char* value)
483
{
484
	get_value(*list, section, key, value);
485

486
487
488
489
490
	if(*value==0 /* blank */) {
		if(deflt==NULL)
			return(NULL);
		sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,deflt);
	}
491

492
493
494
495
496
497
498
499
	return(value);
}

static str_list_t splitList(char* list, const char* sep)
{
	char*		token;
	ulong		items=0;
	str_list_t	lp;
500

501
	if((lp=strListInit())==NULL)
502
503
		return(NULL);

504
505
506
	if(sep==NULL)
		sep=",";

507
508
509
	token=strtok(list,sep);
	while(token!=NULL) {
		truncsp(token);
510
		if(strListAppend(&lp,token,items++)==NULL)
511
512
513
			break;
		token=strtok(NULL,sep);
	}
514

515
516
517
	return(lp);
}

518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
str_list_t iniReadStringList(FILE* fp, const char* section, const char* key
						 ,const char* sep, const char* deflt)
{
	char*	value;
	char	buf[INI_MAX_VALUE_LEN];
	char	list[INI_MAX_VALUE_LEN];

	if((value=read_value(fp,section,key,buf))==NULL || *value==0 /* blank */)
		value=(char*)deflt;

	SAFECOPY(list,value);

	return(splitList(list,sep));
}

str_list_t iniGetStringList(str_list_t* list, const char* section, const char* key
						 ,const char* sep, const char* deflt)
{
	char	buf[INI_MAX_VALUE_LEN];
	char*	value=buf;

	get_value(*list, section, key, value);

	if(*value==0 /* blank */)
		value=(char*)deflt;

	SAFECOPY(buf,value);

	return(splitList(buf,sep));
}

549
void* iniFreeStringList(str_list_t list)
550
{
551
552
	strListFree(&list);
	return(list);
553
}
554

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
void* iniFreeNamedStringList(named_string_t** list)
{
	ulong	i;

	if(list==NULL)
		return(NULL);

	for(i=0;list[i]!=NULL;i++) {
		if(list[i]->name!=NULL)
			free(list[i]->name);
		if(list[i]->value!=NULL)
			free(list[i]->value);
		free(list[i]);
	}

	free(list);
	return(NULL);
}

574
str_list_t iniReadSectionList(FILE* fp, const char* prefix)
575
576
{
	char*	p;
577
	char	str[INI_MAX_LINE_LEN];
578
	ulong	items=0;
579
	str_list_t	lp;
580

581
	if((lp=strListInit())==NULL)
582
583
584
585
586
587
588
589
590
591
		return(NULL);

	if(fp==NULL)
		return(lp);

	rewind(fp);

	while(!feof(fp)) {
		if(fgets(str,sizeof(str),fp)==NULL)
			break;
592
		if((p=section_name(str))==NULL)
593
			continue;
594
		if(prefix!=NULL)
595
596
			if(strnicmp(p,prefix,strlen(prefix))!=0)
				continue;
597
		if(strListAppend(&lp,p,items++)==NULL)
598
599
600
601
602
603
			break;
	}

	return(lp);
}

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
str_list_t iniGetSectionList(str_list_t* list, const char* prefix)
{
	char*	p;
	char	str[INI_MAX_LINE_LEN];
	ulong	i,items=0;
	str_list_t	lp;

	if((lp=strListInit())==NULL)
		return(NULL);

	if(list==NULL)
		return(lp);

	for(i=0;list[i];i++) {
		SAFECOPY(str,list[i]);
		if((p=section_name(str))==NULL)
			continue;
		if(prefix!=NULL)
			if(strnicmp(p,prefix,strlen(prefix))!=0)
				continue;
		if(strListAppend(&lp,p,items++)==NULL)
			break;
	}

	return(lp);
}

631
str_list_t iniReadKeyList(FILE* fp, const char* section)
632
633
{
	char*	p;
634
	char*	vp;
635
	char	str[INI_MAX_LINE_LEN];
636
	ulong	items=0;
637
	str_list_t	lp;
638

639
	if((lp=strListInit())==NULL)
640
641
642
643
644
645
646
		return(NULL);

	if(fp==NULL)
		return(lp);

	rewind(fp);

647
	if(!seek_section(fp,section))
648
649
650
651
652
		return(lp);

	while(!feof(fp)) {
		if(fgets(str,sizeof(str),fp)==NULL)
			break;
653
		if((p=key_name(str,&vp))==NULL)
654
			continue;
655
		if(p==INI_NEW_SECTION)
656
			break;
657
		if(strListAppend(&lp,p,items++)==NULL)
658
659
660
661
662
663
			break;
	}

	return(lp);
}

664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
str_list_t iniGetKeyList(str_list_t* list, const char* section)
{
	char*	p;
	char*	vp;
	char	str[INI_MAX_LINE_LEN];
	ulong	i,items=0;
	str_list_t	lp;

	if((lp=strListInit())==NULL)
		return(NULL);

	if(list==NULL)
		return(lp);

	for(i=find_section(*list,section);list[i]==NULL;i++) {
		SAFECOPY(str,list[i]);
		if((p=key_name(str,&vp))==NULL)
			continue;
		if(p==INI_NEW_SECTION)
			break;
		if(strListAppend(&lp,p,items++)==NULL)
			break;
	}

	return(lp);
}


692
named_string_t**
693
iniReadNamedStringList(FILE* fp, const char* section)
694
695
696
{
	char*	name;
	char*	value;
697
	char	str[INI_MAX_LINE_LEN];
698
699
700
701
	ulong	items=0;
	named_string_t** lp;
	named_string_t** np;

702
	if((lp=(named_string_t**)malloc(sizeof(named_string_t*)))==NULL)
703
704
705
706
707
708
709
710
711
		return(NULL);

	*lp=NULL;

	if(fp==NULL)
		return(lp);

	rewind(fp);

712
	if(!seek_section(fp,section))
713
714
715
716
717
		return(lp);

	while(!feof(fp)) {
		if(fgets(str,sizeof(str),fp)==NULL)
			break;
718
		if((name=key_name(str,&value))==NULL)
719
			continue;
720
		if(name==INI_NEW_SECTION)
721
			break;
722
		if((np=(named_string_t**)realloc(lp,sizeof(named_string_t*)*(items+2)))==NULL)
723
724
			break;
		lp=np;
725
		if((lp[items]=(named_string_t*)malloc(sizeof(named_string_t)))==NULL)
726
			break;
727
		if((lp[items]->name=strdup(name))==NULL)
728
			break;
729
		if((lp[items]->value=strdup(value))==NULL)
730
731
732
733
734
735
736
737
738
			break;
		items++;
	}

	lp[items]=NULL;	/* terminate list */

	return(lp);
}

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
named_string_t**
iniGetNamedStringList(str_list_t* list, const char* section)
{
	char*	name;
	char*	value;
	char	str[INI_MAX_LINE_LEN];
	ulong	i,items=0;
	named_string_t** lp;
	named_string_t** np;

	if((lp=(named_string_t**)malloc(sizeof(named_string_t*)))==NULL)
		return(NULL);

	*lp=NULL;

	if(list==NULL)
		return(lp);

	for(i=find_section(*list,section);list[i]!=NULL;i++) {
		SAFECOPY(str,list[i]);
		if((name=key_name(str,&value))==NULL)
			continue;
		if(name==INI_NEW_SECTION)
			break;
		if((np=(named_string_t**)realloc(lp,sizeof(named_string_t*)*(items+2)))==NULL)
			break;
		lp=np;
		if((lp[items]=(named_string_t*)malloc(sizeof(named_string_t)))==NULL)
			break;
		if((lp[items]->name=strdup(name))==NULL)
			break;
		if((lp[items]->value=strdup(value))==NULL)
			break;
		items++;
	}

	lp[items]=NULL;	/* terminate list */

	return(lp);
}


781
782
/* These functions read a single key of the specified type */

783
long iniReadInteger(FILE* fp, const char* section, const char* key, long deflt)
784
{
785
	char*	value;
786
	char	buf[INI_MAX_VALUE_LEN];
787

788
	if((value=read_value(fp,section,key,buf))==NULL)
789
790
		return(deflt);

791
792
793
	if(*value==0)		/* blank value */
		return(deflt);

794
795
796
	return(strtol(value,NULL,0));
}

797
798
799
800
801
802
803
804
805
806
807
808
long iniGetInteger(str_list_t* list, const char* section, const char* key, long deflt)
{
	char	value[INI_MAX_VALUE_LEN];

	get_value(*list, section, key, value);

	if(*value==0)		/* blank value */
		return(deflt);

	return(strtol(value,NULL,0));
}

809
ushort iniReadShortInt(FILE* fp, const char* section, const char* key, ushort deflt)
810
{
811
	return((ushort)iniReadInteger(fp, section, key, deflt));
812
813
}

814
815
816
817
818
ushort iniGetShortInt(str_list_t* list, const char* section, const char* key, ushort deflt)
{
	return((ushort)iniGetInteger(list, section, key, deflt));
}

819
#if !defined(NO_SOCKET_SUPPORT)
820
821
822
823
824
825
826
827
828

static ulong parseIpAddress(const char* value)
{
	if(strchr(value,'.')==NULL)
		return(strtol(value,NULL,0));

	return(ntohl(inet_addr(value)));
}

829
ulong iniReadIpAddress(FILE* fp, const char* section, const char* key, ulong deflt)
830
{
831
	char	buf[INI_MAX_VALUE_LEN];
832
	char*	value;
833

834
	if((value=read_value(fp,section,key,buf))==NULL)
835
836
		return(deflt);

837
838
839
	if(*value==0)		/* blank value */
		return(deflt);

840
841
	return(parseIpAddress(value));
}
842

843
844
845
846
847
848
849
850
851
852
ulong iniGetIpAddress(str_list_t* list, const char* section, const char* key, ulong deflt)
{
	char	value[INI_MAX_VALUE_LEN];

	get_value(*list, section, key, value);

	if(*value==0)		/* blank value */
		return(deflt);

	return(parseIpAddress(value));
853
}
854
855

#endif	/* !NO_SOCKET_SUPPORT */
856

857
double iniReadFloat(FILE* fp, const char* section, const char* key, double deflt)
858
{
859
	char	buf[INI_MAX_VALUE_LEN];
860
	char*	value;
861

862
	if((value=read_value(fp,section,key,buf))==NULL)
863
864
		return(deflt);

865
866
867
	if(*value==0)		/* blank value */
		return(deflt);

868
869
870
	return(atof(value));
}

871
double iniGetFloat(str_list_t* list, const char* section, const char* key, double deflt)
872
{
873
	char	value[INI_MAX_VALUE_LEN];
874

875
	get_value(*list, section, key, value);
876

877
878
879
	if(*value==0)		/* blank value */
		return(deflt);

880
881
882
883
884
	return(atof(value));
}

static BOOL parseBool(const char* value)
{
885
886
887
888
889
890
891
892
	if(!stricmp(value,"TRUE"))
		return(TRUE);
	if(!stricmp(value,"FALSE"))
		return(FALSE);

	return(strtol(value,NULL,0));
}

893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
BOOL iniReadBool(FILE* fp, const char* section, const char* key, BOOL deflt)
{
	char	buf[INI_MAX_VALUE_LEN];
	char*	value;

	if((value=read_value(fp,section,key,buf))==NULL)
		return(deflt);

	if(*value==0)		/* blank value */
		return(deflt);

	return(parseBool(value));
}

BOOL iniGetBool(str_list_t* list, const char* section, const char* key, BOOL deflt)
{
	char	value[INI_MAX_VALUE_LEN];

	get_value(*list, section, key, value);

	if(*value==0)		/* blank value */
		return(deflt);

	return(parseBool(value));
}

static ulong parseBitField(char* value, ini_bitdesc_t* bitdesc)
920
{
921
	int		i;
922
923
924
925
	char*	p;
	char*	tp;
	ulong	v=0;

926
	for(p=value;*p;) {
927
928
929
930
931
932
933
934
935
936
937
		tp=strchr(p,'|');
		if(tp!=NULL)
			*tp=0;
		truncsp(p);

		for(i=0;bitdesc[i].name;i++)
			if(!stricmp(bitdesc[i].name,p))
				break;

		if(bitdesc[i].name)
			v|=bitdesc[i].bit;
938
939
		else
			v|=strtoul(p,NULL,0);
940
941
942
943
944

		if(tp==NULL)
			break;

		p=tp+1;
945
		SKIP_WHITESPACE(p);
946
947
948
949
	}

	return(v);
}
rswindell's avatar
rswindell committed
950

951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
ulong iniReadBitField(FILE* fp, const char* section, const char* key, 
						ini_bitdesc_t* bitdesc, ulong deflt)
{
	char*	value;
	char	buf[INI_MAX_VALUE_LEN];

	if((value=read_value(fp,section,key,buf))==NULL)
		return(deflt);

	return(parseBitField(value,bitdesc));
}

ulong iniGetBitField(str_list_t* list, const char* section, const char* key, 
						ini_bitdesc_t* bitdesc, ulong deflt)
{
	char	value[INI_MAX_VALUE_LEN];

	get_value(*list, section, key, value);

	if(*value==0)		/* blank value */
		return(deflt);

	return(parseBitField(value,bitdesc));
}

976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
FILE* iniOpenFile(const char* fname)
{
	char* mode="r+";

	if(!fexist(fname))
		mode="w+";

	return(fopen(fname,mode));
}

BOOL iniCloseFile(FILE* fp)
{
	return(fclose(fp)==0);
}

rswindell's avatar
rswindell committed
991
992
993
994
995
996
997
str_list_t iniReadFile(FILE* fp)
{
	size_t		i;
	str_list_t	list;
	
	rewind(fp);

998
	list = strListReadFile(fp, NULL, INI_MAX_LINE_LEN);
rswindell's avatar
rswindell committed
999
	if(list!=NULL) {
1000
		/* truncate new-line chars off end of strings */
For faster browsing, not all history is shown. View entire blame