Artifact faa9d4eca24da0fcc097f2ff9184f1370901fdc9:
- File
freshlib/data/uConfig.asm
— part of check-in
[47db564bdf]
at
2012-12-09 11:07:10
on branch uConfig
— The new uConfig library works pretty good. The API is still not clear,
because in this variant it is too complex and makes the library too fat.
Some changes was made is strlib.asm ( StrToNumEx procedure ) that need to be merged back to FreshLibDev branch. (user: johnfound size: 11388)
; _______________________________________________________________________________________ ;| | ;| ..::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" ; config data types. cdtNULL = 0 cdtInteger = 1 ; 32bit integer value. cdtString = 2 ; utf-8 string. cdtBlob = 3 ; arbitraty sized array of bytes. cdtDirectory = 4 cdtMaxAlowed = cdtDirectory ; Search for the given parameter in the database and return its value. ; ; arguments: ; .hData - handle of a string with the config database. ; .path - pointer or handle to the string with full path to the database element. ; ; returns: ; CF=0; eax=value of the element. edx - type of the element. id edx==cdtDirectory, the value of eax ; is unchanged. ; CF=1; the element not found. ; ; GetConfigRecord.__info.codesize proc GetConfigRecord, .hData, .path begin pushad stdcall StrPtr, [.hData] mov esi, eax stdcall StrPtr, [.path] mov edx, eax call __SearchData jc .exit cmp ah, ':' je .is_dir call .SkipSpaces ; skip to the stard of the text jc .is_null mov al, [esi] cmp al, '$' je .is_number cmp al, '0' jb .not_number cmp al, '9' jbe .is_number .not_number: ; cmp al, '#' ; je .is_blob .is_string: mov ecx, esi .outer_end: mov ebx, esi .end_loop: lodsb cmp al, $0d je .crlf cmp al, $0a je .crlf test al, al jz .crlf cmp al, ' ' je .end_loop jmp .outer_end .crlf: cmp ebx, ecx je .is_null mov ah, [ebx-1] mov al, [ecx] sub ebx, ecx cmp ebx, 1 jbe .extract cmp al, '"' je .quote cmp al, "'" jne .extract .quote: cmp al, ah jne .extract sub ebx, 2 inc ecx .extract: stdcall StrExtract, ecx, 0, ebx mov [esp+4*regEAX], eax mov dword [esp+4*regEDX], cdtString jmp .exit_ok .is_number: stdcall StrToNumEx, esi jc .is_string mov [esp+4*regEAX], eax mov dword [esp+4*regEDX], cdtInteger jmp .exit_ok .is_dir: mov dword [esp+4*regEDX], cdtDirectory jmp .exit_ok .is_null: mov dword [esp+4*regEDX], cdtNULL .exit_ok: clc .exit: popad return .SkipSpaces: lodsb test al, al jz .end_skip cmp al, ' ' je .SkipSpaces .end_skip: dec esi retn endp ; SetConfigRecord.__info.codesize proc SetConfigRecord, .hData, .path, .type, .data, .size .ins_pos dd ? begin pushad stdcall StrPtr, [.hData] mov esi, eax stdcall StrPtr, [.path] mov edx, eax call __SearchData jc .not_found stdcall StrPtr, [.hData] mov edi, eax ; search the bounds of the record... mov edx, esi sub edx, edi ; position of the record start. .end_loop: lodsb cmp al, $0d je .crlf cmp al, $0a je .crlf test al, al jnz .end_loop .crlf: dec esi sub esi, edi sub esi, edx ; length of the record stdcall StrSplit,[.hData], edx push eax stdcall StrSplit, eax, esi stdcall StrDel ; from the stack mov edx, eax ; the part of the string after the record. stdcall __CreateAsciiData, [.type], [.data], [.size] jc .restore stdcall StrCat, [.hData], eax .restore: stdcall StrCat, [.hData], edx stdcall StrDel, eax stdcall StrDel, edx clc popad return .not_found: ; search back the new line. ; int3 stdcall StrPtr, [.hData] mov edi, eax .back_loop: cmp esi, edi je .create_here dec esi mov cl, [esi] test cl, cl jz .create_here cmp cl, $0a je .create_here cmp cl, $0d jne .back_loop .create_here: sub esi, edi ; position inside the string. mov [.ins_pos], esi stdcall StrNew mov edi, eax dec edx test cl, cl jnz .scan_path stdcall StrCharCat, edi, $0a0d .scan_path: inc edx inc ebx jz @f inc ebx @@: mov esi, edx ; the remainer of the path .key_loop: lodsb cmp al, '/' je .record cmp al, '\' je .record test al, al jnz .key_loop ; record found .record: dec esi sub esi, edx mov ecx, ebx jecxz .indent_ok .ins_indent: stdcall StrCharCat, edi, ' ' dec ecx jnz .ins_indent .indent_ok: stdcall StrNew stdcall StrCopyPart, eax, edx, 0, esi stdcall StrCat, edi, eax stdcall StrDel, eax lea edx, [edx+esi] mov eax, '=' cmp byte [edx], 0 je @f mov eax, ':'+$0a0d00 @@: stdcall StrCharCat, edi, eax cmp byte [edx], 0 jne .ins_ready stdcall __CreateAsciiData, [.type], [.data], [.size] stdcall StrCat, edi, eax stdcall StrDel, eax .ins_ready: cmp byte [edx], 0 jne .scan_path stdcall StrSplit,[.hData], [.ins_pos] stdcall StrCat, [.hData], edi stdcall StrCat, [.hData], eax stdcall StrDel, eax clc popad return endp proc __CreateAsciiData, .type, .data, .size begin cmp byte [.type], cdtInteger je .number stdcall StrNew cmp byte [.type], cdtNULL je .finish cmp byte [.type], cdtBlob je .blob cmp byte [.type], cdtString jne .finish stdcall StrCopy, eax, [.data] .finish: return .number: push ecx mov ecx, [.type] and ecx, $ffffff00 stdcall NumToStr, [.data], ecx mov cl, byte [.type+1] cmp cl, $10 jne @f stdcall StrCharInsert, eax, '$', 0 @@: pop ecx return .blob: push ecx edx esi mov edx, eax mov esi, [.data] mov ecx, [.size] stdcall StrCharCat, edx, '#' jecxz .end_blob .loop: lodsb movzx eax, al stdcall NumToStr, eax, ntsHex + ntsFixedWidth + 2 stdcall StrCat, edx, eax stdcall StrDel, eax loop .loop .end_blob: mov eax, edx pop esi edx ecx return endp ; __SearchData.__info.codesize ; ; Arguments: ; esi - pointer to the text of the database ; edx - pointer to the path string ; Returns: ; CF=0 if the path is found. ; esi - pointer to the value. ; ah=":" if the path is directory. ; ah="=" if the path is data field. ; ; CF=1 the path was not found. ; esi - points to the first row after the end of the block where the path ; is supposed to be (but is not). ; edx - points to the remainder of the path that was not found. proc __SearchData begin mov edi, edx xor ebx, ebx ; current block indent dec ebx .outer_loop: ; compute the line indent mov ecx, esi .scan_indent: lodsb test al, al jz .end_of_file cmp al, ' ' je .scan_indent jb .outer_loop cmp al, ';' jne .indent_ok ; skips to the end of the line. .SkipIt: lodsb cmp al, ' ' jb .outer_loop test al, al jnz .SkipIt .end_of_file: dec esi .error: stc return .indent_ok: dec esi sub ecx, esi neg ecx ; Here the indent of the current line is in ECX. cmp ecx, ebx jle .error ; if the current indent is less of equal than the block ; indent, then the needed element can not be found. cmp ecx, edi ja .SkipIt ; the current indent is above the current upper limit, so ; the whole line have not to be processed. mov edi, edx ; the start of the current path (it is always greater than the current indeent) .key_loop: mov al, [edi] inc edi mov ah, [esi] inc esi test al, al jz .maybe_end_of_path cmp al, '/' je .key_maybe_found cmp al, '\' je .key_maybe_found test ah, ah jz .end_of_file cmp al, ah je .key_loop ; not this, so check the current line whether it is a directory. .not_this: dec esi .dir_loop: lodsb test al, al jz .end_of_file cmp al, ' ' jb .outer_loop je .SkipIt cmp al, '=' je .SkipIt cmp al, ':' jne .dir_loop mov edi, ecx ; it is a subdirectory, that is not in the path, ; so set the upper limit. jmp .SkipIt .maybe_end_of_path: cmp ah, '=' je .found .key_maybe_found: cmp ah, ':' jne .not_this test al, al jz .found ; the searched path is subdirectory, not a record. mov edx, edi ; the subdirectory was found. Set new path and block indent. mov ebx, ecx jmp .SkipIt .found: ; the whole path was found. clc return endp endmodule