@Keya
Very nice for fast string management, but is better you rename your BSTR to FastStr then there is no discusion about the structures used.
BSTR is not equal to FastStr and finished!
Property times a code written to create BSTR manually.
BSTR is only needed under Windows and there are ready APIs.
Update for Keya  
 
Code: Select all
; BSTR Functions; Created by mk-soft; Date 19.03.017
; *****************************************************************************
Structure udtArrayChar
  c.c[0]
EndStructure
Structure udtBStr;Align 4
  len.l
  str.udtArrayChar
EndStructure
; -----------------------------------------------------------------------------
Procedure CreateBStr(Text.s)
  Protected *bstr.udtBStr, len
  len = StringByteLength(Text)
  *bstr = AllocateMemory(len + SizeOf(Long) + SizeOf(character))
  *bstr\len = len
  CopyMemory(@Text, @*bstr\str, len)
  ProcedureReturn @*bstr\str
EndProcedure
; -----------------------------------------------------------------------------
Procedure FreeBStr(*Bstr)
  Protected *mem = *Bstr - SizeOf(Long)
  FreeMemory(*mem)
EndProcedure
; -----------------------------------------------------------------------------
Procedure ConcatBStr(T1, T2)
  Protected *t1.udtBStr, *t2.udtBStr, *r1.udtBStr, len
  *t1 = t1 - SizeOf(Long)
  *t2 = t2 - SizeOf(Long)
  If *t1\len And *t2\len
    len = *t1\len + *t2\len
    *r1 = AllocateMemory(len + SizeOf(Long) + SizeOf(character))
    *r1\len = len
    CopyMemory(@*t1\str, @*r1\str, *t1\len)
    CopyMemory(@*t2\str, @*r1\str + *t1\len, *t2\len)
  ElseIf *t1\len
    len = MemorySize(*t1)
    *r1 = AllocateMemory(len)
    CopyMemory(*t1, *r1, len)
  ElseIf *t2\len
    len = MemorySize(*t2)
    *r1 = AllocateMemory(len)
    CopyMemory(*t2, *r1, len)
  Else
    *r1 = AllocateMemory(SizeOf(long) + SizeOf(character))
  EndIf
  ProcedureReturn @*r1\str
EndProcedure
; -----------------------------------------------------------------------------
Procedure _AddBStr(BStr, Text.s)
  Protected *bstr.udtBStr, len, len2
  *bstr = Bstr - SizeOf(Long)
  len = StringByteLength(Text)
  len2 = *bstr\len + len
  *bstr = ReAllocateMemory(*bstr, len2 + SizeOf(Long) + SizeOf(character))
  CopyMemory(@Text, @*bstr\str + *bstr\len, len)
  *bstr\len = len2
  ProcedureReturn @*bstr\str
EndProcedure
Macro AddBstr(BStr, Text)
  BStr = _AddBStr(BStr, Text)
EndMacro
; -----------------------------------------------------------------------------
Procedure LenBStr(*Bstr)
  Protected *mem.udtBStr = *Bstr - SizeOf(Long)
  ProcedureReturn (*mem\len / SizeOf(character))
EndProcedure
; -----------------------------------------------------------------------------
Procedure LeftBStr(BStr, Lenght)
  Protected *r1.udtBStr, *BStr.udtBStr, len
  *BStr.udtBStr = Bstr - SizeOf(Long)
  len = Lenght * SizeOf(character)
  If len > *BStr\len
    len = *BStr\len
  EndIf
  *r1 = AllocateMemory(len + SizeOf(Long) + SizeOf(character))
  *r1\len = len
  CopyMemory(@*BStr\str, @*r1\str, len)
  ProcedureReturn @*r1\str
