Subversion Repositories Kolibri OS

Rev

Rev 783 | Rev 919 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
717 mikedld 1
;;================================================================================================;;
2
;;//// libini.asm //// (c) mike.dld, 2006-2008 ///////////////////////////////////////////////////;;
3
;;================================================================================================;;
4
;;                                                                                                ;;
5
;; This file is part of Common development libraries (Libs-Dev).                                  ;;
6
;;                                                                                                ;;
7
;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
8
;; General Public License as published by the Free Software Foundation, either version 3 of the   ;;
9
;; License, or (at your option) any later version.                                                ;;
10
;;                                                                                                ;;
11
;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without  ;;
12
;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  ;;
13
;; General Public License for more details.                                                       ;;
14
;;                                                                                                ;;
15
;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;;
16
;; see .                                                            ;;
17
;;                                                                                                ;;
18
;;================================================================================================;;
19
;;                                                                                                ;;
845 mikedld 20
;; 2008-08-06 (mike.dld)                                                                          ;;
21
;;   changes:                                                                                     ;;
22
;;     - split private procs into libini_p.asm, added comments                                    ;;
717 mikedld 23
;; 2008-02-07 (mike.dld)                                                                          ;;
24
;;   changes:                                                                                     ;;
25
;;     - renamed all *.aux.* to *._.* to match overall libraries design                           ;;
26
;; 2007-09-26 (mike.dld)                                                                          ;;
27
;;   bug-fixes:                                                                                   ;;
28
;;     - value was not correctly trimmed (reported by diamond)                                    ;;
29
;; 2007-08-01 (mike.dld)                                                                          ;;
30
;;   bug-fixes:                                                                                   ;;
31
;;     - serious defect in ini.set_str causing displaced write operations                         ;;
32
;;       (reported by diamond)                                                                    ;;
33
;;     - another serious defect in ini.enum_keys introduced with refactoring                      ;;
34
;;   changes:                                                                                     ;;
35
;;     - callback for enum_keys now takes additional parameter - key value                        ;;
36
;;     - handling trailing spaces in section/key/value                                            ;;
37
;; 2007-05-19 (mike.dld)                                                                          ;;
38
;;   bug-fixes:                                                                                   ;;
39
;;     - last char still wasn't read correctly                                                    ;;
40
;;     - digits of number were reversed when using ini.set_int                                    ;;
41
;;     - now using 'ini.aux.unget_char' instead of dangerous 'dec esi'                            ;;
42
;;   changes:                                                                                     ;;
43
;;     - all non-public functions now start with ini.aux.*                                        ;;
44
;;     - added ini.enum_sections and ini.enum_keys                                                ;;
45
;;     - removed ini.query_sec (use ini.enum_* instead)                                           ;;
46
;;                                                                                                ;;
47
;;================================================================================================;;
48
 
49
format MS COFF
50
 
51
public @EXPORT as 'EXPORTS'
52
 
53
include '../../../../proc32.inc'
54
include '../../../../macros.inc'
55
include '../libio/libio.inc'
56
purge section ; mov,add,sub
57
 
58
include 'libini_p.inc'
59
 
845 mikedld 60
section '.flat' code readable align 16
717 mikedld 61
 
845 mikedld 62
include 'libini_p.asm'
717 mikedld 63
 
64
;;================================================================================================;;
65
proc ini.enum_sections _f_name, _callback ;///////////////////////////////////////////////////////;;
66
;;------------------------------------------------------------------------------------------------;;
845 mikedld 67
;? Enumerate sections, calling callback function for each of them                                 ;;
717 mikedld 68
;;------------------------------------------------------------------------------------------------;;
845 mikedld 69
;> _f_name = ini filename                                                                 ;;
70
;> _callback = callback function address: func(f_name, sec_name), where                           ;;
71
;>   f_name = ini filename (as passed to the function)                                    ;;
72
;>   sec_name = section name found                                                        ;;
717 mikedld 73
;;------------------------------------------------------------------------------------------------;;
845 mikedld 74
;< eax = -1 (error) / 0                                                                           ;;
717 mikedld 75
;;================================================================================================;;
76
locals
77
  f	  IniFile
