Subversion Repositories Kolibri OS

Rev

Rev 845 | Rev 988 | 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
 
919 mikedld 105
	invoke	file.seek, [f.fh], 0, SEEK_SET
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:
845 mikedld 385
	stdcall libini._.get_value_length, [f_addr]
717 mikedld 386
	sub	eax, [_buf_len]
845 mikedld 387
	stdcall libini._.shift_content, [f_addr], eax
717 mikedld 388
 
389
  .modify_key.ex:
390
	invoke	file.tell, [f.fh]
391
	sub	eax, [f.cnt]
392
;       dec     eax
919 mikedld 393
	invoke	file.seek, [f.fh], eax, SEEK_SET
717 mikedld 394
	invoke	file.write, [f.fh], [_buffer], [_buf_len]
395
 
396
	pop	edi esi ebx
397
	xor	eax, eax
398
	ret
399
 
400
  .create_key:
401
	mov	edi, [f.buf]
402
	add	edi, ini.BLOCK_SIZE
403
	push	edi
404
 
405
  .create_key.ex:
406
;       mov     word[edi], 0x0A0D
407
;       add     edi,2
408
	mov	esi, [_key_name]
845 mikedld 409
	call	libini._.string_copy
717 mikedld 410
	mov	byte[edi], '='
411
	inc	edi
412
	mov	esi, [_buffer]
413
	mov	ecx, [_buf_len]
414
	rep	movsb
415
	mov	word[edi], 0x0A0D
416
	add	edi, 2
417
	mov	eax, edi
418
 
419
	pop	edi
420
	sub	eax, edi
421
	mov	[_buffer], edi
422
	mov	[_buf_len], eax
423
	neg	eax
845 mikedld 424
	stdcall libini._.shift_content, [f_addr], eax
717 mikedld 425
 
426
	jmp	.modify_key.ex
427
 
428
  .create_section:
429
	mov	edi, [f.buf]
430
	add	edi, ini.BLOCK_SIZE
431
	push	edi
432
 
433
	mov	esi, [_sec_name]
434
;       mov     dword[edi], 0x0A0D + ('[' shl 16)
435
;       add     edi, 3
436
	mov	byte[edi], '['
437
	inc	edi
845 mikedld 438
	call	libini._.string_copy
717 mikedld 439
;       mov     byte[edi], ']'
440
;       inc     edi
441
	mov	dword[edi], ']' + (0x0A0D shl 8)
442
	add	edi, 3
443
 
444
	jmp	.create_key.ex
445
 
446
  .exit_error:
447
	pop	edi esi ebx
448
	or	eax, -1
449
	ret
450
endp
451
 
452
;;================================================================================================;;
453
proc ini.get_int _f_name, _sec_name, _key_name, _def_val ;////////////////////////////////////////;;
454
;;------------------------------------------------------------------------------------------------;;
845 mikedld 455
;? Read integer                                                                                   ;;
717 mikedld 456
;;------------------------------------------------------------------------------------------------;;
845 mikedld 457
;> _f_name = ini filename                                                                 ;;
458
;> _sec_name = section name                                                               ;;
459
;> _key_name = key name                                                                   ;;
460
;> _def_val = default value to return if no key, section or file found                     ;;
717 mikedld 461
;;------------------------------------------------------------------------------------------------;;
845 mikedld 462
;< eax = [_def_val] (error) / found key value                                              ;;
717 mikedld 463
;;================================================================================================;;
464
locals
465
  f	 IniFile
466
  f_addr dd ?
467
endl
468
 
469
	push	ebx esi edi
470
 
471
	xor	eax, eax
472
	mov	[f.fh], eax
473
	mov	[f.buf], eax
474
	invoke	file.open, [_f_name], O_READ
475
	cmp	eax, 32
476
	jb	.exit_error
477
	mov	[f.fh], eax
478
	invoke	mem.alloc, ini.MEM_SIZE
479
	or	eax, eax
480
	jz	.exit_error
481
	mov	[f.buf], eax
482
	lea	ebx, [f]
483
	mov	[f_addr], ebx
845 mikedld 484
	stdcall libini._.find_section, ebx, [_sec_name]
717 mikedld 485
	or	eax, eax
486
	jnz	.exit_error
487
 
845 mikedld 488
	stdcall libini._.find_key, ebx, [_key_name]
717 mikedld 489
	or	eax, eax
490
	jnz	.exit_error
491
 
845 mikedld 492
	stdcall libini._.skip_nonblanks, [f_addr]
717 mikedld 493
	xor	eax, eax
