Structured strings and plain strings

Share your advanced PureBasic knowledge/code with the community.
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Structured strings and plain strings

Post by luis »

Sometimes when passing strings around, or mixing structured strings with normal strings, or using pointers, etc. the relationship between these different string representations may be confusing.

Maybe this can be of some help to someone.

Code: Select all

; a pb structured string is a structure like this
;
; Structure String
;  s.s
; EndStructure

; when you modify the s.s string, its address @s may change, because the string contents are reallocated somewhere else if required
; the base address of the structure never change

; a normal unstructured a$ string it's actually stored inside a structure too but that structure is not visible
; again the address of this string may change when modified 
; the base address of the "invisible" structure never change

; some pratical examples to explore these relationships (better go through them using the step debugger)

#SPACES = 64 ; this is to try to force a reallocation when updating the string, use a bigger number if required

; when using a structured string

Define a.string\s = "hello"

Debug @a ; base address of the PB string structure, the string is NOT in there, the structure contains just a pointer to the string

Debug @a\s ; this is the "PB way" to get the address of actual string
Debug PeekI(@a) ; this is equivalent to the above, you read the pointer located at the start of the structure

Debug a\s ; this is the "PB way" to print the string
Debug PeekS(@a\s) ; this is equivalent to the above
Debug PeekS(PeekI(@a)) ; and this too is equivalent to the above