78
  f_addr  dd ?
79
  sec_buf dd ?
80
endl
81
 
82
	push	ebx esi edi
83
 
84
	cld
85
 
86
	invoke	mem.alloc, ini.MAX_NAME_LEN
87
	or	eax, eax
88
	jz	.exit_error.2
89
	mov	[sec_buf], eax
90
 
91
	xor	eax, eax
92
	mov	[f.fh], eax
93
	mov	[f.buf], eax
94
	invoke	file.open, [_f_name], O_READ
95
	cmp	eax, 32
96
	jb	.exit_error
97
	mov	[f.fh], eax
98
	invoke	mem.alloc, ini.MEM_SIZE
99
	or	eax, eax
100
	jz	.exit_error
101
	mov	[f.buf], eax
102
	lea	ebx, [f]
103
	mov	[f_addr], ebx
104
 
105
	invoke	file.seek, [f.fh], SEEK_SET, 0
845 mikedld 106
	stdcall libini._.preload_block, [f_addr]
717 mikedld 107
 
108
  .next_section:
845 mikedld 109
	stdcall libini._.find_next_section, [f_addr]
717 mikedld 110
	or	eax, eax
111
	jnz	.exit_error
112
 
845 mikedld 113
	stdcall libini._.get_char, [f_addr]
114
	stdcall libini._.skip_spaces, [f_addr]
717 mikedld 115
;       inc     esi
116
;       dec     [f.cnt]
117
	mov	edi, [sec_buf]
845 mikedld 118
    @@: stdcall libini._.get_char, [f_addr]
717 mikedld 119
	cmp	al, ']'
120
	je	@f
121
	or	al, al
122
	jz	.exit_ok
123
	cmp	al, 13
124
	je	.next_section
125
	cmp	al, 10
126
	je	.next_section
127
	stosb
128
	jmp	@b
129
    @@: xor	al, al
130
	stosb
131
	add	edi, -2
132
    @@: cmp	byte[edi], 32
133
	ja	@f
134
	mov	byte[edi], 0
135
	dec	edi
136
	jmp	@b
137
    @@:
138
	pushad
139
	mov	eax, [f_addr]
140
	stdcall [_callback], [_f_name], [sec_buf]
141
	or	eax, eax
142
	popad
143
	jnz	.next_section
144
 
145
  .exit_ok:
146
	invoke	file.close, [f.fh]
147
	invoke	mem.free, [f.buf]
148
	invoke	mem.free, [sec_buf]
149
	xor	eax, eax
150
	pop	edi esi ebx
151
	ret
152
 
153
  .exit_error:
154
	invoke	file.close, [f.fh]
155
	invoke	mem.free, [f.buf]
156
	invoke	mem.free, [sec_buf]
157
  .exit_error.2:
158
	or	eax, -1
159
	pop	edi esi ebx
160
	ret
161
endp
162
 
163
;;================================================================================================;;
164
proc ini.enum_keys _f_name, _sec_name, _callback ;////////////////////////////////////////////////;;
165
;;------------------------------------------------------------------------------------------------;;
845 mikedld 166
;? Enumerate keys within a section, calling callback function for each of them                    ;;
717 mikedld 167
;;------------------------------------------------------------------------------------------------;;
845 mikedld 168
;> _f_name = ini filename                                                                 ;;
169
;> _sec_name = section name                                                               ;;
170
;> _callback = callback function address: func(f_name, sec_name, key_name, key_value), where      ;;
171
;>   f_name = ini filename (as passed to the function)                                    ;;
172
;>   sec_name = section name (as passed to the function)                                  ;;
173
;>   key_name = key name found                                                            ;;
174
;>   key_value = value of key found                                                       ;;
717 mikedld 175
;;------------------------------------------------------------------------------------------------;;
845 mikedld 176
;< eax = -1 (error) / 0                                                                           ;;
717 mikedld 177
;;================================================================================================;;
178
locals
179
  f	  IniFile
180
  f_addr  dd ?
181
  key_buf dd ?
182
  val_buf dd ?
183
endl
184
 
185
	push	ebx esi edi
186
 
187
	cld
188
 
189
	invoke	mem.alloc, ini.MAX_NAME_LEN