494
	xor	ebx, ebx
495
	xor	edx, edx
845 mikedld 496
	stdcall libini._.get_char, [f_addr]
717 mikedld 497
	cmp	al, '-'
498
	jne	.lp1
499
	inc	bh
845 mikedld 500
    @@: stdcall libini._.get_char, [f_addr]
717 mikedld 501
  .lp1: cmp	al, '0'
502
	jb	@f
503
	cmp	al, '9'
504
	ja	@f
505
	inc	bl
506
	add	eax, -'0'
507
	imul	edx, 10
508
	add	edx, eax
509
	jmp	@b
510
    @@:
511
	or	bl, bl
512
	jz	.exit_error
513
	or	bh, bh
514
	jz	@f
515
	neg	edx
516
    @@: invoke	file.close, [f.fh]
517
	invoke	mem.free, [f.buf]
518
	mov	eax, edx
519
	pop	edi esi ebx
520
	ret
521
 
522
  .exit_error:
523
	invoke	file.close, [f.fh]
524
	invoke	mem.free, [f.buf]
525
	mov	eax, [_def_val]
526
	pop	edi esi ebx
527
	ret
528
endp
529
 
530
;;================================================================================================;;
531
proc ini.set_int _f_name, _sec_name, _key_name, _val ;////////////////////////////////////////////;;
532
;;------------------------------------------------------------------------------------------------;;
845 mikedld 533
;? Write integer                                                                                  ;;
717 mikedld 534
;;------------------------------------------------------------------------------------------------;;
845 mikedld 535
;> _f_name = ini filename                                                                 ;;
536
;> _sec_name = section name                                                               ;;
537
;> _key_name = key name                                                                   ;;
538
;> _val = value                                                                            ;;
717 mikedld 539
;;------------------------------------------------------------------------------------------------;;
845 mikedld 540
;< eax = -1 (error) / 0                                                                           ;;
717 mikedld 541
;;================================================================================================;;
542
locals
543
  buf rb 16
544
endl
545
 
546
	push	ecx edx edi
547
 
548
	lea	edi, [buf]
549
	add	edi, 15
550
	mov	eax, [_val]
551
	or	eax, eax
552
	jns	@f
553
	mov	byte[edi], '-'
554
	neg	eax
555
	inc	edi
556
    @@: mov	ecx, 10
557
    @@: xor	edx, edx
558
	idiv	ecx
559
	add	dl, '0'
560
	mov	[edi], dl
561
	dec	edi
562
	or	eax, eax
563
	jnz	@b
564
	lea	eax, [buf]
565
	add	eax, 15
566
	sub	eax, edi
567
	inc	edi
568
 
569
	stdcall ini.set_str, [_f_name], [_sec_name], [_key_name], edi, eax
570
 
571
	pop	edi edx ecx
572
	ret
573
endp
574
 
575
 
576
;;================================================================================================;;
577
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
578
;;================================================================================================;;
579
;! Imported functions section                                                                     ;;
580
;;================================================================================================;;
581
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
582
;;================================================================================================;;
583
 
584
 
585
align 16
586
@IMPORT:
587
 
588
library \
845 mikedld 589
	libio , 'libio.obj'
717 mikedld 590
 
845 mikedld 591
import	libio			    , \
592
	file.size   , 'file.size'   , \
593
	file.open   , 'file.open'   , \
594
	file.read   , 'file.read'   , \
595
	file.write  , 'file.write'  , \
596
	file.seek   , 'file.seek'   , \
597
	file.eof?   , 'file.eof?'   , \
598
	file.seteof , 'file.seteof' , \
599
	file.tell   , 'file.tell'   , \
600
	file.close  , 'file.close'
717 mikedld 601
 
602
 
603
;;================================================================================================;;
604
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
605
;;================================================================================================;;
606
;! Exported functions section                                                                     ;;
607
;;================================================================================================;;
608
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
609
;;================================================================================================;;
610
 
611
 
612
align 16
613
@EXPORT:
614
 
615
export						  \
845 mikedld 616
	libini._.init	  , 'lib_init'		, \
717 mikedld 617
	0x00040005	  , 'version'		, \
618
	ini.enum_sections , 'ini.enum_sections' , \
619
	ini.enum_keys	  , 'ini.enum_keys'	, \
620
	ini.get_str	  , 'ini.get_str'	, \
621
	ini.get_int	  , 'ini.get_int'	, \
622
	ini.set_str	  , 'ini.set_str'	, \
623
	ini.set_int	  , 'ini.set_int'