Page 1 of 2
Add MSet() function to string library
Posted: Mon Feb 24, 2025 10:42 pm
by Quin
I'm proposing a function similar to RSet or LSet, accept it would pad both sides of your string instead of just one until the specified length is reached.
Not much else needs said I think

Re: Add Set() function to string library
Posted: Tue Feb 25, 2025 2:21 am
by BarryG
Good idea!

I propose the name MSet(), with the "m" for "middle", to match LSet() and RSet().
A workaround for now:
Code: Select all
Procedure.s MSet(text$,length,char$=" ")
t=Len(text$)
If t>0 And length>t
pad=(length-t)/2
char$=Left(char$,1)
text$=RSet(char$,pad,char$)+text$+LSet(char$,pad,char$)
If Len(text$)<length
text$+char$
EndIf
EndIf
ProcedureReturn text$
EndProcedure
Debug "123456789.123456789.123456789.123456789.123456789."
Debug MSet("pad this to 50 chars",50,"-")
Output:
Code: Select all
123456789.123456789.123456789.123456789.123456789.
---------------pad this to 50 chars---------------
Re: Add Set() function to string library
Posted: Tue Feb 25, 2025 4:17 am
by idle
BarryG wrote: Tue Feb 25, 2025 2:21 am
Good idea!

I propose the name MSet(), with the "m" for "middle", to match LSet() and RSet().
A workaround for now:
Code: Select all
Procedure.s MSet(text$,length,char$=" ")
t=Len(text$)
If t>0 And length>t
pad=(length-t)/2
char$=Left(char$,1)
text$=RSet(char$,pad,char$)+text$+LSet(char$,pad,char$)
If Len(text$)<length
text$+char$
EndIf
EndIf
ProcedureReturn text$
EndProcedure
Debug "123456789.123456789.123456789.123456789.123456789."
Debug MSet("pad this to 50 chars",50,"-")
Output:
Code: Select all
123456789.123456789.123456789.123456789.123456789.
---------------pad this to 50 chars---------------
nice!
Re: Add Set() function to string library
Posted: Tue Feb 25, 2025 6:29 am
by DarkDragon
Set() could be confused with a set data structure.
Re: Add Set() function to string library
Posted: Tue Feb 25, 2025 11:33 am
by Quin
DarkDragon wrote: Tue Feb 25, 2025 6:29 am
Set() could be confused with a set data structure.
True, that's why I like BarryG's naming suggestion. Will update the topic with it

Re: Add Set() function to string library
Posted: Tue Feb 25, 2025 11:34 am
by Quin
BarryG wrote: Tue Feb 25, 2025 2:21 am
Good idea!

I propose the name MSet(), with the "m" for "middle", to match LSet() and RSet().
A workaround for now:
Code: Select all
Procedure.s MSet(text$,length,char$=" ")
t=Len(text$)
If t>0 And length>t
pad=(length-t)/2
char$=Left(char$,1)
text$=RSet(char$,pad,char$)+text$+LSet(char$,pad,char$)
If Len(text$)<length
text$+char$
EndIf
EndIf
ProcedureReturn text$
EndProcedure
Debug "123456789.123456789.123456789.123456789.123456789."
Debug MSet("pad this to 50 chars",50,"-")
Output:
Code: Select all
123456789.123456789.123456789.123456789.123456789.
---------------pad this to 50 chars---------------
Nice function! Thanks for sharing