190
	or	eax, eax
191
	jz	.exit_error.3
192
	mov	[key_buf], eax
193
	invoke	mem.alloc, ini.MAX_VALUE_LEN
194
	or	eax, eax
195
	jz	.exit_error.2
196
	mov	[val_buf], eax
197
 
198
	xor	eax, eax
199
	mov	[f.fh], eax
200
	mov	[f.buf], eax
201
	invoke	file.open, [_f_name], O_READ
202
	cmp	eax, 32
203
	jb	.exit_error
204
	mov	[f.fh], eax
205
	invoke	mem.alloc, ini.MEM_SIZE
206
	or	eax, eax
207
	jz	.exit_error
208
	mov	[f.buf], eax
209
	lea	ebx, [f]
210
	mov	[f_addr], ebx
845 mikedld 211
	stdcall libini._.find_section, ebx, [_sec_name]
717 mikedld 212
	or	eax, eax
213
	jnz	.exit_error
214
 
215
  .next_key:
845 mikedld 216
	stdcall libini._.skip_line, [f_addr]
217
	stdcall libini._.skip_nonblanks, [f_addr]
717 mikedld 218
	or	al, al
219
	jz	.exit_error
220
	cmp	al, '['
221
	je	.exit_error
222
	mov	edi, [key_buf]
845 mikedld 223
    @@: stdcall libini._.get_char, [f_addr]
717 mikedld 224
	or	al, al
225
	jz	.exit_error
226
	cmp	al, '='
227
	je	@f
228
	stosb
229
	jmp	@b
230
    @@:
231
	xor	al, al
232
	stosb
233
	add	edi, -2
234
    @@: cmp	byte[edi], 32
235
	ja	@f
236
	mov	byte[edi], 0
237
	dec	edi
238
	jmp	@b
845 mikedld 239
    @@: stdcall libini._.low.read_value, [f_addr], [val_buf], ini.MAX_VALUE_LEN
717 mikedld 240
	pushad
241
	stdcall [_callback], [_f_name], [_sec_name], [key_buf], [val_buf]
242
	or	eax, eax
243
	popad
244
	jnz	.next_key
245
 
246
    @@: invoke	file.close, [f.fh]
247
	invoke	mem.free, [f.buf]
248
	xor	eax, eax
249
	stosb
250
	pop	edi esi ebx
251
	ret
252
 
253
  .exit_error:
254
	invoke	file.close, [f.fh]
255
	invoke	mem.free, [f.buf]
256
	invoke	mem.free, [val_buf]
257
  .exit_error.2:
258
	invoke	mem.free, [key_buf]
259
  .exit_error.3:
260
	or	eax, -1
261
	pop	edi esi ebx
262
	ret
263
endp
264
 
265
;;================================================================================================;;
266
proc ini.get_str _f_name, _sec_name, _key_name, _buffer, _buf_len, _def_val ;/////////////////////;;
267
;;------------------------------------------------------------------------------------------------;;
845 mikedld 268
;? Read string                                                                                    ;;
717 mikedld 269
;;------------------------------------------------------------------------------------------------;;
845 mikedld 270
;> _f_name = ini filename                                                                 ;;
271
;> _sec_name = section name                                                               ;;
272
;> _key_name = key name                                                                   ;;
273
;> _buffer = destination buffer address                                                    ;;
274
;> _buf_len = buffer size (maximum bytes to read)                                          ;;
275
;> _def_val = default value to return if no key, section or file found                    ;;
717 mikedld 276
;;------------------------------------------------------------------------------------------------;;
845 mikedld 277
;< eax = -1 (error) / 0                                                                           ;;
278
;< [_buffer] = [_def_val] (error) / found key value                                       ;;
717 mikedld 279
;;================================================================================================;;
280
locals
281
  f	 IniFile
282
  f_addr dd ?
283
endl
284
 
285
	push	ebx esi edi
286
 
287
	xor	eax, eax
288
	mov	[f.fh], eax
289
	mov	[f.buf], eax
290
	invoke	file.open, [_f_name], O_READ
291
	cmp	eax, 32
292
	jb	.exit_error
