News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Split Macro or Function needed

Started by kyo, August 20, 2006, 06:59:02 AM

Previous topic - Next topic

kyo

How we split a string in to Pieces for general purpose string operations
here is a vb example i want to make asm convertion for that . How do i do so?

Private Sub Form_Load()
Dim FullString As String

Dim MainSetting() As String
Dim SubSetting1() As String
Dim SubSetting2() As String

FullString = "MainSetting1<>M1_SubSetting1<>M1_SubSetting2{}MainSetting2<>M2_SubSetting1<>M2_SubSetting2"

MainSetting = Split(FullString, "{}")
SubSetting1 = Split(MainSetting(0), "<>")
SubSetting2 = Split(MainSetting(1), "<>")

MsgBox MainSetting(0)
For i = 0 To UBound(SubSetting1)
    MsgBox SubSetting1(i)
Next
MsgBox MainSetting(1)
For i = 0 To UBound(SubSetting2)
    MsgBox SubSetting2(i)
Next


End Sub



what it does  "MainSetting1<>M1_SubSetting1<>M1_SubSetting2{}MainSetting2<>M2_SubSetting1<>M2_SubSetting2"

is the main string
1- first it splits  it in the array MainSetting (n) ; n are the number of string it finds

2- MainSetting1(0) t splits  in the array SubSetting1(n) ; n are the number of string it finds

3- MainSetting1(1) t splits  in the array SubSetting1(n) ; n are the number of string it finds

4- Finally display resulted setting in the message

Now how do we convert this in the asm code.Is there any macro to do split operations using delimiter.eg."{}"or "<>" or any one which we want to use.

hutch--

kyo,

What are the forms of the input string and what form must the individual outputs be. I don't have a dialect of basic handy that has the "split" function so I don't know what its supposed to look like.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

kyo

Input is the simple string.(does not matters what ever it is) Split divides the string where it finds  delimiter.eg."{}"or "<>" or " " or "&" * or any one which we want to use.removes the delimiter and copies the parts to the MainString(n)= the parts of the splited strings. Out put is in the same form as the input is.  The example i gave is fully working in the vb6 copy it to the form code and run it you will see the results.


Jackal

What it does is takes a string and splits it into an array where it finds the specified delimiter. For exaple if i had the string "This is a test" and used the split function with the delimiter being char(32) which i believe is the space then i would have the following

string[0] = This
string[1] = is
string[2] = a
string[3] = test


the vb code would actually be string = split("This is a test", chr(32)) or something close... been awhile since i used vb as i found masm to be much better and i like the speed and not needed to have the extra runtime files and such.

Jackal

here is a vc++ function i wrote that does close to the same thing as he wants.


void CJIrcView::GetColor(LPCTSTR itmName)
{

CString Path(*__argv);
int i = Path.ReverseFind('\\') + 1;
if(i) Path = Path.Left(i);

vm_strINIFile = Path + _T("JClient.ini");
vm_strSectionName = _T("COLOURS");

GetPrivateProfileString((LPCTSTR)vm_strSectionName,(LPCTSTR)itmName, "0,0,0;", vm_lRetValue, 255, (LPCTSTR)vm_strINIFile);

const char delimiters[] = ",;";

        char *token;

token = strtok (vm_lRetValue, delimiters);
vm_RedCode = atoi(token);

token = strtok (NULL, delimiters);
        vm_GreenCode = atoi(token);

token = strtok (NULL, delimiters);
        vm_BlueCode = atoi(token);

}

ToutEnMasm

Hello,
If I understand well the split function take the string between to delimiters and make a concatenation of the strings Found ?.
That's not very difficult to simulate with standard asm,perhaps the MID function is missing in masm32 but i am not sure.
                                      ToutEnMasm

hutch--

