Code: Select all
; tested with PB 5.42 LTS
DeclareModule ASCII
   ; -- *Simple* functions for using ASCII strings even
   ;    in programs that are compiled in Unicode mode;
   ; This is a bit more flexible than using the function
   ; Ascii(), which is built-in in PB 5.50+.
   
   Structure Str
      *Addr
      Len.i
   EndStructure
   
   Declare   Put (*s.Str, s$)
   Declare.s Get (*s.Str)
   Declare   Free (*s.Str)
   Declare   SetChunkSize (bytes.i)
EndDeclareModule
Module ASCII
   EnableExplicit
   
   Define s_ChunkSize.i = 1024
   
   
   Procedure Put (*s.Str, s$)
      Shared s_ChunkSize
      Protected *new, bytes.i, length.i=Len(s$)
      
      If *s\Addr = #Null Or MemorySize(*s\Addr) <= length
         bytes = Round(length/s_ChunkSize, #PB_Round_Up) * s_ChunkSize
         *new = ReAllocateMemory(*s\Addr, bytes+1, #PB_Memory_NoClear)
         If *new
            *s\Addr = *new
         Else   
            ProcedureReturn
         EndIf
      EndIf   
      
      PokeS(*s\Addr, s$, length, #PB_Ascii)
      *s\Len = length          ; Store the length for *quick* access.
   EndProcedure
   
   
   Procedure.s Get (*s.Str)
      ProcedureReturn PeekS(*s\Addr, *s\Len, #PB_Ascii)
   EndProcedure
   
   
   Procedure Free (*s.Str)
      FreeMemory(*s\Addr)
      *s\Addr = #Null
   EndProcedure
   
   
   Procedure SetChunkSize (bytes.i)
      ; The smaller the chunk size is, the more often ReAllocateMemory() will be called (which takes time).
      ; The bigger  the chunk size is, the more memory will be alloceted unnecessarily.
      ; The optimum chunk size depends on the details of the program that uses this module.
      Shared s_ChunkSize
      
      If bytes >= 1
         s_ChunkSize = bytes
      EndIf   
   EndProcedure   
EndModule
CompilerIf #PB_Compiler_IsMainFile
   ;-- Module demo
   
   EnableExplicit
   
   Define.ASCII::Str a, b, c
   
   ASCII::Put(a, "Hello World")
   Debug "'" + ASCII::Get(a) + "'"
   Debug "Length = " + a\Len
   Debug ""
   
   ASCII::Put(a, "Hello")
   Debug "'" + ASCII::Get(a) + "'"
   Debug "Length = " + a\Len
   Debug ""
   
   ASCII::Put(a, "A somewhat longer text, used for testing.")
   Debug "'" + ASCII::Get(a) + "'"
   Debug "Length = " + a\Len
   Debug ""
   
   ASCII::Put(b, "This is another string.")
   Debug "'" + ASCII::Get(b) + "'"
   Debug "Length = " + b\Len
   Debug ""
   
   ASCII::Put(c, ASCII::Get(a) + " " + ASCII::Get(b))
   Debug "'" + ASCII::Get(c) + "'"
   Debug "Length = " + c\Len
   Debug ""
   
   Debug "Address = " + a\Addr
   ASCII::Free(a)
   Debug "Address = " + a\Addr
CompilerEndIf