293
	mov	[f.fh], eax
294
	invoke	mem.alloc, ini.MEM_SIZE
295
	or	eax, eax
296
	jz	.exit_error
297
	mov	[f.buf], eax
298
	lea	ebx, [f]
299
	mov	[f_addr], ebx
845 mikedld 300
	stdcall libini._.find_section, ebx, [_sec_name]
717 mikedld 301
	or	eax, eax
302
	jnz	.exit_error
303
 
845 mikedld 304
	stdcall libini._.find_key, ebx, [_key_name]
717 mikedld 305
	or	eax, eax
306
	jnz	.exit_error
307
 
845 mikedld 308
	stdcall libini._.low.read_value, [f_addr], [_buffer], [_buf_len]
717 mikedld 309
;       mov     edi, [_buffer]
310
;   @@: dec     [_buf_len]
311
;       jz      @f
312
;       stdcall ini.aux.get_char, [f_addr]
313
;       or      al, al
314
;       jz      @f
315
;       cmp     al, 13
316
;       je      @f
317
;       cmp     al, 10
318
;       je      @f
319
;       stosb
320
;       jmp     @b
321
    @@: invoke	file.close, [f.fh]
322
	invoke	mem.free, [f.buf]
323
	xor	eax, eax
324
	stosb
325
	pop	edi esi ebx
326
	ret
327
 
328
  .exit_error:
329
	invoke	file.close, [f.fh]
330
	invoke	mem.free, [f.buf]
331
	mov	esi, [_def_val]
332
	mov	edi, [_buffer]
333
    @@: lodsb
334
	stosb
335
	or	al, al
336
	jnz	@b
337
	or	eax, -1
338
	pop	edi esi ebx
339
	ret
340
endp
341
 
342
;;================================================================================================;;
343
proc ini.set_str _f_name, _sec_name, _key_name, _buffer, _buf_len ;///////////////////////////////;;
344
;;------------------------------------------------------------------------------------------------;;
845 mikedld 345
;? Write string                                                                                   ;;
717 mikedld 346
;;------------------------------------------------------------------------------------------------;;
845 mikedld 347
;> _f_name = ini filename                                                                 ;;
348
;> _sec_name = section name                                                               ;;
349
;> _key_name = key name                                                                   ;;
350
;> _buffer = source buffer address                                                         ;;
351
;> _buf_len = buffer size (bytes to write)                                                 ;;
717 mikedld 352
;;------------------------------------------------------------------------------------------------;;
845 mikedld 353
;< eax = -1 (error) / 0                                                                           ;;
717 mikedld 354
;;================================================================================================;;
355
locals
356
  f	 IniFile
357
  f_addr dd ?
358
endl
359
 
360
	push	ebx esi edi
361
 
362
	xor	eax, eax
363
	mov	[f.fh], eax
364
	mov	[f.buf], eax
365
	invoke	file.open, [_f_name], O_READ + O_WRITE + O_CREATE
366
	cmp	eax, 32
367
	jb	.exit_error
368
	mov	[f.fh], eax
369
	invoke	mem.alloc, ini.MEM_SIZE
370
	or	eax, eax
371
	jz	.exit_error
372
	mov	[f.buf], eax
373
	lea	ebx, [f]
374
	mov	[f_addr], ebx
375
 
845 mikedld 376
	stdcall libini._.find_section, ebx, [_sec_name]
717 mikedld 377
	or	eax, eax
378
	jnz	.create_section
379
 
845 mikedld 380
	stdcall libini._.find_key, ebx, [_key_name]
717 mikedld 381
	or	eax, eax
382
	jnz	.create_key
383
 
384
  .modify_key:
385
 
845 mikedld 386
	stdcall libini._.get_value_length, [f_addr]
717 mikedld 387
	sub	eax, [_buf_len]
845 mikedld 388
	stdcall libini._.shift_content, [f_addr], eax
717 mikedld 389
 
390
  .modify_key.ex:
391
	invoke	file.tell, [f.fh]
392
	sub	eax, [f.cnt]
393
;       dec     eax
394
	invoke	file.seek, [f.fh], SEEK_SET, eax
395
	invoke	file.write, [f.fh], [_buffer], [_buf_len]