Best guess at the moment gets something like this.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    bcopy PROTO :DWORD,:DWORD

    .data?
      value dd ?

    .data
      item db "MainSetting1 SubSetting11 SubSetting12",13,10
           db "MainSetting2 SubSetting21 SubSetting22",13,10
           db "MainSetting3 SubSetting31 SubSetting32",13,10
           db "MainSetting4 SubSetting41 SubSetting42",13,10
           db "MainSetting5 SubSetting51 SubSetting52",13,10
           db "MainSetting6 SubSetting61 SubSetting62",13,10
           db "MainSetting7 SubSetting71 SubSetting72",13,10
           db "MainSetting8 SubSetting81 SubSetting82",0

    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main
    inkey
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    LOCAL array1    :DWORD
    LOCAL cnt1      :DWORD
    LOCAL array2    :DWORD
    LOCAL npos      :DWORD
    LOCAL pbuf      :DWORD
    LOCAL pbuf1     :DWORD
    LOCAL buffer[128]:BYTE
    LOCAL buffer1[128]:BYTE

    push esi
    push edi

    mov cnt1, rv(ltok,OFFSET item,ADDR array1)

    mov esi, array1
    sub esi, 4

  @@:
    add esi, 4
    mov pbuf, ptr$(buffer)

    invoke bcopy,[esi],pbuf
    print pbuf,13,10

    mov npos, 0

    mov pbuf1, ptr$(buffer1)
    mov npos, rv(ArgByNumber,pbuf,pbuf1,1,npos)
    print "arg1 = "
    print pbuf1,13,10

    mov pbuf1, ptr$(buffer1)
    mov npos, rv(ArgByNumber,pbuf,pbuf1,1,npos)
    print "arg2 = "
    print pbuf1,13,10

    mov pbuf1, ptr$(buffer1)
    mov npos, rv(ArgByNumber,pbuf,pbuf1,1,npos)
    print "arg3 = "
    print pbuf1,13,10,13,10

    sub cnt1, 1
    jnz @B

    free array1
    free array2

    pop edi
    pop esi

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

bcopy proc src:DWORD,dst:DWORD

    push ebx

    mov eax, src
    mov ecx, dst
    xor edx, edx

  @@:
    mov bl, [eax+edx]
    mov [ecx+edx], bl
    add edx, 1
    test bl, bl
    jnz @B

    pop ebx

    ret

bcopy endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start


Which delivers this output.


MainSetting1 SubSetting11 SubSetting12
arg1 = MainSetting1
arg2 = SubSetting11
arg3 = SubSetting12

MainSetting2 SubSetting21 SubSetting22
arg1 = MainSetting2
arg2 = SubSetting21
arg3 = SubSetting22

MainSetting3 SubSetting31 SubSetting32
arg1 = MainSetting3
arg2 = SubSetting31
arg3 = SubSetting32

MainSetting4 SubSetting41 SubSetting42
arg1 = MainSetting4
arg2 = SubSetting41
arg3 = SubSetting42

MainSetting5 SubSetting51 SubSetting52
arg1 = MainSetting5
arg2 = SubSetting51
arg3 = SubSetting52

MainSetting6 SubSetting61 SubSetting62
arg1 = MainSetting6
arg2 = SubSetting61
arg3 = SubSetting62

MainSetting7 SubSetting71 SubSetting72
arg1 = MainSetting7
arg2 = SubSetting71
arg3 = SubSetting72

MainSetting8 SubSetting81 SubSetting82
arg1 = MainSetting8
arg2 = SubSetting81
arg3 = SubSetting82

Press any key to continue ...
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

kyo

hutch--

Split and join are 2 very important functions and you should include them in the high level string macros. I just checked the help of high level  left$ and righ$ macros are there but mid$ is also missing.
You should also make Split$ Join$ and Mid$ macros. These perform very important tasks.

Join does the reverse of split it adds all arrays to a string with the delimiter supplied.

string[0] = This
string[1] = is
string[2] = a
string[3] = test

rslt = Join(string()," ")

rslt =This is a test ; ans would be like that