EndProcedure
; -----------------------------------------------------------------------------
Procedure RightBStr(BStr, Lenght)
  Protected *r1.udtBStr, *BStr.udtBStr, len, pos
  *BStr.udtBStr = Bstr - SizeOf(Long)
  len = Lenght * SizeOf(character)
  If len > *BStr\len
    len = *BStr\len
  EndIf
  *r1 = AllocateMemory(len + SizeOf(Long) + SizeOf(character))
  *r1\len = len
  pos = *BStr\len - len
  CopyMemory(@*BStr\str + Pos, @*r1\str, len)
  ProcedureReturn @*r1\str
EndProcedure
; -----------------------------------------------------------------------------
Procedure MidBStr(BStr, Position, Lenght = 0)
  Protected *r1.udtBStr, *BStr.udtBStr, len, ofs
  *BStr.udtBStr = Bstr - SizeOf(Long)
  ofs = (position - 1) * SizeOf(character)
  len = Lenght * SizeOf(character)
  Repeat
    If ofs >= *BStr\len Or ofs < 0
      *r1 = AllocateMemory(SizeOf(Long) + SizeOf(character))
      Break
    EndIf
    If Not len
      len = *BStr\len
    EndIf
    If ofs + len > *BStr\len
      len = *BStr\len - ofs
    EndIf
    *r1 = AllocateMemory(len + SizeOf(Long) + SizeOf(character))
    *r1\len = len
    CopyMemory(@*BStr\str + ofs, @*r1\str, len)
  Until #True
  ProcedureReturn @*r1\str
EndProcedure
; -----------------------------------------------------------------------------
Procedure.s BStrString(*BStr)
  Protected *value.String = @*Bstr
  ProcedureReturn *value\s
EndProcedure
; -----------------------------------------------------------------------------
Procedure BStrVal(*BStr)
  Protected *value.String = @*Bstr
  ProcedureReturn Val(*value\s)
EndProcedure
; -----------------------------------------------------------------------------
Procedure.f BStrValF(*BStr)
  Protected *value.String = @*Bstr
  ProcedureReturn ValF(*value\s)
EndProcedure
; -----------------------------------------------------------------------------
Procedure.d BStrValD(*BStr)
  Protected *value.String = @*Bstr
  ProcedureReturn ValD(*value\s)
EndProcedure
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
;- Test
CompilerIf #PB_Compiler_Debugger
  
  Define t1, t2, t3, r1
  t1 = CreateBStr("Hello World")
  t2 = CreateBStr(", Purebasic Power")
  t3 = ConcatBStr(t1,t2)
  AddBStr(t3, " !")
  Debug LenBStr(t3)
  Debug BStrString(t3)
  r1 = LeftBStr(t3, 5)
  Debug BStrString(r1)
  FreeBStr(r1)
  r1 = RightBStr(t3, 7)
  Debug BStrString(r1)
  FreeBStr(r1)
  r1 = MidBStr(t3, 14, 9)
  Debug BStrString(r1)
  Debug LenBStr(r1)
  FreeBStr(r1)
  r1 =CreateBStr("12345.12345")
  Debug BStrVal(r1)
  Debug BStrValF(r1)
  Debug BStrValD(r1)
  FreeBStr(r1)
  FreeBStr(t1)
  FreeBStr(t2)
  FreeBStr(t3)
  
CompilerElse
  Define t1, append$   ;a BString and a normal String$
  
  append$ = ""
  Time1=ElapsedMilliseconds()
  For i = 1 To 20000
    append$ + "Append This"
  Next i
  Time2=ElapsedMilliseconds()
  
  A$ = "Str$ Time=" + Str(Time2 - Time1) + ~"ms\n" 
  
  t1 = CreateBStr("")
  Time1=ElapsedMilliseconds()
  For i = 1 To 20000
    AddBStr(t1, "Append This")
  Next i
  Time2=ElapsedMilliseconds()
  
  A$ + "BSTR Time=" + Str(Time2 - Time1) + "ms"
  
  MessageRequester("BSTR timings",A$)
  ;Str$ Time=7716ms
  ;BSTR Time=26ms
CompilerEndIf
 
 
P.S. Only Unicode