Re: Add MSet() function to string library
Posted: Tue Feb 25, 2025 1:11 pm
by benubi
Just an other "branchless" version.
Code: Select all
Procedure.s MSet(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
ProcedureReturn (LSet("",l2,char$)+Left(text$,length)+LSet("",l2,char$))
EndProcedure
txt$=mset("Hello World",35,"*")
Debug txt$
Debug Len(txt$)
txt$=mset("Hello World",5,"*")
Debug txt$
Debug Len(txt$)
LSet/Rset has no problem accepting negative values, that does the little "trick" above.
Code: Select all
Debug LSet("",-3," ") ; No problem
Debug Space(-3) ; Debugger warning/error
Re: Add MSet() function to string library
Posted: Tue Feb 25, 2025 1:12 pm
by Quin
benubi wrote: Tue Feb 25, 2025 1:11 pm
Just an other "branchless" version.
Code: Select all
Procedure.s MSet(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
ProcedureReturn Left((LSet("",l2,char$)+Left(text$,length)+LSet("",l2,char$)),length)
EndProcedure
txt$=mset("Hello World",35,"*")
Debug txt$
Debug Len(txt$)
txt$=mset("Hello World",5,"*")
Debug txt$
Debug Len(txt$)
LSet/Rset has no problem accepting negative values, that does the little "trick" above.
Code: Select all
Debug LSet("",-3," ") ; No problem
Debug Space(-3) ; Debugger warning/error
Whoa, that's cool. The more you know! Thanks for sharing

Re: Add MSet() function to string library
Posted: Tue Feb 25, 2025 1:16 pm
by benubi
I just modified a little The Left() around all isn't necessary since there's the Left() between the Lset()'s. It may be glitchy (?) because you may want the middle part of "Hello world", "lo wo" or something, and here it returns the left part.
Update: I added Mset2() to return the center part
Code: Select all
Procedure.s MSet(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
ProcedureReturn (LSet("",l2,char$)+Left(text$,length)+LSet("",l2,char$))
EndProcedure
Procedure.s MSet2(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
Protected m2 = 1 + (Bool(l2<0)*l2*-1)
ProcedureReturn LSet("",l2,char$)+Mid(text$,m2,length)+LSet("",l2,char$)
EndProcedure
txt$=mset2("Hello World",35,"*")
Debug txt$
Debug Len(txt$)
txt$=mset2("Hello World",5,"*")
Debug txt$
Debug Len(txt$)
Re: Add MSet() function to string library
Posted: Tue Feb 25, 2025 1:26 pm
by BarryG
@benubi: Your code has a bug. It misses a padding character when the string is short:
benubi wrote: Tue Feb 25, 2025 1:16 pm
Code: Select all
Procedure.s MSet(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
ProcedureReturn (LSet("",l2,char$)+Left(text$,length)+LSet("",l2,char$))
EndProcedure
Procedure.s MSet2(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
Protected m2 = 1 + (Bool(l2<0)*l2*-1)
ProcedureReturn LSet("",l2,char$)+Mid(text$,m2,length)+LSet("",l2,char$)
EndProcedure
txt$=mset2("Hi",35,"*")
Debug txt$
Debug Len(txt$) ; 34 <- BUG
txt$=mset2("Hi",5,"*")
Debug txt$
Debug Len(txt$) ; 4 <- BUG
Re: Add MSet() function to string library
Posted: Tue Feb 25, 2025 1:32 pm
by benubi
@BarryG thanks for the feedback and the challenge. It makes me feel "competitive"
Now test this - it has all my "new best tricks"
Code: Select all
Procedure.s MSet2(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
Protected m2 = 1 + (Bool(l2<0)*l2*-1)
ProcedureReturn LSet("",l2,char$)+Mid(text$,m2,length)+LSet("",l2 + (length & 1),char$) ;
EndProcedure
txt$=mset2("Hi",35,"*")
Debug txt$
Debug Len(txt$) ;
txt$=mset2("Hi",5,"*")
Debug txt$
Debug Len(txt$) ;
txt$=mset2("Hi",32,"*")
Debug txt$
Debug Len(txt$) ;
txt$=mset2("Hi",3,"*")
Debug txt$
Debug Len(txt$) ;
Re: Add MSet() function to string library
Posted: Tue Feb 25, 2025 2:01 pm
by benubi
This version took me a little longer.
It is "branchless" and uses less String function calls (only 1 Lset to preallocate and pre-fill the result). This should be faster than the previous versions. But in practice I found it impossible to beat PB with most string functions like Hex() or Val() when I tried, the URLEncoders are the exception (I believe windows throttles it because of spam/viri and/or to better sell their faster server versions or so).
Code: Select all
Procedure.s MSet3(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
Protected m2 = (Bool(l2<0)*l2*-1)* SizeOf(Character)
Protected out$ = LSet("",length,char$)
Protected *Z1.character = @text$ + m2
Protected *Z2.character = @out$ + (Bool(l2>0)*l2*SizeOf(Character))
While *Z2\c And *Z1\c
*Z2\c = *Z1\c
*Z1+SizeOf(Character)
*Z2+SizeOf(Character)
Wend
ProcedureReturn out$
EndProcedure
txt$=mset3("Hi",35,"*")
Debug txt$
Debug Len(txt$) ;
txt$=mset3("Hi",5,"*")
Debug txt$
Debug Len(txt$) ;
txt$=mset3("Hi",32,"*")
Debug txt$
Debug Len(txt$) ;
txt$=mset3("Hi",2,"*")
Debug txt$
Debug Len(txt$) ;
Re: Add MSet() function to string library
Posted: Wed Feb 26, 2025 1:28 am
by BarryG
Both new versions work great!

Re: Add MSet() function to string library
Posted: Wed Feb 26, 2025 2:01 am
by Quin
BarryG wrote: Wed Feb 26, 2025 1:28 am
Both new versions work great!
Can confirm, incredibly impressive work. Gives me something to work towards in terms of my eventual PB skill level

Re: Add MSet() function to string library
Posted: Wed Feb 26, 2025 8:20 am
by PBJim
BarryG wrote: Wed Feb 26, 2025 1:28 am
Both new versions work great!
Not quite Barry, MSet3() is the only one that works. MSet() and MSet2() fail in the below cases.
Your own MSet() code was actually bug-free as you had anticipated the possibility of odd-numbered lengths, which Benubi hadn't.
Code: Select all
Procedure.s MSet(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
ProcedureReturn (LSet("",l2,char$)+Left(text$,length)+LSet("",l2,char$))
EndProcedure
Procedure.s MSet2(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
Protected m2 = 1 + (Bool(l2<0)*l2*-1)
ProcedureReturn LSet("",l2,char$)+Mid(text$,m2,length)+LSet("",l2 + (length & 1),char$) ;
EndProcedure
Procedure.s MSet3(text$,length,char$=" ")
Protected l2 = (length/2) - (Len(text$)/2)
Protected m2 = (Bool(l2<0)*l2*-1)* SizeOf(Character)
Protected out$ = LSet("",length,char$)
Protected *Z1.character = @text$ + m2
Protected *Z2.character = @out$ + (Bool(l2>0)*l2*SizeOf(Character))
While *Z2\c And *Z1\c
*Z2\c = *Z1\c
*Z1+SizeOf(Character)
*Z2+SizeOf(Character)
Wend
ProcedureReturn out$
EndProcedure
Debug "123456789.123456789."
Debug MSet("ABC",8,"-") ; Fails
Debug "123456789.123456789."
Debug MSet("ABCD",7,"-") ; Fails
Debug "===================="
Debug "123456789.123456789."
Debug MSet2("ABC",8,"-") ; Fails
Debug "123456789.123456789."
Debug MSet2("ABCD",7,"-")
Debug "===================="
Debug "123456789.123456789."
Debug MSet3("ABC",8,"-")
Debug "123456789.123456789."
Debug MSet3("ABCD",7,"-")