hutch--

kyo,

There is a mid procedure in the masm32 library.


szMid proc source:DWORD, substring:DWORD, stPos:DWORD, ln:DWORD


VB emulation is not exactly what you are after as its architecture has it has a different set of assumptions. The macros handle the easy stuff with no problems but where speed matters, there are faster ways of doing most of this stuff.

In the masm32 subforum is a posting that has two (2) very high speed tokenisers, one for lines and one for seperate words. The example I posted used the line tokeniser and a sequential word parser "ArgByNumber".

If you are committed to VB style string arrays, you are probably stuck with VB style performance but if you need improved performance, you will need to think of the layout in a different way.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

ToutEnMasm

Hello,
join is made,with no limits in number and size of strings.Just limit by the size of memory.
WriteToMemHeap is a function tha i have posted here
Give me a real string to split and i make the function split.



.data
string db "This",0   ;asciiz
db "is",0
db "a",0
db "test",0           
db 0            ;end list
memheap MEMHEAP <>
separetor db " ",0
.code
;@@@@@@@@@@@@@@@@@@@@@@@      POINT d'ENTREE  du code, start:    @@@@@@@@@@@@@@@@@@@@@@
start:

invoke join,addr string,addr separetor,addr memheap
;affiche

;free memory
.if dword ptr memheap.Pheap != 0   ;&& eax != 0
invoke MessageBox,NULL,memheap.Pheap,SADR("Titre"),MB_OK
invoke WriteToMemHeap,addr memheap,NULL,NULL
.endif

invoke ExitProcess,0
;@@@@@@@@@@@@@@@@@@@@@@@      POINT de sortie  du code     @@@@@@@@@@@@@@@@@@@@@@@
;################################################################
join PROC uses esi edi ebx pstrings:DWORD,pseparetor:DWORD,pheap:DWORD
local phrase[MAX_PATH+1]:BYTE
Local  retour:DWORD

mov retour,0
mov esi,pstrings
@@:
.if byte ptr [esi] != 0
invoke lstrcpy,addr phrase,esi
invoke lstrcat,addr phrase,pseparetor
invoke WriteToMemHeap,pheap,addr phrase,NULL
.if eax != 0
mov retour,1
;success,is another ?
mov edi,esi
mov ecx,MAX_PATH
mov al,0
cld
repnz scasb
;edi pointer on the new string
mov esi,edi
jmp @B
.else
;failed
mov ebx,pheap
.if dword ptr [ebx][MEMHEAP.Pheap] != 0
;free memory
invoke WriteToMemHeap,pheap,NULL,NULL
.endif
mov retour,0
.endif   
.endif
Findejoin:
mov eax,retour
ret
join endp


kyo

ToutEnMasm

:bg good if it works but it gives error to me which lib in have to inlude for WriteToMemHeap api.
to split you can use same string "This is a test" and use " " space as delimiter , get it back
This,0
is,0
a,0
test,0

and a question what happens if its binary i mean 0 is in the text or input or string in case bin operation.

ToutEnMasm

Hello,
It's work with no problems.
To have the function WriteToMemHeap follow this link,it's here.
http://www.masm32.com/board/index.php?topic=2253.msg17776#msg17776

If you want to put the NULL caracter as separator,modify a little the function.

original code

.if byte ptr [esi] != 0
invoke lstrcpy,addr phrase,esi
invoke lstrcat,addr phrase,pseparetor
invoke WriteToMemHeap,pheap,addr phrase,NULL



new code

.if byte ptr [esi] != 0
invoke lstrcpy,addr phrase,esi
                                mov ebx,pseparetor
                                .if byte ptr [ebx] != 0
      invoke lstrcat,addr phrase,pseparetor
                               .endif
invoke WriteToMemHeap,pheap,addr phrase,NULL



in data write
.data
separetor db 0,0

For the list of strings,you must terminate the list by a zero,there is no other choice.

                                         ToutEnMasm