Bay Six Software Forum Index Bay Six Software
Beyond the Basics
 
 FAQFAQ   SearchSearch   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[BETA] Large Strings Library

 
Post new topic   Reply to topic    Bay Six Software Forum Index -> Snippet Testing
View previous topic :: View next topic  
Author Message
Brent
Site Admin


Joined: 01 Jul 2005
Posts: 728

PostPosted: Nov 9th, 2007, 5:20am    Post subject: [BETA] Large Strings Library Reply with quote

Below is a library that improves the speed of LB code that manipulates large strings. Strings larger than 3-4KB can be modified more quickly with this library that LB's own native code. Below that threshold, the overhead of the calls becomes great enough to make it slower than LB native code.

The main reason for the speed improvement is due to its doing its own memory management. The string is allocated statically at a fixed size that cannot be modified. Attempting to overflow the string results in clipping.

First is a little test driver, then the actual library, then finally an equivalent program to the first two using native code and my old QBMID routine from the "Snips" section. On my system, the library's driver is more than one second faster than the native code example.
Code:
    ITERATIONS = 40
    STRINGSIZE = 4000
    t = Time$("ms")
    aString = NewStr(STRINGSIZE)
    For i = 1 To ITERATIONS
        For c = 1 To STRINGSIZE
            Call MidStrN aString, c, 1, "X"
        Next c
    Next i
    Call KillStr aString
    Print Time$("ms") - t
    End

Code:
'== Large String Library
'== By Brent D. Thorn, 11/2007

Function NewStr( Size )
'-- Creates a new string of a given size.
'-- Paramters
'     Size - number of bytes
'-- Returns
'      a pointer to the string or NULL
    Struct cbStr, cb As ULong
    Global g.hProcessHeap
    CallDLL #kernel32, "GetProcessHeap", g.hProcessHeap As ULong

    If Size < 1 Then Exit Function

    cbHeap = Size + 4
    CallDLL #kernel32, "HeapAlloc", g.hProcessHeap As ULong, 0 As ULong, cbHeap As ULong, NewStr As ULong
    cbStr.cb.struct = 0
    CallDLL #kernel32, "RtlMoveMemory", NewStr As ULong, cbStr As Struct, 4 As ULong, ret As Void
End Function

Sub KillStr pStr
'-- Destroys a string created by 'NewStr'
'-- Parameters
'      pStr - a pointer to a string
    CallDLL #kernel32, "HeapFree", g.hProcessHeap As ULong, 0 As ULong, pStr As ULong, ret As Long
End Sub

Function LenStr( pStr )
'-- Equivalent of the LEN function
'-- Parameters
'      pStr - a pointer to a string created by 'NewStr'
'-- Returns
'      the length of the string in bytes
    '[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pStr As ULong, 4 As ULong, ret As Void
    cbStr.struct = pStr '[unsafe]
    LenStr = cbStr.cb.struct
End Function

Sub LetStr pDst, Src$
'-- Equivalent of LET for a string created by 'NewStr'
'-- Paramters
'      pDst - a pointer to the string to be assigned a new value
'      Src$ - a string that holds the new value to be assigned
    CallDLL #kernel32, "HeapSize", g.hProcessHeap As ULong, 0 As ULong, pDst As ULong, cbHeap As ULong
    pStr = pDst + 4
    cbSrc = Min(cbHeap - 4, Len(Src$))
    CallDLL #kernel32, "RtlMoveMemory", pStr As ULong, Src$ As Ptr, cbSrc As ULong, ret As Void
    cbStr.cb.struct = cbSrc
    CallDLL #kernel32, "RtlMoveMemory", pDst As ULong, cbStr As Struct, 4 As ULong, ret As Void
End Sub

Sub CatStr pDst, Src$
'-- Concatenates a string onto a string created by 'NewStr'
'-- Parameters
'      pDst - a pointer to a string to be modified
'      Src$ - a string to be concatenated
    CallDLL #kernel32, "HeapSize", g.hProcessHeap As ULong, 0 As ULong, pDst As ULong, cbHeap As ULong
    '[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pDst As ULong, 4 As ULong, ret As Void
    cbStr.struct = pDst '[unsafe]
    cbDst = cbStr.cb.struct
    cbSrc = Min(cbHeap - 4 - cbDst, Len(Src$))
    pStr = pDst + 4 + cbDst
    CallDLL #kernel32, "RtlMoveMemory", pStr As ULong, Src$ As Ptr, cbSrc As ULong, ret As Void
    cbStr.cb.struct = cbDst + cbSrc
    CallDLL #kernel32, "RtlMoveMemory", pDst As ULong, cbStr As Struct, 4 As ULong, ret As Void
End Sub

Function GetStr$( pStr )
'-- Somewhat equivalent to WINSTRING
'-- Parameters
'      pStr - a pointer to a string created by 'NewStr'
'-- Returns
'      the string value regardless of NUL characters
    '[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pStr As ULong, 4 As ULong, ret As Void
    cbStr.struct = pStr '[unsafe]
    cbStr = cbStr.cb.struct
    GetStr$ = Space$(cbStr)
    pStr = pStr + 4
    CallDLL #kernel32, "RtlMoveMemory", GetStr$ As Ptr, pStr As ULong, cbStr As ULong, ret As Void
