Add MSet() function to string library

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Add MSet() function to string library

Post 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 :D
Last edited by Quin on Tue Feb 25, 2025 11:33 am, edited 1 time in total.
BarryG
Addict
Addict
Posts: 4121
Joined: Thu Apr 18, 2019 8:17 am

Re: Add Set() function to string library

Post 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---------------
User avatar
idle
Always Here
Always Here
Posts: 5834
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Add Set() function to string library

Post 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!
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: Add Set() function to string library

Post by DarkDragon »

Set() could be confused with a set data structure.
bye,
Daniel
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Add Set() function to string library

Post 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 :)
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Add Set() function to string library

Post 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 8)
benubi
Enthusiast
Enthusiast
Posts: 215
Joined: Tue Mar 29, 2005 4:01 pm

Re: Add MSet() function to string library

Post 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
Last edited by benubi on Tue Feb 25, 2025 1:13 pm, edited 1 time in total.
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Add MSet() function to string library

Post 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 :)
benubi
Enthusiast
Enthusiast
Posts: 215
Joined: Tue Mar 29, 2005 4:01 pm

Re: Add MSet() function to string library

Post 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$)
BarryG
Addict
Addict
Posts: 4121
Joined: Thu Apr 18, 2019 8:17 am

Re: Add MSet() function to string library

Post 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
benubi
Enthusiast
Enthusiast
Posts: 215
Joined: Tue Mar 29, 2005 4:01 pm

Re: Add MSet() function to string library

Post by benubi »

@BarryG thanks for the feedback and the challenge. It makes me feel "competitive" :lol:
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$) ; 
benubi
Enthusiast
Enthusiast
Posts: 215
Joined: Tue Mar 29, 2005 4:01 pm

Re: Add MSet() function to string library

Post 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$) ; 
BarryG
Addict
Addict
Posts: 4121
Joined: Thu Apr 18, 2019 8:17 am

Re: Add MSet() function to string library

Post by BarryG »

Both new versions work great! :)
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Add MSet() function to string library

Post 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 :D
PBJim
Enthusiast
Enthusiast
Posts: 294
Joined: Fri Jan 19, 2024 11:56 pm

Re: Add MSet() function to string library

Post 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. :D

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,"-")
Post Reply