a\s =  a\s + Space(#SPACES) + "world" ; if you modify the string ...
Debug a\s ; string is changed
Debug @a\s ; ... you'll see the address of the string is probably changed, because a new allocated string replaced the old one
Debug @a ; ... while the address of the structured string is still the same

Debug "--------------------"

; when using a plain string
; the string it's still part of a structured PB string, but the structure it's not directly accessible

Define a$ = "hello"

Debug @a$ ; this is the address of the actual string
Debug a$ ; this prints the string
Debug PeekS(@a$) ; so this is equivalent to the above
a$ = a$ + Space(#SPACES) + "world" ; if you modify the string ...
Debug a$ ; string is changed
Debug @a$ ; ... you'll see the address of the string is probably changed, because a new allocated string replaced the old one
Debug PeekS(@a$) ; so this is equivalent to the above

; the base address of the structured string is not changed, but you can't access it anyway
; ... unless you use some asm 

Define *p

CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
! lea ecx,[v_a$] ; this load the address of where the PB structured string containing a$ is in memory
! mov [p_p], ecx ; and copies it to *p
CompilerElse   
! lea rcx,[v_a$] ; this load the address of where the PB structured string containing a$ is in memory
! mov [p_p], rcx ; and copies it to *p
CompilerEndIf

Debug *p ; base address of the "invisible" PB string structure
Debug PeekI(*p) ; this is the pointer located at the start of the structure which points to a$
Debug PeekS(PeekI(*p)) ; and a$ contents are there

"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5353
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Structured strings and plain strings

Post by Kwai chang caine »

A very good and precious explanation about string :shock:
Need for me, several days of thinking :mrgreen:
Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Structured strings and plain strings

Post by davido »

@luis,
Excellent. Thank you for the explanation.
Always nice to learn something new.

Your input into this Forum is always welcome, in my humble opinion.
DE AA EB
Wolfram
Enthusiast
Enthusiast
Posts: 568
Joined: Thu May 30, 2013 4:39 pm

Re: Structured strings and plain strings

Post by Wolfram »

Thanks for this example.
I just stumbled on the problem yesterday.

Is your assambler code faster as this?

Code: Select all

*pp =@a$
*p =@*pp
Debug *p
Debug PeekI(*p)
Debug PeekS(PeekI(*p))
macOS Catalina 10.15.7
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Structured strings and plain strings

Post by luis »

@KCC, @Davido :wink:
Wolfram wrote:Thanks for this example.
I just stumbled on the problem yesterday.
That's why I posted this, and because I remembered these things are asked from time to time :)

About your question....

Uhm.. but my little asm code does an entirely different thing (?)

I'm not sure what's the purpose of your code.

Code: Select all

a$ = "hello"

*pp =@a$ ; you save in a pointer the address of the string, where the characters are stored ...

Debug @*pp ; you print the address of the pointer variable

Debug PeekI(@*pp) ; you read the value stored inside the pointer (what you saved with *pp=@a$), so the address of the string a$. PeekI(@*pp) is the same as *pp 

Debug PeekS(PeekI(@*pp)) ; you print the contents of the string a$
In my asm code, I was getting the address of the "invisible" structure containing the string. And from there I was getting the address of the string to show it is indeed there.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Structured strings and plain strings

Post by Lunasole »

Thanks for some interesting ASM magic

It looks safe to swap 2 strings this way, however that's not much usable on practice (as different macro needed to be used from procedures and outside) + anyway "Swap" does that already.

Well maybe someone will find another usage, I currently have no better ideas ^^ (except some crazy stuff like following:)

Code: Select all

EnableExplicit
; some dirty stuff
Define a$ = "1"
Define b$ = "2"
Define.Integer *p, *p1

CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
! lea ecx,[v_a$] ; this load the address of where the PB structured string containing a$ is in memory
! mov [p_p], ecx ; and copies it to *p
CompilerElse   
! lea rcx,[v_a$] ; this load the address of where the PB structured string containing a$ is in memory
! mov [p_p], rcx ; and copies it to *p
CompilerEndIf
CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
! lea ecx,[v_b$] ; this load the address of where the PB structured string containing a$ is in memory
! mov [p_p1], ecx ; and copies it to *p
CompilerElse   
! lea rcx,[v_b$] ; this load the address of where the PB structured string containing a$ is in memory
! mov [p_p1], rcx ; and copies it to *p
CompilerEndIf


; now a$ and b$ using the same memory
*p\i = *p1\i

; thus changing a$ or b$ will change both of them
; that's so... thoughtful ^^
b$ = "asdffffffffffffff"
Debug a$
a$ = "sssssssss"
Debug b$
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Structured strings and plain strings

Post by luis »

@Lunasole

ahahah I like your idea :wink:

In practice copying one pointer to another makes one string an ALIAS to the other, hence you have ONE string with TWO different names.

BTW if we want to split hairs in half (just for completeness), it is probably nice to set to #Null$ the string you are about to unlink from its original memory area to deallocate it or you end up with some orphaned memory (the original a$ contents).

Code: Select all

EnableExplicit

Macro GetStringStruct (a, p)
CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
! lea ecx,[a] ; this load the address of where the PB structured string containing a$ is in memory
! mov [p], ecx ; and copies it to *p
CompilerElse   
! lea rcx,[a] ; this load the address of where the PB structured string containing a$ is in memory
! mov [p], rcx ; and copies it to *p
CompilerEndIf
EndMacro

Define a$ = "1"
Define b$ = "2"
Define.Integer *pa, *pb

GetStringStruct (v_a$,p_pa)
GetStringStruct (v_b$,p_pb)

Debug a$
Debug b$

a$ = #Null$ ; free the original contents of a$

; unlink a$ from its memory area and link it to b$
*pa\i = *pb\i

; now a$ is an alias to b$
Debug @a$
Debug @b$

b$ = "123"
Debug a$
a$ = "456"
Debug b$
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
mk-soft
Always Here
Always Here
Posts: 5406
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Structured strings and plain strings

Post by mk-soft »

We can´t for procedures a string as argument byref, only with structure types, because the pointer to the string is change.

Edit

Code: Select all

;-TOP
Procedure foo(*inout.String, *value.integer)
  *inout\s + " 12345678"
  *value\i + 100
EndProcedure

Global t1.String
Global v1 = 100
t1\s = "hello world"
Debug PeekI(t1)
Debug PeekS(PeekI(t1))
foo(t1, @v1)
Debug PeekI(t1)
Debug PeekS(PeekI(t1))
Debug v1
See a way or features request
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply