Please speed up this string operation

Just starting out? Need help? Post your questions and find answers here.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Please speed up this string operation

Post by wilbert »

Here's my attempt

Code: Select all

#SOC=SizeOf(Character)

Procedure.i GetLongestLine(*c.Character, *numlines.Integer=0)
  Protected.i l, n, s
  While *c\c
    If *c\c=#LF
      If s>l : l=s : EndIf
      s=0 : n+1
    ElseIf *c\c<>#CR
      s+1
    EndIf
    *c+#SOC
  Wend
  If s ; For last line without #LF at end.
    If s>l : l=s : EndIf
    n+1
  EndIf
  If *numlines : *numlines\i=n : EndIf
  ProcedureReturn l
EndProcedure

Procedure.s Decorated(*t.Character)
  Protected.i l, n, maxlen, numlines, *c.Character
  Protected.i x, y, w, h
    
  maxlen = GetLongestLine(*t, @numlines)
  
  w = maxlen + 22   ; desired width for text canvas
  h = numlines + 7  ; desired height for text canvas
  x = 11            ; desired x for text
  y = 2             ; desired y for text
  
  ; minimum decoration height is 11 lines
  If h < 11 : h = 11 : EndIf
  
  ; >> create blank canvas <<
  Protected Dim c.c(h,w+1)
  FillMemory(@c(0,0), w*#SOC, 32, #PB_Character)
  c(0,w) = #CR : c(0,w+1) = #LF
  n=h-1 : For l=1 To n
    CopyMemory(@c(0,0), @c(l,0), (w+2)*#SOC)
  Next
  
  ; >> write text to canvas <<
  l=y : *c=@c(l,x)
  While *t\c
    If *t\c=#LF
      l+1 : *c=@c(l,x)
    ElseIf *t\c<>#CR
      *c\c=*t\c : *c+#SOC
    EndIf
    *t+#SOC
  Wend    
    
  ; >> decorate <<
  n=h-4
  PokeS(@c( 0,0),  "  .------", -1, #PB_String_NoZero)
  PokeS(@c( 1,0),  " /  .-.  ", -1, #PB_String_NoZero)
  PokeS(@c( 2,0),  "|  /   \ ", -1, #PB_String_NoZero)
  PokeS(@c( 3,0),  "| |\_.  |", -1, #PB_String_NoZero)
  PokeS(@c( 4,0),  "|\|  | /|", -1, #PB_String_NoZero)
  PokeS(@c( 5,0),  "| `---' |", -1, #PB_String_NoZero)
  For l = 6 To n
    PokeS(@c(l,0), "|       |", -1, #PB_String_NoZero)
  Next
  PokeS(@c(n+1,0), "\       |", -1, #PB_String_NoZero)
  PokeS(@c(n+2,0), " \     / ", -1, #PB_String_NoZero)
  PokeS(@c(n+3,0), "  `---'  ", -1, #PB_String_NoZero)
  
  PokeS(@c( 0,w-9),  "-------. ", -1, #PB_String_NoZero)
  PokeS(@c( 1,w-9),  "  .-.   \", -1, #PB_String_NoZero)
  PokeS(@c( 2,w-9),  " /   \  |", -1, #PB_String_NoZero)
  PokeS(@c( 3,w-9),  "|    /| |", -1, #PB_String_NoZero)
  PokeS(@c( 4,w-9),  "|\  | |/|", -1, #PB_String_NoZero)
  PokeS(@c( 5,w-9),  "| `---' |", -1, #PB_String_NoZero)
  For l = 6 To n
    PokeS(@c(l,w-9), "|       |", -1, #PB_String_NoZero)
  Next
  PokeS(@c(n+1,w-9), "|       /", -1, #PB_String_NoZero)
  PokeS(@c(n+2,w-9), " \     / ", -1, #PB_String_NoZero)
  PokeS(@c(n+3,w-9), "  `---'  ", -1, #PB_String_NoZero)  
  l=n
  For n=9 To w-10 : c(0,n)='-' : c(l,n)='-' : Next
  
  ; return decorated text
  ProcedureReturn PeekS(@c(0,0))
EndProcedure


text$="One"+#CRLF$
text$+"Two"+#CRLF$
text$+"Three"+#CRLF$

Debug Decorated(@text$)
Windows (x64)
Raspberry Pi OS (Arm64)
infratec
Always Here
Always Here
Posts: 6883
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Please speed up this string operation

Post by infratec »

Fixed a bug in my last code with TextLineDistance.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Please speed up this string operation

Post by Dude »

Thanks guys, for your help. :) The speed of both examples are great: less than one second, whereas mine took minutes.

I decided to go with wilbert's example because I found it just that bit easier to understand and adapt (sorry infratec!).

For example, here's how I adapted wilbert's code to "upgrade" my very slow Boxed() procedure:

Code: Select all

#SOC=SizeOf(Character)

Procedure.i GetLongestLine(*c.Character, *numlines.Integer=0)
  Protected.i l, n, s
  While *c\c
    If *c\c=#LF
      If s>l : l=s : EndIf
      s=0 : n+1
    ElseIf *c\c<>#CR
      s+1
    EndIf
    *c+#SOC
  Wend
  If s ; For last line without #LF at end.
    If s>l : l=s : EndIf
    n+1
  EndIf
  If *numlines : *numlines\i=n+1 : EndIf
  ProcedureReturn l
EndProcedure

Procedure.s Boxed(*t.Character)
  
  Protected.i l, n, maxlen, numlines, *c.Character
  Protected.i x, y, w, h
  
  maxlen = GetLongestLine(*t, @numlines) + 1
  
  w = maxlen + 2    ; desired width for text canvas
  h = numlines + 1  ; desired height for text canvas
  x = 2             ; desired x for text
  y = 1             ; desired y for text
  
  ; >> create blank canvas <<
  Protected Dim c.c(h,w+1)
  FillMemory(@c(0,0), w*#SOC, 32, #PB_Character)
  c(0,w) = #CR : c(0,w+1) = #LF
  n=h-1
  For l=1 To n
    CopyMemory(@c(0,0), @c(l,0), (w+2)*#SOC)
  Next
  
  ; >> write text to canvas <<
  l=y : *c=@c(l,x)
  While *t\c
    If *t\c=#LF
      l+1 : *c=@c(l,x)
    ElseIf *t\c<>#CR
      *c\c=*t\c : *c+#SOC
    EndIf
    *t+#SOC
  Wend
  
  ; >> decorate top line <<
  PokeS(@c(0,0),  "+-", -1, #PB_String_NoZero)
  For n = 2 To maxlen : c(0,n)='-' : Next
  PokeS(@c(0,n), "-+", -1, #PB_String_NoZero)

  ; >> decorate sides <<
  rside = maxlen + 2
  For l = 1 To numlines
    PokeS(@c(l,0), "|", -1, #PB_String_NoZero) ; Left side.
    PokeS(@c(l,rside), "|", -1, #PB_String_NoZero) ; Right side.
  Next
  
  ; >> decorate bottom line <<
  PokeS(@c(numlines,0),  "+-", -1, #PB_String_NoZero)
  For n = 2 To maxlen : c(numlines,n)='-' : Next
  PokeS(@c(numlines,n), "-+", -1, #PB_String_NoZero)  

  ProcedureReturn PeekS(@c(0,0))
  
EndProcedure

text$=GetClipboardText()

Debug Boxed(@text$)
Post Reply