Might be useful if you need to work with multiple string formats and can't remember the ins and outs.
logic may be a bit bent so feel free to modify and add to it.
Facilitates using strings in any format, which may be useful when interacting with external libs
that require either utf8, unicode, wchar, ascii or Bstr
Needs testing on OSX may need imports fixed
Windows see if the Chinese prints, doesn't do it on xp vm but probably the font or local settings!
v1.3
Added Bstr
fixed catchXstring
v1.2
added
AddXString
AppendXString
LeftXString
MidXString
RightXString
ClearXString
v1.1
Added CopyXstring
Code: Select all
;;======================================================================
; Module: ModXString.pbi
; Author: Idle
; Date: Aug 08, 2013
; Version: 1.3
; Target Compiler: PureBasic 5.2+
; Target OS: Linux, OSX, Windows
;Compiler Mode Unicode
; License: Free, unrestricted, no warranty whatsoever ,use at your own risk
;
; Description multi type string wrangller
; Useage
;
; *str.Xstring = NewXString(pbString,xStringType)
; makes a string of the desired type where type can be Ascii, unicode, utf8, wchar,Bstr
;
; *str.Xstring = CatchXString(*ptr,xStringCastType,xStringSourceType=0,len=-1)
; catch a string from memory or data , len may need to be specified
;
; pbstring = PeekXString(*string.XString)
; returns a gui printable string from a given xstring, assumes you've compiled in unicode mode unless the strings are printable in ascii values
;
; *newXstring = CopyXString(*src.xstring,*dest.xString=0,typecast=0)
; copys an xString returns the pointer to the new or replaced xstring
; ;dest can be null of an existing xstring
; ;typecast allows you to overide and cast dest to the specified format
;
; *newXstring = AppendXString(*str.xstring,text.s,xStringType=0)
; add text to the string and optionlly recast it, returns a new string
;
; *newXstring = AddXString(*a.xstring,*b.xstring,xStringType=0)
; joins two xtrigns together returning the new string optioanlly casting it
;
; *newXstring = LeftXString(*str.xString,len,xStringType=0)
; returns the left portion of a string optional casting to it
;
; to pass an xString to an external libray function, pass the strings char buffer pointer
; *str\char
;
; to get an xString from an external library function use CatchXstring
;
; for fast string itteration use the opaque itterators, ensure you pick the right one for the string type
; *str\char\a[index] ascii , utf8 ;
; *str\char\u[index] unicode, Bstr (note bStr index starts from 2
; *str\char\w[index] wide char : .l on linux and osx, .u on windows
;
; String length reports the byte length in ascii and utf8 (since it's variable length)
; bytelen = *strAscii\len
; bytelen = *strUTF8\len
; For unicode and Wchar mutliply by the size of the structure
; bytelen = *strUnicode\len * SizeOf(unicode)
; bytelen = *strWchar\len * SizeOf(Wchar)
; or
; bytelen = *strUnicode\bytelen
;
;======================================================================
DeclareModule ModXString
Structure _xStrptr ;internal for Xstring Strucutre
StructureUnion ;char buffer itterators
a.a[0] ;ascii and utf8
u.u[0] ;unicode
CompilerIf #PB_Compiler_OS = #PB_OS_Linux Or#PB_Compiler_OS = #PB_OS_MacOS
w.l[0] ;wide char 32 bits linux osx
CompilerElse
w.u[0] ;wide char windows 16 bit unicode
CompilerEndIf
EndStructureUnion
EndStructure
;dummy structure for sizeof(wChar)
CompilerIf #PB_Compiler_OS = #PB_OS_Linux Or#PB_Compiler_OS = #PB_OS_MacOS
Structure wChar
char.l
EndStructure
CompilerElse
Structure wChar
char.u
EndStructure
CompilerEndIf
Structure XString
type.a
len.l
bytelen.l
*char._xStrptr
EndStructure
#Ascii = #PB_Ascii
#Unicode = #PB_Unicode
#UTF8 = #PB_UTF8
#Wchar = 255
#BStr = 254
;-Declare
Declare NewXString(string.s,xStrType) ;Create a string with a type
Declare CatchXString(*ptr,xStringSourceType,xStringCastType=0,len=-1) ;Catch a string from memory or data section
Declare.s PeekXString(*string.xString) ;converts the string to the native mode for gui output
Declare CopyXString(*src.xstring,*dest.xString=0,typecast=0) ;copy an xstring returns either *dest or a new xstring
Declare AppendXString(*str.xstring,text.s,xStringType=0) ;append an xstring and optionally recast to another type
Declare AddXString(*a.xstring,*b.xstring,xStringType=0) ;add join two xtrings together returns a new xstring
Declare LeftXString(*str.xstring,len,xStringType=0) ;returns left by len in a new xstring
Declare MidXString(*str.xString,pos,len,xStringType=0) ;returns mid from position by len in a new xstring
Declare RightXString(*str.xString,len,xStringType=0) ;returns right by len in a new xstring
Declare ClearXString(*str.xString) ;clear an xstring = ""
Declare FreeXString(*string.xString) ;free string
EndDeclareModule
Module ModXString
CompilerIf #PB_Compiler_OS = #PB_OS_Linux Or#PB_Compiler_OS = #PB_OS_MacOS
ImportC ""
mbstowcs(*dest,*src,n)
wcstombs(*dest,*src,n)
EndImport
CompilerEndIf
Procedure NewXString(string.s,type)
Protected *tmem,*str.xstring,len,blen
len = Len(string)
If len > 0
*tmem = AllocateMemory(len*6)
CompilerIf #PB_Compiler_Unicode
CompilerIf #PB_Compiler_OS = #PB_OS_Linux Or#PB_Compiler_OS = #PB_OS_MacOS
If type = #BStr
blen = PokeS(*tmem,PeekS(@string,#PB_Unicode),-1,#PB_Unicode)
ElseIf type <> #Wchar
blen = PokeS(*tmem,PeekS(@string,#PB_Unicode),-1,type)
Else
*mem = AllocateMemory(len*6)
len = PokeS(*mem,PeekS(@string,#PB_Unicode),-1,#PB_UTF8)
EndIf
CompilerElse
If type = #BStr
blen = PokeS(*tmem,PeekS(@string,#PB_Unicode),-1,#PB_Unicode)
ElseIf type <> #Wchar
blen = PokeS(*tmem,PeekS(@string,#PB_Unicode),-1,type)
Else
blen = PokeS(*tmem,PeekS(@string,#PB_Unicode),-1,#PB_Unicode)
EndIf
CompilerEndIf
CompilerElse
CompilerIf #PB_Compiler_OS = #PB_OS_Linux Or#PB_Compiler_OS = #PB_OS_MacOS
If type = #Bstr
blen = PokeS(*tmem,PeekS(@string,#PB_Ascii),-1,#PB_Unicode)
ElseIf type <> #Wchar
blen = PokeS(*tmem,PeekS(@string,#PB_Ascii),-1,type)
Else
*mem = AllocateMemory(len*6)
len = PokeS(*mem,PeekS(@string,#PB_Ascii),-1,#PB_UTF8)
EndIf
CompilerElse
If type = #Bstr
blen = PokeS(*tmem,PeekS(@string,#PB_Ascii),-1,#PB_Unicode)
ElseIf type <> #Wchar
blen = PokeS(*tmem,PeekS(@string,#PB_Ascii),-1,type)
ElseIf type = #wchar
blen = PokeS(*tmem,PeekS(@string,#PB_Ascii),-1,#PB_Unicode)
EndIf
CompilerEndIf
CompilerEndIf
CompilerIf #PB_Compiler_OS = #PB_OS_Linux Or#PB_Compiler_OS = #PB_OS_MacOS
If type = #Wchar
If mbstowcs(*tmem,*mem,len) > 0
blen = len*4
FreeMemory(*mem)
EndIf
EndIf
CompilerEndIf
If type = #PB_UTF8
len = blen
EndIf
*str = AllocateMemory(SizeOf(xString))
*str\type = type
*str\len = len
If type <> #bstr
*str\bytelen = blen
*str\char = AllocateMemory(blen+1)
CopyMemory(*tmem,*str\char,blen+1)
FreeMemory(*tmem)
Else
*str\bytelen = blen + 4
*str\char = AllocateMemory(blen+5)
CopyMemory(*tmem,*str\char+4,blen+1)
PokeL(*str\char,len*2)
FreeMemory(*tmem)
EndIf
ProcedureReturn *str
Else
*str = AllocateMemory(SizeOf(xString))
*str\type = type
ProcedureReturn *str
EndIf
EndProcedure
Procedure CatchXString(*ptr,xStringSourceType,xStringCastType=0,len=-1)
Protected string.s
If xStringCastType=0
xStringCastType = xStringSourceType
EndIf
Select xStringSourceType
Case #Ascii,#unicode,#utf8
string = PeekS(*ptr,len,xStringSourceType)
Case #bstr
string = PeekS(*ptr+4,PeekL(*ptr),#PB_Unicode)
Case #wchar
CompilerIf #PB_Compiler_OS = #PB_OS_Linux Or #PB_Compiler_OS = #PB_OS_MacOS
len = wcstombs(0,*ptr,0)
If len
*tmp = AllocateMemory(len)
wcstombs(*tmp,*ptr,len)
string = PeekS(*tmp,-1,#PB_UTF8)
FreeMemory(*tmp)
Else
ProcedureReturn 0
EndIf
CompilerElse
string = PeekS(*ptr,-1,#PB_Unicode)
CompilerEndIf
EndSelect
ProcedureReturn NewXString(string,xStringCastType)
EndProcedure
Procedure FreeXString(*string.xstring)
If *string
If *string\len > 0
FreeMemory(*string\char)
EndIf
FreeMemory(*string)
EndIf
EndProcedure
Procedure.s PeekXString(*string.XString)
Protected out.s,*tmp
If *string
If *string\len > 0
Select *string\type
Case #Ascii
ProcedureReturn PeekS(*string\char,-1,#PB_Ascii)
Case #Unicode
ProcedureReturn PeekS(*string\char,-1,#PB_Unicode)
Case #UTF8
ProcedureReturn PeekS(*string\char,-1,#PB_UTF8)
Case #Wchar
CompilerIf #PB_Compiler_OS = #PB_OS_Linux Or #PB_Compiler_OS = #PB_OS_MacOS
*tmp = AllocateMemory(*string\len*4)
wcstombs(*tmp,*string\char,*string\len*4+1)
out = PeekS(*tmp,-1,#PB_UTF8)
FreeMemory(*tmp)
ProcedureReturn out
CompilerElse
ProcedureReturn PeekS(*string\char,-1,#PB_Unicode)
CompilerEndIf
Case #bstr
ProcedureReturn PeekS(*string\char+4,PeekL(*string\char)>>1,#PB_Unicode)
EndSelect
EndIf
EndIf
EndProcedure
Procedure CopyXString(*src.xstring,*dest.xString=0,typecast=0)
Protected blen,*psrc
If typecast = 0
typecast = *src\type
EndIf
If *dest = 0
ProcedureReturn CatchXString(*src\char,*src\type,typecast,*src\bytelen)
ElseIf typecast <> *src\type
If *dest\len
FreeMemory(*dest\char)
EndIf
FreeMemory(*dest)
ProcedureReturn CatchXString(*src\char,*src\type,typecast,*src\bytelen)
ElseIf *dest\len > 0
FreeMemory(*dest\char)
EndIf
*dest\len = *src\len
*dest\type = *src\type
*dest\char = AllocateMemory(*src\bytelen)
CopyMemory(*src\char,*dest\char,*src\bytelen)
ProcedureReturn *dest
EndProcedure
Procedure AppendXString(*str.xstring,text.s,xStringType=0)
Protected *out.xstring,temp.s
If *str
temp.s = PeekXString(*str)
temp + text
If xStringType =0
xStringType = *str\type
EndIf
*out = NewXString(temp,xStringType)
FreeXString(*str)
ProcedureReturn *out
Else
*out = NewXString(temp,xStringType)
ProcedureReturn *out
EndIf
EndProcedure
Procedure AddXString(*a.xstring,*b.xstring,xStringType=0)
Protected *out.xstring, text.s
If *a And *b
text = PeekXString(*a)
text + PeekXString(*b)
If xStringType =0
xStringType = *a\type
EndIf
*out = NewXString(text,xStringType)
FreeXString(*a)
FreeXString(*b)
ProcedureReturn *out
EndIf
EndProcedure
Procedure LeftXString(*str.xstring,len,xStringType=0)
Protected *out.xstring, text.s
If *str
text = Peekxstring(*str)
text = Left(text,len)
If xStringType =0
xStringType = *str\type
EndIf
*out= NewXString(text,xStringType)
ProcedureReturn *out
EndIf
EndProcedure
Procedure MidXString(*str.xString,pos,len,xStringType=0)
Protected *out.xstring, text.s
If *str
text = Peekxstring(*str)
text = Mid(text,pos,len)
If xStringType =0
xStringType = *str\type
EndIf
*out= NewXString(text,xStringType)
ProcedureReturn *out
EndIf
EndProcedure
Procedure RightXString(*str.xString,len,xStringType=0)
Protected *out.xstring, text.s
If *str
text = Peekxstring(*str)
text = Right(text,len)
If xStringType =0
xStringType = *str\type
EndIf
*out= NewXString(text,xStringType)
ProcedureReturn *out
EndIf
EndProcedure
Procedure ClearXString(*str.xString)
If *str
If *str\len
FreeMemory(*str\char)
*str\len=0
EndIf
EndIf
EndProcedure
EndModule
;compile in console mode
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
OpenConsole()
UseModule ModXString
Define.xstring *sasc,*suni,*sut8,*swc,*sBstr,*x,*y,*z,*copyWc,*copyBstr
*sasc = NewXString("hello@",#Ascii)
*suni = NewXString("hello@",#Unicode)
*sut8 = NewXString("hello@",#UTF8)
*swc = NewXString("hello@",#Wchar)
*sBstr = NewXString("hello@",#Bstr)
*x = CatchXString(?textc,#UTF8,0,9)
Define.i a
For a = 0 To *sasc\len ;len holds the number of bytes in ascii and utf8
Print(Str(*sasc\char\a[a])+ " ") ;use the \a[index] itterator
Next
PrintN("Ascii " + PeekXString(*sasc))
PrintN("+++++++++++++++++++++++++")
;
For a = 0 To *suni\len ;len holds number of characters use len * sizeof(unicode) to get number of byte if needed
Print(Str(*suni\char\u[a]) + " "); ;use the \u[index] itterator
Next
PrintN("Unicode " + PeekXString(*suni))
PrintN("+++++++++++++++++++++++++")
For a = 0 To *sut8\len ; utf reports number of bytes in buffer
Print(Str(*sut8\char\a[a]) + " ") ;use \a[index] itterator
Next
PrintN("UTF8 " + PeekXString(*sut8)) ;
PrintN("+++++++++++++++++++++++++")
For a = 0 To *swc\len ;len holds number of characters call string\blen for length of bytes
Print(Str(*swc\char\w[a])+ " ") ;use \w[index] itterator
Next
PrintN("Wchar " + PeekXString(*swc))
PrintN("+++++++++++++++++++++++++")
*copyWc = CopyXString(*swc)
PrintN("copy wchar " + PeekXString(*copyWc))
PrintN("+++++++++++++++++++++++++")
For a = 2 To *sbstr\len+2 ;len holds number of characters but a bStr index starts from 2 to len +2
Print(Str(*sbstr\char\u[a])+ " ") ;use \u[index] itterator
Next
PrintN("bStr " + PeekXString(*sbstr))
PrintN("+++++++++++++++++++++++++")
*copyBstr = CopyXString(*sBstr)
PrintN("copy bstr " + PeekXString(*copyBstr))
PrintN("+++++++++++++++++++++++++")
For a = 0 To *x\len ;debug utf8 string
Print(Str(*x\char\a[a])+ " " )
Next
PrintN("UTF8 " + PeekXString(*x)) ;prints the utf8 string masheled through the compilers mode -> unicode!
PrintN("+++++++++++++++++++++++++")
*y = CopyXString(*x) ;copy *x casts *x to *y
PrintN("copy utf8 " + PeekXString(*y))
PrintN("+++++++++++++++++++++++++")
*y = CopyXString(*suni,*y,#Ascii) ;copy *suni which is unicode to *y which is utf8 but cast y to ascii
PrintN("copy a unicode string to a utf8 string recasting it as ascii " + PeekXString(*y))
PrintN("+++++++++++++++++++++++++")
*y = AppendXString(*y," world")
PrintN("append " + PeekXString(*y))
PrintN("+++++++++++++++++++++++++")
*z = LeftXString(*y,5)
PrintN("left 5 " + PeekXString(*z))
FreeXString(*z)
PrintN("+++++++++++++++++++++++++")
*z = RightXString(*y,5)
PrintN("right 5 " + PeekXString(*z))
FreeXString(*z)
PrintN("+++++++++++++++++++++++++")
*z = MidXString(*y,6,1)
PrintN("mid 5,1 " + PeekXString(*z))
PrintN("+++++++++++++++++++++++++")
ClearXstring(*z)
*z = AppendXString(*z,"hello world 123")
PrintN("append " + PeekXString(*z))
FreeXString(*sasc) ;free the strings pb can't free them for you
FreeXString(*suni)
FreeXString(*sut8)
FreeXString(*swc)
FreeXString(*sBstr)
FreeXString(*copyWc)
FreeXString(*copyBstr)
FreeXString(*x)
FreeXString(*y)
FreeXString(*z)
DataSection
textc:
Data.a 231,186,175,229,159,186,231,161,128 ;pure basic in chinese google translation
EndDataSection
UnuseModule ModXString
PrintN("press key to end")
Input()
CompilerEndIf