396
 
397
	pop	edi esi ebx
398
	xor	eax, eax
399
	ret
400
 
401
  .create_key:
402
	mov	edi, [f.buf]
403
	add	edi, ini.BLOCK_SIZE
404
	push	edi
405
 
406
  .create_key.ex:
407
;       mov     word[edi], 0x0A0D
408
;       add     edi,2
409
	mov	esi, [_key_name]
845 mikedld 410
	call	libini._.string_copy
717 mikedld 411
	mov	byte[edi], '='
412
	inc	edi
413
	mov	esi, [_buffer]
414
	mov	ecx, [_buf_len]
415
	rep	movsb
416
	mov	word[edi], 0x0A0D
417
	add	edi, 2
418
	mov	eax, edi
419
 
420
	pop	edi
421
	sub	eax, edi
422
	mov	[_buffer], edi
423
	mov	[_buf_len], eax
424
	neg	eax
845 mikedld 425
	stdcall libini._.shift_content, [f_addr], eax
717 mikedld 426
 
427
	jmp	.modify_key.ex
428
 
429
  .create_section:
430
	mov	edi, [f.buf]
431
	add	edi, ini.BLOCK_SIZE
432
	push	edi
433
 
434
	mov	esi, [_sec_name]
435
;       mov     dword[edi], 0x0A0D + ('[' shl 16)
436
;       add     edi, 3
437
	mov	byte[edi], '['
438
	inc	edi
845 mikedld 439
	call	libini._.string_copy
717 mikedld 440
;       mov     byte[edi], ']'
441
;       inc     edi
442
	mov	dword[edi], ']' + (0x0A0D shl 8)
443
	add	edi, 3
444
 
445
	jmp	.create_key.ex
446
 
447
  .exit_error:
448
	pop	edi esi ebx
449
	or	eax, -1
450
	ret
451
endp
452
 
453
;;================================================================================================;;
454
proc ini.get_int _f_name, _sec_name, _key_name, _def_val ;////////////////////////////////////////;;
455
;;------------------------------------------------------------------------------------------------;;
845 mikedld 456
;? Read integer                                                                                   ;;
717 mikedld 457
;;------------------------------------------------------------------------------------------------;;
845 mikedld 458
;> _f_name = ini filename                                                                 ;;
459
;> _sec_name = section name                                                               ;;
460
;> _key_name = key name                                                                   ;;
461
;> _def_val = default value to return if no key, section or file found                     ;;
717 mikedld 462
;;------------------------------------------------------------------------------------------------;;
845 mikedld 463
;< eax = [_def_val] (error) / found key value                                              ;;
717 mikedld 464
;;================================================================================================;;
465
locals
466
  f	 IniFile
467
  f_addr dd ?
468
endl
469
 
470
	push	ebx esi edi
471
 
472
	xor	eax, eax
473
	mov	[f.fh], eax
474
	mov	[f.buf], eax
475
	invoke	file.open, [_f_name], O_READ
476
	cmp	eax, 32
477
	jb	.exit_error
478
	mov	[f.fh], eax
479
	invoke	mem.alloc, ini.MEM_SIZE
480
	or	eax, eax
481
	jz	.exit_error
482
	mov	[f.buf], eax
483
	lea	ebx, [f]
484
	mov	[f_addr], ebx
845 mikedld 485
	stdcall libini._.find_section, ebx, [_sec_name]
717 mikedld 486
	or	eax, eax
487
	jnz	.exit_error
488
 
845 mikedld 489
	stdcall libini._.find_key, ebx, [_key_name]
717 mikedld 490
	or	eax, eax
491
	jnz	.exit_error
492
 
845 mikedld 493
	stdcall libini._.skip_nonblanks, [f_addr]
717 mikedld 494
	xor	eax, eax
495
	xor	ebx, ebx
496
	xor	edx, edx
845 mikedld 497
	stdcall libini._.get_char, [f_addr]
717 mikedld 498
	cmp	al, '-'
499
	jne	.lp1
500
	inc	bh
845 mikedld 501
    @@: stdcall libini._.get_char, [f_addr]
717 mikedld 502
  .lp1: cmp	al, '0'
