News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

how to implement auto sizing strings

Started by mhmooney, July 18, 2020, 09:40:21 AM

Previous topic - Next topic

mhmooney

Have a hobby parser, code generator that shells to masm32 to create a exe. Im trying to figure out the best way to do a basic string, bstr, ansi, maybe unicode, something that I can automatically resize as needed. I assume id create a  pointer to a memory block to hold the string. Guess my question is should I use stack based, malloc, or heap. Im interested in any intuition on how to implement and other considerations.

fearless

This might help: https://www.quora.com/How-does-C++-implement-a-string
Have a field that contains a pointer to the buffer that contains the text and a field that contains the size of the buffer used in the "string". Can then code functions to take the address and look for the pointer and size for fields based on that structure.

TouEnMasm

THe number of bstr is limited by the size in dword of bstr_array
Quote
; #########################################################################

      .386                      ; force 32 bit code
      .model flat, stdcall      ; memory model & calling convention
      option casemap :none      ; case sensitive

      ; -------------------------------------------------------------------
      ; Les fichiers inclus içi ,AUCUN .lib c'est au programme utilisateur
      ;   de les fournir
      ; -------------------------------------------------------------------
       include \masm32\include\windows.inc
   include \masm32\include\kernel32.inc
   include \masm32\include\oleaut32.inc
      ; include \masm32\include\gdi32.inc
      ; include \masm32\include\user32.inc
      ;   include \masm32\include\kernel32.inc
      ; include perso32.inc
      ;  include macros.txt   

      ; ---------------------------------------------------------
      ; Les PROTO sont tous regroupés dans un fichier .inc du même
      ; nom que la librairie .lib
      ; ---------------------------------------------------------

      ; CreateBstr PROTO :DWORD
   ; FreeBSTR PROTO
   ;UtoA PROTO  :DWORD
   ;AtoU PROTO  :DWORD

   ;BSTR MACRO arg
   ;   invoke CreateBstr,SADR(arg)
   ;   EXITM<eax>
   ;ENDM

      ;exemples de definitions externes
      ;    EXTERNDEF Copier :PROTO  :DWORD,:DWORD
      ;    EXTERNDEF EtatMemoirePile :MEMORY_BASIC_INFORMATION
      ;    EXTERNDEF PoriginePile:DWORD         
   
   .data   
bstr_array dd 50 dup (0)
buffer db MAX_PATH dup (0)
ubuffer dw MAX_PATH dup (0)
    .code

;################################################################
UtoA PROC  pChain:DWORD
   invoke WideCharToMultiByte,CP_ACP,NULL,pChain,\
      -1,addr buffer,LENGTHOF buffer,NULL,NULL
   .if eax != 0
      mov edx,eax
      lea eax,buffer
   .endif              
         ret
UtoA endp

;################################################################

AtoU PROC  pChain:DWORD
   invoke MultiByteToWideChar,CP_ACP,NULL,pChain,\
      -1,addr ubuffer,LENGTHOF ubuffer
   .if eax != 0
      mov edx,eax
      lea eax,ubuffer
   .endif       
         ret
AtoU endp


;################################################################
;use bstr_array in data
CreateBstr PROC  pChain:DWORD 
         Local  retour:DWORD
         Local   phrase[MAX_PATH]:WORD
   mov eax,pChain
   invoke MultiByteToWideChar,CP_ACP,NULL,pChain,\
      -1,addr phrase,LENGTHOF phrase 
   invoke SysAllocString,addr phrase
   mov retour,eax   
   .if eax == 0
      ;invoke MessageBox,NULL,SADR("FAILED"),SADR("MultiByteToWideChar"),MB_OK
      jmp FindeCreateBstr
   .endif
   ;---------------- save pointer in an array BSTR -----------------
   lea edx,bstr_array
   .LISTALL
   mov ecx,LENGTHOF bstr_array
   .NOLIST
   @@:
   .if dword ptr [edx] == 0
      mov [edx],eax
   .else
      dec ecx
      .if ecx != 0   ;not the end of array
         add edx,4
         jmp @B
      .else
         ;failed to save bstr pointer         
         ;invoke MessageBox,NULL,SADR("BSTR array too small"),SADR("ERREUR"),MB_OK
         invoke SysFreeString,retour
         mov retour,0         
      .endif
   .endif
FindeCreateBstr:
         mov eax,retour
         ret
CreateBstr endp

;################################################################
;use bstr_array in data
FreeBSTR PROC uses esi
         Local count:DWORD
         Local  retour:DWORD
         mov retour,1
   mov ecx,LENGTHOF bstr_array
   mov count,ecx
   lea esi,bstr_array
   @@:
   .if dword ptr [esi] != 0
      mov edx,dword ptr [esi]
      invoke SysFreeString,edx
      mov dword ptr [esi],0
      add esi,4
      dec count
      jnz @B
   .endif
FindeFreeBSTR:
         mov eax,retour
         ret
FreeBSTR endp


; #########################################################################

end

Fa is a musical note to play with CL

mhmooney

Thanks for the responses, gives me a starting point to consider.

TouEnMasm

Very simple.
Quote
invoke CreateBstr,addr phrase  ; phrase db "bla blate ",0     could be repeat size of bstr_array in dword(50 times)
                                              ;the bstr is in eax (or 0 if failed) and in the bstr_array
;When you have finished used them
invoke FreeBSTR         ;all bstr in bstr_array are free and the bstr_array is initialized to 0
Fa is a musical note to play with CL

jj2007

Quote from: mhmooney on July 18, 2020, 09:40:21 AMIm trying to figure out the best way to do a basic string, bstr, ansi, maybe unicode, something that I can automatically resize as needed

BSTRs in Windows are a can of worms, just try googling "bstr" and ignore the first 5 hits pointing to official Micros**t docs - an astonishing number of people have problems with them. In Windows, they are needed for COM and almost nothing else (I attach a 29-lines demo, building needs the MasmBasic library)

But I suppose your focus was on "automatically resize as needed". Something like this?

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init

  Let esi="A string"
  PrintLine esi

  Let esi="This is "+Lower$(esi)
  PrintLine esi

  Let esi=esi+" created "+Date$+", "+Time$
  PrintLine esi
 
  Let esi=Left$(esi, 5)+"text was"+Mid$(esi, 17)
  PrintLine esi

  Inkey
EndOfCode


Output:
A string
This is a string
This is a string created 20.07.2020, 15:17:52
This text was created 20.07.2020, 15:17:52


You need macros to do that, and it's not that trivial. What exactly do you need it for?

mhmooney

I am just researching whether I need to do bstr, or do a c style string. It appears c style should suffice. Id like to do str1=str1+str2  and other string operators and have the code gen spit out the code needed to allocate, reallocate and free once I am ready to leave the current scope of the variable . Seems alloc$,cat$ and free$ macros do a fine job (not to mention all the other string macros available). Thanks for everyone's input

hutch--

If you have a use for it, the BSTR format works OK, it done like an old PASCAL string where the character count is in the first 4 bytes and the character data is written directly after it. It is OLE string and is generally associated with BASIC style string manipulation where when you modify a string that increases its length, it re-allocates the memory and sets the length at the first 4 bytes.

You have to build a string engine to use it properly like basic which few would bother with as zero terminated strings work fine in both ANSI and UNICODE so there may be no point in doing that much work.

TouEnMasm

BSTR are much used in com.
There are small chain (or what else you want) put in a shared memory.
This allow further independants programs to communicate.
This shared memory is small and you have also to keep the bstr small.

Fa is a musical note to play with CL