Artifact 3542b4164daa220c7351da5b9ace14ff5ba7df47:
- File
freshlib/data/uConfig.asm
- 2012-01-24 09:39:51 - part of checkin [7f97771e7e] on branch FreshLibDev - Added StrToNumEx function in strlib.asm that converts strings to number using FASM syntax for numbers. Implemented such syntax to the TestGroundConfig.asm Fixed small problem with the signatures in uConfig.asm (user: lhmnai0
- 2012-04-27 06:49:35 - part of checkin [07192215a5] on branch trunk - Merged with FreshLibDev. Also, some small changes on the xref windows, related to the font used. (user: lhmnai0
-
2012-05-24 04:49:02
- part of checkin
[591cbfa516]
on branch FreshLibDev
- 1. Added test GUI application about the directory functions.
2. Fixed the Linux DirectoryRead function.
3. The function FreeDirArray and the structure definition TDirItem moved to the OS independent part of the library.
4. When is set options.DebugMode=1 the Linux timers are stopped from initialization because the timers generate signals and stop the program running in debugger.
5. Added some structures and constants definitions about sys_getdents in equates/Linux/_linux.inc
(user: johnfound - 2012-05-24 06:41:09 - part of checkin [3b8ab4c6fa] on branch FreshLibDev - Implemented Win32 version of DirectoryRead function. (user: johnfound
; _______________________________________________________________________________________
;| |
;| ..::FreshLib::.. Free, open source. Licensed under "Fresh artistic license." |
;|_______________________________________________________________________________________|
;
; Description: OS independent micro configuration files library.
;
; Target OS: Any
;
; Dependencies: memory.asm; strlib.asm; arrays.asm; files.asm
;
; Notes:
;
;_________________________________________________________________________________________
module "uConfig library"
; Structure of the file of uConfig:
;
; offset | size | description
; --------+-------+-----------------------------------------------------------------------
; 0 | 4 | Signature
; 4 | 4 | $0a1a0a0d (CR, LF, EOF, 00)
; 8 | 4 | Hash of the whole file including file length of the next field
; 12 | 4 | Chunk data length (N)
; 16 | N | Data chunks
; --------+-------+-----------------------------------------------------------------------
;
; Every data chunk have following structure:
;
; offset | size | description
; --------+-------+-----------------------------------------------------------------------
; 0 | 4 | Key name 4xASCII chars.
; 4 | 4 | Length of the data in bytes (K)
; 8 | 4 | Data type. Constant of cdtXXXXX (see definitions below)
; 12 | K | Chunk data.
; --------+-------+-----------------------------------------------------------------------
;
cdtNULL = 0
cdtInteger = 1 ; 32bit integer value.
cdtString = 2 ; utf-8 string.
cdtBlob = 3 ; arbitraty sized array of bytes.
cdtConfig = 4
cdtMaxAlowed = cdtConfig
struct TConfigHeader
.signature dd ?
.filler dd ?
.hash dd ?
.length dd ?
.chunks:
ends
struct TChunkHeader
.KeyName dd ?
.length dd ? ; length of the data without the size of the header and checksum.
.type dd ?
ends
struct TConfigRecord
.KeyName dd ?
.DataSize dd ?
.Type dd ?
.Data dd ?
ends
; loads the file representation from the memory and expands it to the database tree structure.
; returns pointer to TArray of TConfigRecord structures.
proc LoadConfigDB, .ptrSource, .signature
begin
push ecx edx esi
mov esi, [.ptrSource]
test esi, esi
jnz .process_source
stdcall CreateArray, sizeof.TConfigRecord
jmp .db_ok
.process_source:
; check 8 bytes signature
mov edx, [esi+TConfigHeader.signature]
cmp [.signature], -1
je .signatureok
cmp edx, [.signature]
jne .error_bad_signature
.signatureok:
mov [.signature], edx
cmp dword [esi+TConfigHeader.filler], $001a0a0d
jne .error_bad_signature
mov ecx, [esi+TConfigHeader.length]
lea esi, [esi+TConfigHeader.length]
add ecx, 4 ;(the length itself)
stdcall DataHash, esi, ecx
cmp eax, [esi-4]
jne .error_bad_hash
add esi, 4
sub ecx, 4
stdcall __DoRecurseConfigSource, esi, ecx
.db_ok:
pushd [.signature]
popd [eax+TArray.lparam] ; store the signature to the .lparam field of the root TArray
clc
.finish:
pop esi edx ecx
return
.error_bad_signature:
mov eax, -1
stc
jmp .finish
.error_bad_hash:
mov eax, -2
stc
jmp .finish
endp
proc __DoRecurseConfigSource, .ptrSource, .length
.array dd ?
begin
pushad
stdcall CreateArray, sizeof.TConfigRecord
mov [.array], eax
mov esi, [.ptrSource]
mov ecx, [.length]
.chunk_loop:
cmp ecx, sizeof.TConfigRecord
jb .finish
stdcall AddArrayItems, [.array], 1
mov [.array], edx
mov edi, eax
mov eax, [esi+TChunkHeader.KeyName]
mov edx, [esi+TChunkHeader.length]
mov [edi+TConfigRecord.KeyName], eax
mov [edi+TConfigRecord.DataSize], edx
mov eax, [esi+TChunkHeader.type]
mov [edi+TConfigRecord.Type], eax
add esi, sizeof.TChunkHeader
sub ecx, sizeof.TChunkHeader
and eax, $7
movzx eax, [.type_handlers+eax]
add eax, .type_handlers
call eax
mov [edi+TConfigRecord.Data], eax
.next_chunk:
mov eax, [edi+TConfigRecord.DataSize]
add eax, 3
and al, $fc
add esi, eax
sub ecx, eax
jmp .chunk_loop
.finish:
popad
mov eax, [.array]
return
.type_handlers db .handle_null - .type_handlers
db .handle_int - .type_handlers
db .handle_string - .type_handlers
db .handle_blob - .type_handlers
db .handle_config - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
.handle_config:
stdcall __DoRecurseConfigSource, esi, edx
.handle_null:
retn
.handle_int:
mov eax, [esi]
retn
.handle_string:
stdcall StrNew
stdcall StrCopyPart, eax, esi, 0, edx
retn
.handle_blob:
stdcall GetMem, edx
push esi edi ecx
mov edi, eax
mov ecx, edx
rep movsb
pop ecx edi esi
retn
endp
; creates memory image (TArray) of the file of the config database.
proc SaveConfigFile, .ptrRoot, .signature
begin
push edx ecx
stdcall CreateArray, 4
mov edx, eax
mov ecx, [.ptrRoot]
stdcall AddArrayItems, edx, sizeof.TConfigHeader/4
pushd [.signature] $001a0a0d
popd [eax+TConfigHeader.filler] [eax+TConfigHeader.signature]
stdcall __DoSaveParamArray, edx, [.ptrRoot]
push edx
mov ecx, [edx+TArray.count]
shl ecx, 2
lea edx, [edx+TArray.array+TConfigHeader.length]
sub ecx, sizeof.TConfigHeader
mov [edx], ecx
add ecx, 4 ; .length field
stdcall DataHash, edx, ecx
mov [edx-4], eax ; -4 if the offset to TConfigHeader.hash relative to TConfigHeader.length
pop eax
pop ecx edx
return
endp
proc __DoSaveParamArray, .stream, .array
.count dd ?
begin
pushad
mov ebx, [.array]
mov ecx, [ebx+TArray.count]
lea ebx, [ebx+TArray.array-sizeof.TConfigRecord]
mov [.count], ecx
.loop:
add ebx, sizeof.TConfigRecord
dec [.count]
js .end_save
stdcall AddArrayItems, [.stream], 3
mov [.stream], edx
pushd [ebx+TConfigRecord.KeyName] [ebx+TConfigRecord.DataSize] [ebx+TConfigRecord.Type]
popd [eax+TChunkHeader.type] [eax+TChunkHeader.length] [eax+TChunkHeader.KeyName]
movzx eax, byte [ebx+TConfigRecord.Type]
and al, $07
movzx eax, [.type_handlers+eax]
add eax, .type_handlers
call eax
jc .loop
; align to dword
mov ecx, [ebx+TConfigRecord.DataSize]
add ecx, 3
and cl, $fc
shr ecx, 2
stdcall AddArrayItems, [.stream], ecx
mov [.stream], edx
mov edi, eax
rep movsd
jmp .loop
.end_save:
popad
mov edx, [.stream]
return
.type_handlers db .handle_null - .type_handlers
db .handle_int - .type_handlers
db .handle_string - .type_handlers
db .handle_blob - .type_handlers
db .handle_config - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
.handle_int:
lea esi, [ebx+TConfigRecord.Data]
clc
retn
.handle_string:
stdcall StrPtr, [ebx+TConfigRecord.Data]
mov esi, eax
clc
retn
.handle_blob:
mov esi, [ebx+TConfigRecord.Data]
clc
retn
.handle_config:
mov eax, [.stream]
mov eax, [eax+TArray.count]
push eax
stdcall __DoSaveParamArray, [.stream], [ebx+TConfigRecord.Data]
mov [.stream], edx
pop eax ; old size
mov ecx, [edx+TArray.count]
sub ecx, eax
lea edx, [edx+TArray.array+4*eax-sizeof.TChunkHeader]
shl ecx, 2
mov [edx+TChunkHeader.length], ecx
.handle_null:
stc
retn
endp
proc FreeConfigDB, .ptrRoot
.dummy TConfigRecord
begin
push eax
cmp [.ptrRoot], 0
je .exit
mov [.dummy.Type], cdtConfig
mov eax, [.ptrRoot]
mov [.dummy.Data], eax
lea eax, [.dummy]
stdcall __FreeConfigRecord, eax
.exit:
pop eax
return
endp
; searches the tree for the given path and returns a pointer to the variable, containing pointer to TArray of the directory.
proc __GetParamArray, .ptrVarRoot, .pDirectory, .create
begin
push ebx edx esi
mov esi, [.pDirectory]
mov ebx, [.ptrVarRoot]
test esi, esi
jz .found
.loop:
cmp dword [esi], 0
je .found
stdcall __ScanParamArray, [ebx], [esi]
jc .err_not_found
cmp [eax+TConfigRecord.Type], cdtConfig
jne .err_not_directory
.next:
lea ebx, [eax+TConfigRecord.Data]
add esi, 4
jmp .loop
.found:
mov eax, ebx
clc
pop esi edx ebx
return
.err_not_found:
cmp [.create], 0
je .no_create
stdcall AddArrayItems, [ebx], 1
mov [ebx], edx
mov edx, eax
pushd [esi]
popd [edx+TConfigRecord.KeyName]
mov [edx+TConfigRecord.Type], cdtConfig
stdcall CreateArray, sizeof.TConfigRecord
mov [edx+TConfigRecord.Data], eax
mov eax, edx
jmp .next
.no_create:
xor eax, eax
.error:
stc
pop esi edx ebx
return
.err_not_directory:
xor eax, eax
dec eax
jmp .error
endp
; returns:
; CF=0 and eax = pointer to TConfigRecord
; ecx = index of the record in the array.
; CF=1 and eax = 0 - the key was not found.
proc __ScanParamArray, .ptrArray, .name
begin
push ecx esi
mov esi, [.ptrArray]
test esi, esi
jz .not_found
mov ecx, [esi+TArray.count]
lea esi, [esi+TArray.array]
jecxz .not_found
xor edx, edx
.loop:
mov eax, [esi+TConfigRecord.KeyName]
cmp eax, [.name]
je .found
add esi, sizeof.TConfigRecord
inc edx
loop .loop
.not_found:
xor eax, eax
stc
pop esi ecx
return
.found:
mov eax, esi
clc
pop esi ecx
return
endp
; returns
; eax - poiner to the TConfigRecord or NULL if missing
proc GetConfigParam, .ptrConfig, .pDirectory, .name
begin
push edx
lea eax, [.ptrConfig]
stdcall __GetParamArray, eax, [.pDirectory], 0
stdcall __ScanParamArray, [eax], [.name]
pop edx
return
endp
proc GetConfigParam.AsString, .ptrConfig, .pDirectory, .name
begin
push edx
stdcall GetConfigParam, [.ptrConfig], [.pDirectory], [.name]
jc .finish
movzx edx, byte [eax+TConfigRecord.Type]
and dl, $07
movzx edx, [.type_handlers+edx]
add edx, .type_handlers
call edx
.finish:
pop edx
return
.type_handlers db .handle_null - .type_handlers
db .handle_int - .type_handlers
db .handle_string - .type_handlers
db .handle_blob - .type_handlers
db .handle_config - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
.handle_null:
stdcall StrDup, .txtNULL
retn
.handle_int:
stdcall NumToStr, [eax+TConfigRecord.Data], ntsSigned or ntsDec
retn
.handle_string:
stdcall StrDup, [eax+TConfigRecord.Data]
retn
.handle_config:
stdcall StrDup, .txtDir
retn
.handle_blob:
stdcall StrDup, .txtBlob
retn
.txtNULL db 'NULL', 0
.txtDir db 'SDIR', 0
.txtBlob db 'BLOB', 0
endp
proc __FreeConfigRecord, .ptrRecord
begin
pushad
mov esi, [.ptrRecord]
movzx eax, byte [esi+TConfigRecord.Type]
and al, $07
mov al, [.type_handlers+eax]
add eax, .type_handlers
call eax
xor eax, eax
mov [esi+TConfigRecord.Type], eax
mov [esi+TConfigRecord.Data], eax
mov [esi+TConfigRecord.DataSize], eax
popad
return
.type_handlers db .handle_null - .type_handlers
db .handle_int - .type_handlers
db .handle_string - .type_handlers
db .handle_blob - .type_handlers
db .handle_config - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
.handle_config:
mov eax, [esi+TConfigRecord.Data]
mov ecx, [eax+TArray.count]
lea eax, [eax+TArray.array]
jecxz .handle_blob
.loop:
stdcall __FreeConfigRecord, eax
add eax, sizeof.TConfigRecord
loop .loop
.handle_blob:
stdcall FreeMem, [esi+TConfigRecord.Data]
retn
.handle_string:
stdcall StrDel, [esi+TConfigRecord.Data]
.handle_null:
.handle_int:
retn
endp
proc DelCongigParam, .ptrVarConfig, .pDirectory, .name
begin
pushad
stdcall __GetParamArray, [.ptrVarConfig], [.pDirectory], 0
jc .deleted
mov esi, eax
stdcall __ScanParamArray, [esi], [.name]
jc .deleted
stdcall __FreeConfigRecord, eax
stdcall DeleteArrayItems, [esi], edx, 1
mov [esi], edx
.deleted:
popad
return
endp
; set the value of the given config parameter.
; if the parameter exists, the value will be changed.
; if the parameter does not exists, it will be created.
proc SetConfigParam, .ptrVarConfig, .pDirectory, .name, .type, .value, .size
begin
push eax ecx edx esi edi
stdcall __GetParamArray, [.ptrVarConfig], [.pDirectory], 1
jc .missing_directory
mov esi, eax
stdcall __ScanParamArray, [esi], [.name]
jnc .record_ok
stdcall AddArrayItems, [esi], 1
mov [esi], edx
push [.name]
pop [eax+TConfigRecord.KeyName]
.record_ok:
mov esi, eax
stdcall __FreeConfigRecord, esi
movzx ecx, byte [.type]
and cl, $7
mov [esi+TConfigRecord.Type], ecx
movzx ecx, [.type_handlers+ecx]
add ecx, .type_handlers
call ecx
clc
.finish:
pop edi esi edx ecx eax
return
.missing_directory:
stc
jmp .finish
.type_handlers db .handle_null - .type_handlers
db .handle_int - .type_handlers
db .handle_string - .type_handlers
db .handle_blob - .type_handlers
db .handle_config - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
db .handle_blob - .type_handlers
.handle_int:
mov [esi+TConfigRecord.DataSize], 4
push [.value]
pop [esi+TConfigRecord.Data]
.handle_null:
retn
.handle_string:
stdcall StrDup, [.value]
mov [esi+TConfigRecord.Data], eax
stdcall StrLen, eax
mov [esi+TConfigRecord.DataSize], eax
retn
.handle_config:
stdcall CreateArray, sizeof.TConfigRecord
mov [esi+TConfigRecord.Data], eax
mov [esi+TConfigRecord.DataSize], 4
retn
.handle_blob:
mov ecx, [.size]
stdcall GetMem, ecx
mov [esi+TConfigRecord.Data], eax
mov [esi+TConfigRecord.DataSize], ecx
push esi
mov edi, eax
mov esi, [.value]
rep movsb
pop esi
retn
endp
endmodule