; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "BSD 2-clause" license."          |
;|_______________________________________________________________________________________|
;
;  Description: Dynamic byte streams library.
;
;  Target OS: Any
;
;  Dependencies:
;
;  Notes: Based on works of Mateusz Tymek.
;_________________________________________________________________________________________

module "ByteStream"


struct TByteStream
  .capacity dd  ?
  .size     dd  ?
  .offset   dd  ?
  .lparam   dd  ?
  label .data byte
ends



; creates byte stream and returns pointer
; free it with FreeMem
proc BytesCreate, .length
begin
        push    ecx

        mov     ecx, [.length]
        add     ecx, sizeof.TByteStream

        stdcall GetMem, ecx
        jc      .finish

        sub     ecx, sizeof.TByteStream
        mov     [eax+TByteStream.capacity], ecx

        clc

.finish:
        pop     ecx
        return
endp



; returns the pointer at the begining of the requested block in EDI
; returns the stream pointer in EBX (it can be changed on reallocation)
proc BytesGetRoom, .pStream, .room
begin
        push    eax ecx edx

        mov     ebx, [.pStream]
        mov     edi, [ebx+TByteStream.offset]

        mov     edx, [.room]
        add     edx, edi             ; the total size needed

        cmp     edx, [ebx+TByteStream.capacity]
        jbe     .sizeok

        lea     ecx, [2*edx]
        lea     eax, [ecx+sizeof.TByteStream]

        stdcall ResizeMem, ebx, eax
        jc      .finish    ; CF=1

        mov     ebx, eax
        mov     [eax+TByteStream.capacity], ecx

.sizeok:
        mov     [ebx+TByteStream.offset], edx

        cmp     edx, [ebx+TByteStream.size]
        jbe     @f
        mov     [ebx+TByteStream.size], edx
@@:
        lea     edi, [edi+ebx+sizeof.TByteStream]
        clc

.finish:
        pop     edx ecx eax
        return
endp






proc BytesLoadFromFile, .ptrFileName
begin
        push    esi edi ebx ecx

        stdcall FileOpen, [.ptrFileName]
        jc      .error

        mov     edi, eax

        stdcall FileSize, edi
        jc      .errorclose

        mov     ebx, eax
        lea     ecx, [eax+8+sizeof.TByteStream]    ; It is for the case that the file is
                                                   ; text and we want to use it as null terminated
                                                   ; string.

        stdcall GetMem, ecx
        jc      .errorclose
        mov     esi, eax

        mov     eax, ebx

        mov     [esi + TByteStream.size], ebx
        mov     [esi + TByteStream.capacity], ebx

        lea     eax, [esi+TByteStream.data]
        stdcall FileRead, edi, eax, ebx
        jc      .errorclosemem

        stdcall FileClose, edi

        mov     eax, esi
        clc
        pop     ecx ebx edi esi
        return

.errorclosemem:
        stdcall FreeMem, esi

.errorclose:
        push    eax
        stdcall FileClose, edi
        pop     eax

.error:
        stc
        pop     ecx ebx edi esi
        return
endp




endmodule