503
	jb	@f
504
	cmp	al, '9'
505
	ja	@f
506
	inc	bl
507
	add	eax, -'0'
508
	imul	edx, 10
509
	add	edx, eax
510
	jmp	@b
511
    @@:
512
	or	bl, bl
513
	jz	.exit_error
514
	or	bh, bh
515
	jz	@f
516
	neg	edx
517
    @@: invoke	file.close, [f.fh]
518
	invoke	mem.free, [f.buf]
519
	mov	eax, edx
520
	pop	edi esi ebx
521
	ret
522
 
523
  .exit_error:
524
	invoke	file.close, [f.fh]
525
	invoke	mem.free, [f.buf]
526
	mov	eax, [_def_val]
527
	pop	edi esi ebx
528
	ret
529
endp
530
 
531
;;================================================================================================;;
532
proc ini.set_int _f_name, _sec_name, _key_name, _val ;////////////////////////////////////////////;;
533
;;------------------------------------------------------------------------------------------------;;
845 mikedld 534
;? Write integer                                                                                  ;;
717 mikedld 535
;;------------------------------------------------------------------------------------------------;;
845 mikedld 536
;> _f_name = ini filename                                                                 ;;
537
;> _sec_name = section name                                                               ;;
538
;> _key_name = key name                                                                   ;;
539
;> _val = value                                                                            ;;
717 mikedld 540
;;------------------------------------------------------------------------------------------------;;
845 mikedld 541
;< eax = -1 (error) / 0                                                                           ;;
717 mikedld 542
;;================================================================================================;;
543
locals
544
  buf rb 16
545
endl
546
 
547
	push	ecx edx edi
548
 
549
	lea	edi, [buf]
550
	add	edi, 15
551
	mov	eax, [_val]
552
	or	eax, eax
553
	jns	@f
554
	mov	byte[edi], '-'
555
	neg	eax
556
	inc	edi
557
    @@: mov	ecx, 10
558
    @@: xor	edx, edx
559
	idiv	ecx
560
	add	dl, '0'
561
	mov	[edi], dl
562
	dec	edi
563
	or	eax, eax
564
	jnz	@b
565
	lea	eax, [buf]
566
	add	eax, 15
567
	sub	eax, edi
568
	inc	edi
569
 
570
	stdcall ini.set_str, [_f_name], [_sec_name], [_key_name], edi, eax
571
 
572
	pop	edi edx ecx
573
	ret
574
endp
575
 
576
 
577
;;================================================================================================;;
578
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
579
;;================================================================================================;;
580
;! Imported functions section                                                                     ;;
581
;;================================================================================================;;
582
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
583
;;================================================================================================;;
584
 
585
 
586
align 16
587
@IMPORT:
588
 
589
library \
845 mikedld 590
	libio , 'libio.obj'
717 mikedld 591
 
845 mikedld 592
import	libio			    , \
593
	file.size   , 'file.size'   , \
594
	file.open   , 'file.open'   , \
595
	file.read   , 'file.read'   , \
596
	file.write  , 'file.write'  , \
597
	file.seek   , 'file.seek'   , \
598
	file.eof?   , 'file.eof?'   , \
599
	file.seteof , 'file.seteof' , \
600
	file.tell   , 'file.tell'   , \
601
	file.close  , 'file.close'
717 mikedld 602
 
603
 
604
;;================================================================================================;;
605
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
606
;;================================================================================================;;
607
;! Exported functions section                                                                     ;;
608
;;================================================================================================;;
609
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
610
;;================================================================================================;;
611
 
612
 
613
align 16
614
@EXPORT:
615
 
616
export						  \
845 mikedld 617
	libini._.init	  , 'lib_init'		, \
717 mikedld 618
	0x00040005	  , 'version'		, \
619
	ini.enum_sections , 'ini.enum_sections' , \
620
	ini.enum_keys	  , 'ini.enum_keys'	, \
621
	ini.get_str	  , 'ini.get_str'	, \
622
	ini.get_int	  , 'ini.get_int'	, \
623
	ini.set_str	  , 'ini.set_str'	, \
624
	ini.set_int	  , 'ini.set_int'