End Function

Sub MidStr pDst, Pos, Src$
'-- Equivalent to QB's MID$ statement with two params
'   E.g. MID$(d$, p) = s$
    '[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pDst As ULong, 4 As ULong, ret As Void
    cbStr.struct = pDst '[unsafe]
    cbDst = cbStr.cb.struct
    pDst = pDst + 3 + Pos
    cnt = Len(Src$)
    If Pos + cnt > cbDst Then _
      cnt = cbDst - Pos + 1
    If cnt > 0 Then _
      CallDLL #kernel32, "RtlMoveMemory", pDst As ULong, Src$ As Ptr, cnt As ULong, ret As Void
End Sub

Sub MidStrN pDst, Pos, Cnt, Src$
'-- Equivalent to QB's MID$ statement with three params
'   E.g. MID$(d$, p, c) = s$
    '[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pDst As ULong, 4 As ULong, ret As Void
    cbStr.struct = pDst '[unsafe]
    cbDst = cbStr.cb.struct
    pDst = pDst + 3 + Pos
    If Cnt > Len(Src$) Then Cnt = Len(Src$)
    If Pos + Cnt > cbDst Then _
      Cnt = cbDst - Pos + 1
    If Cnt > 0 Then _
      CallDLL #kernel32, "RtlMoveMemory", pDst As ULong, Src$ As Ptr, Cnt As ULong, ret As Void
End Sub

Code:
    ITERATIONS = 40
    STRINGSIZE = 4000
    t = Time$("ms")
    a$ = Space$(STRINGSIZE)
    For i = 1 To ITERATIONS
        For c = 1 To STRINGSIZE
            Call QBMID a$, c, 1, "X"
        Next c
    Next i
    Print Time$("ms") - t
    End

Sub QBMID ByRef Dst$, Pos, Cnt, Src$
'-- Equivalent to QB's MID$(d$,p,c)=s$ command.
'-- Usage:  Call QBMID d$,p,c,s$
'-- Provided freely by Brent D. Thorn.
'-- http://www.b6sw.com
    If Cnt > Len(Src$) Then Cnt = Len(Src$)
    If Pos + Cnt > Len(Dst$) Then _
      Cnt = Len(Dst$) - Pos + 1
    If Cnt > 0 Then
        Dst$ = Left$(Dst$, Pos - 1) _
             + Left$(Src$, Cnt) _
             + Mid$(Dst$, Pos + Cnt)
    End If
End Sub

_________________
Brent
Back to top
View user's profile Send private message Send e-mail
hans
Guest





PostPosted: Apr 1st, 2009, 7:37am    Post subject: Getting string from memoryblock (large string library) Reply with quote

I made a additional function for the large string library. It gets a string from anywhere in the memoryblock created by NewStr.

There is just one problem: the string GetStr$ doesnt have the content after the kernel is called, it is still a string filled with spaces.

What am I doing wrong?

Code:
Function GetStr$(pStr,Pos,cnt,leng)
'-- Get a string out off a memoryblock created by 'NewStr'
'-- Parameters
'      pStr - a pointer to the start of the memoryblock
'      pos  - offset from start of memoryblock
'      cnt  - required length of string GetStr$
'      leng - length memoryblock (pStr)
'-- Returns
'      the string value regardless of NUL characters
    GetStr$ = Space$(cnt) '**
    Src = pStr + 3 + Pos
    if Pos+cnt-1>leng then cnt=leng - Pos + 1
    CallDLL #kernel32, "RtlMoveMemory", GetStr$ As Ptr, Src As ULong, cnt As ULong, ret As Void
End Function
Back to top
Guest






PostPosted: Apr 1st, 2009, 10:30am    Post subject: Re: [BETA] Large Strings Library Reply with quote

Has it something to do with what you do in other routines?:
[/code]cbStr.struct = pDst '[unsafe]
cbDst = cbStr.cb.struct
Code:


I don't have any idea what this code does.

hans
Back to top
Brent
Site Admin


Joined: 01 Jul 2005
Posts: 728

PostPosted: Apr 1st, 2009, 7:28pm    Post subject: Re: [BETA] Large Strings Library Reply with quote

Hello Hans,

I think you want something like this.
Code:
Function MidStrN$( pStr, Pos, Cnt )
'-- Equivalent to the "Mid$" function with 3 parameters
    If Pos < 1 Or Cnt < 1 Then Exit Function
    cbStr.struct = pStr '[unsafe]
    cbStr = cbStr.cb.struct
    cbMid = Min(Cnt, cbStr - Pos - 1)
    If cbMid < 1 Then Exit Function
    MidStrN$ = Space$(cbMid)
    pStr = pStr + Pos + 3
    CallDLL #kernel32, "RtlMoveMemory", MidStrN$ As Ptr, pStr As ULong, cbMid As ULong, ret As Void
End Function

The cbStr variable holds the count of bytes in the string, which is stored at the start if the memory block.

_________________
Brent
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    Bay Six Software Forum Index -> Snippet Testing All times are GMT
Page 1 of 1
Jump to:  
Quick Reply
Username:
Message:
   Shortcut keys: Alt+Q to activate, Alt+P to preview, Alt+S to submit
You cannot post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum



Lo-Fi Version
Powered by phpBB © 2001, 2005 phpBB Group