Page 1 of 1

Simple functions for ASCII strings

Posted: Wed Jun 08, 2016 9:29 pm
by Little John

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

Re: Simple functions for ASCII strings

Posted: Wed Jun 08, 2016 9:47 pm
by DontTalkToMe
I don't understand.
What is this supposed to do ?
; This is a bit more flexible than using the function
; Ascii(), which is built-in in PB 5.50+.
Ascii() return a ascii buffer from an unicode string, to give the ability to access that ascii data. I don't see the equivalent here, unless you mean not through a public method but directly through the Addr structure's field ? Is it so ?

Don't know... I fail to see the usefulness compared to using just unicode strings and Ascii() when required.

Re: Simple functions for ASCII strings

Posted: Thu Jun 09, 2016 2:00 am
by Lunasole
I was using following 2 simple functions to work with ASCII in unicode program

Code: Select all

; *str   :   a pointer to PB unicode string, or any memory containing unicode string
; RETURN:   PB unicode string with ascii bytes order inside, equal to array of 1-byte chars
Procedure.s ToAscii (*str)
   Protected str$ = PeekS(*str, #PB_Default, #PB_Unicode)
   Protected out_len = 1 + Len(str$) / SizeOf(Character),  out$ = Space(out_len)
      PokeS(@out$, str$, #PB_Default, #PB_Ascii)
   ProcedureReturn out$
EndProcedure

; *str   :   pointer to a PB string returned by ToAscii(), or any ASCII string memory buffer
; RETURN:   PB unicode string. This function is just a wrapper for uniformity
Procedure.s ToUnicode (*str)
   ProcedureReturn PeekS(*str, #PB_Default, #PB_Ascii)
EndProcedure

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Define UNICODE_STRING.s        = "test this stuff"
Define ASCII_STRING.s 
      ASCII_STRING = ToAscii(@UNICODE_STRING); ASCII_STRING now is stored as ascii null-terminated string inside of PB unicode string. it can be sent to C/C++ code directly, but you can't see what it contains ^^

;print results
Debug ASCII_STRING             ; will show some unreadable text, because ascii string interpreted as unicode
Debug ToUnicode(@ASCII_STRING)    ; make string pure unicode again