Container Library: String, Array, Stack, Queue

Started by Theo Gottwald, November 26, 2023, 06:07:35 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Theo Gottwald

🚀 Auto Lib: Choose your container type and let the app do the magic! 🧙�♂️✨ It generates the precise code you need, without the clutter of unnecessary include files. 📁

🔗 Each file stands alone with zero dependencies. Plus, our containers are built on UDTs, offering optional UDT storage. 📦

📚 Stacks & Queues:
Experience lightning-fast operations with our dedicated stacks, rivaling assembly language efficiency! ⚡️
- Long Stack: Push 100M values in just 0.584s, and pop them in 1.296s! 📈
- Long Queue: Impressive speed, adding 100M values in 1.415s and retrieving them in 2.742s! 🔄

📈 Arrays:
Enjoy the convenience of buffered arrays with automatic memory management. They adapt to your needs, growing and shrinking without manual ReDim(). Just add, insert, or delete! ➕➖
- Binary search, insert, and delete are all supported. 🔍
- String arrays make text file processing a breeze. 📃
- WString arrays are perfect for listing files and folders, whether in the root or sub-folders. 📂

🔠 String Containers:
Effortlessly store dynamic strings in UDTs, an essential feature for our library. 📚

#AutoLib #CodeGeneration #Programming #Efficiency #Stacks #Queues #Arrays #SoftwareDevelopment #TechTools #CodingLife #Developers 🚀🧙�♂️✨📁🔗📦⚡️📈🔄➕➖🔍📃📂🔠📚


'AutoLib231019.bas
#PBForms Created V2.01
#Compile Exe
#Dim All

#PBForms Begin Includes
'#Resource "AutoLib231019.pbr"
%USEMACROS = 1
#Include Once "WIN32API.INC"
#Include Once "COMMCTRL.INC"
#Include Once "PBForms.INC"
#PBForms End Includes

#PBForms Begin Constants
%BtnCreate        = 1006
%BtnOutputFile    = 1005
%DlgMain          =  101
%LblContainerType = 1001
%LblVariableType  = 1003
%LbxContainerType = 1002
%LbxVariableType  = 1004
%TxtInstructions  = 1008
%TxtOutputFile    = 1007
#PBForms End Constants


Global gDlg As Long
Global gOutputFile As WString
Global gContainerType As String
Global gVariableType As String
Global gCode As String
Macro tb = "    "
Global gSB As IStringBuilderA
Sub SBAddLine(ByVal s As String)
    gSB.add s + $CrLf
End Sub
Macro SS = SBAddLine


Function PBMain()
    gSB = Class "StringBuilderA"
    PBFormsInitComCtls (%ICC_WIN95_CLASSES Or %ICC_DATE_CLASSES Or %ICC_INTERNET_CLASSES)
    ShowDlg1 %HWND_Desktop
End Function

CallBack Function ShowDlg1Proc()
    Select Case As Long Cb.Msg
        Case %WM_InitDialog : WMInitDialog()
        Case %WM_NCActivate
            Static hWndSaveFocus As Dword
            If IsFalse Cb.WParam Then
                hWndSaveFocus = GetFocus()
            ElseIf hWndSaveFocus Then
                SetFocus(hWndSaveFocus)
                hWndSaveFocus = 0
            End If
        Case %WM_Command
            Select Case As Long Cb.Ctl
                Case %LbxContainerType : If Cb.CtlMsg = %LBN_SelChange Then LbxContainerTypeSelectionChange()
                Case %LbxVariableType : If Cb.CtlMsg = %LBN_SelChange Then LbxVariableTypeSelectionChange()
                Case %BtnOutputFile: If Cb.CtlMsg = %BN_Clicked Or Cb.CtlMsg = 1 Then BtnOutputFileClicked()
                Case %BtnCreate : If Cb.CtlMsg = %BN_Clicked Or Cb.CtlMsg = 1 Then BtnCreateClicked()
                Case %TxtOutputFile
                Case %TxtInstructions
            End Select
    End Select
End Function

Function ShowDlg1(ByVal hParent As Dword) As Long
    Local lRslt  As Long
#PBForms Begin Dialog %DlgMain->->
    Local hDlg   As Dword
    Local hFont1 As Dword

    Dialog New hParent, "Auto Lib", 260, 177, 369, 221, %WS_Popup Or %WS_Border Or %WS_DlgFrame Or %WS_Caption Or %WS_SysMenu Or %WS_MinimizeBox Or %WS_ClipSiblings Or %WS_Visible Or %DS_ModalFrame Or %DS_Center Or %DS_3DLook Or _
        %DS_NoFailCreate Or %DS_SetFont, %WS_Ex_ControlParent Or %WS_Ex_Left Or %WS_Ex_LtrReading Or %WS_Ex_RightScrollbar, To hDlg
    Dialog  Set Color    hDlg, -1, %White
    Control Add Label,   hDlg, %LblContainerType, "Container Type", 4, 4, 180, 16
    Control Set Color    hDlg, %LblContainerType, -1, %White
    Control Add ListBox, hDlg, %LbxContainerType, , 4, 24, 180, 64, %WS_Child Or %WS_Visible Or %WS_TabStop Or %WS_VScroll Or %LBS_Sort Or %LBS_Notify Or %LBS_NoIntegralHeight, %WS_Ex_Left Or %WS_Ex_LtrReading Or %WS_Ex_RightScrollbar
    Control Set Color    hDlg, %LbxContainerType, RGB(0, 0, 191), RGB(249, 249, 249)
    Control Add Label,   hDlg, %LblVariableType, "Variable Type", 4, 92, 180, 16
    Control Set Color    hDlg, %LblVariableType, -1, %White
    Control Add ListBox, hDlg, %LbxVariableType, , 4, 112, 180, 64, %WS_Child Or %WS_Visible Or %WS_TabStop Or %WS_VScroll Or %LBS_Sort Or %LBS_Notify Or %LBS_NoIntegralHeight, %WS_Ex_Left Or %WS_Ex_LtrReading Or %WS_Ex_RightScrollbar
    Control Set Color    hDlg, %LbxVariableType, RGB(0, 0, 206), RGB(248, 248, 248)
    Control Add Button,  hDlg, %BtnOutputFile, "Output File", 4, 180, 84, 16, %WS_Child Or %WS_Visible Or %WS_TabStop Or %BS_Text Or %BS_PushButton Or %BS_Flat Or %BS_Center Or %BS_VCenter, %WS_Ex_Left Or %WS_Ex_LtrReading
    Control Add Button,  hDlg, %BtnCreate, "Create", 92, 180, 92, 16, %WS_Child Or %WS_Visible Or %WS_TabStop Or %BS_Text Or %BS_PushButton Or %BS_Flat Or %BS_Center Or %BS_VCenter, %WS_Ex_Left Or %WS_Ex_LtrReading
    Control Add TextBox, hDlg, %TxtOutputFile, "", 4, 200, 360, 16, %WS_Child Or %WS_Visible Or %ES_Left Or %ES_AutoHScroll, %WS_Ex_Left Or %WS_Ex_LtrReading Or %WS_Ex_RightScrollbar
    Control Set Color    hDlg, %TxtOutputFile, -1, RGB(248, 248, 248)
    Control Add TextBox, hDlg, %TxtInstructions, "", 188, 4, 176, 192, %WS_Child Or %WS_Visible Or %WS_VScroll Or %ES_Left Or %ES_MultiLine Or %ES_AutoVScroll Or %ES_NoHideSel Or %ES_ReadOnly Or %ES_WantReturn, %WS_Ex_Left Or _
        %WS_Ex_LtrReading Or %WS_Ex_RightScrollbar
    Control Set Color    hDlg, %TxtInstructions, RGB(240, 0, 0), RGB(249, 249, 249)

    Font New "Consolas", 12, 0, %ANSI_CHARSET To hFont1

    Control Set Font hDlg, -1, hFont1
    Control Set Font hDlg, %LblContainerType, hFont1
    Control Set Font hDlg, %LbxContainerType, hFont1
    Control Set Font hDlg, %LblVariableType, hFont1
    Control Set Font hDlg, %LbxVariableType, hFont1
    Control Set Font hDlg, %BtnOutputFile, hFont1
    Control Set Font hDlg, %BtnCreate, hFont1
    Control Set Font hDlg, %TxtOutputFile, hFont1
    Control Set Font hDlg, %TxtInstructions, hFont1
#PBForms End Dialog
    gDlg = hDlg
    Dialog Show Modal hDlg, Call ShowDlg1Proc To lRslt
#PBForms Begin CleanUp %DlgMain
    Font End hFont1
#PBForms End CleanUp
    Function = lRslt
End Function

Sub WMInitDialog()
    Local s As String
    gSB.Clear
    gOutputFile = ""
    gContainerType = ""
    gVariableType = ""
    Control Set Text gDlg, %TxtOutputFile, ""
    ListBox Reset gDlg, %LbxContainerType
    ListBox Reset gDlg, %LbxVariableType

    ListBox Add gDlg, %LbxContainerType, "String Container"
    ListBox Add gDlg, %LbxContainerType, "Array"
    ListBox Add gDlg, %LbxContainerType, "Stack"
    ListBox Add gDlg, %LbxContainerType, "Queue"

    s += "Select container type." + $CrLf + $CrLf
    s += "All containers are UDT based and can optionally be stored in a UDT." + $CrLf + $CrLf
    s += "A string container holds a dynamic string." + $CrLf + $CrLf
    s += "The arrays are buffered stacks with added array porcedures. "
    s += "Memory management is automatic. Just add, insert, and delete. "
    s += "Array grows and shrinks as needed. "
    s += "Used as a stack they are very fast." + $CrLf
    Control Set Text gDlg, %TxtInstructions, s
End Sub

Sub BtnCreateClicked()
    If gContainerType = "" Then
        MsgBox "container type not specified",,"Auto Lib" : Exit Sub
    End If
    If gVariableType = "" Then
        MsgBox "variable type not specified",,"Auto Lib" : Exit Sub
    End If
    If gCode = "" Then
        MsgBox "code not built",,"Auto Lib" : Exit Sub
    End If
    If gOutputFile = "" Then
        MsgBox "output file not specified",,"Auto Lib" : Exit Sub
    End If
    StrToFile gOutputFile, gCode
    MsgBox "done...",,"Auto Lib"
    WMInitDialog()
End Sub

Sub BtnOutputFileClicked()
    gOutputFile = ""
    Control Set Text gDlg, %TxtOutputFile, ""
    Display Openfile , , , "Output Source File", "", "*.inc", "", "", 0 To gOutputFile
    Control Set Text gDlg, %TxtOutputFile, gOutputFile
End Sub

Sub LbxContainerTypeSelectionChange()
    ListBox Reset gDlg, %LbxVariableType
    Control Set Text gDlg, %TxtInstructions, ""
    ListBox Get Text gDlg, %LbxContainerType To gContainerType
    Select Case gContainerType
        Case "Array"
            ListBox Add gDlg, %LbxVariableType, "Byte"
            ListBox Add gDlg, %LbxVariableType, "Word"
            ListBox Add gDlg, %LbxVariableType, "Integer"
            ListBox Add gDlg, %LbxVariableType, "Long"
            ListBox Add gDlg, %LbxVariableType, "Dword"
            ListBox Add gDlg, %LbxVariableType, "Quad"
            ListBox Add gDlg, %LbxVariableType, "Single"
            ListBox Add gDlg, %LbxVariableType, "Double"
            ListBox Add gDlg, %LbxVariableType, "Currency"
            ListBox Add gDlg, %LbxVariableType, "CurrencyX"
            ListBox Add gDlg, %LbxVariableType, "Extended"
            ListBox Add gDlg, %LbxVariableType, "String"
            ListBox Add gDlg, %LbxVariableType, "WString"
            Control Set Text gDlg, %TxtInstructions, "Select variable type."
        Case "String Container"
            ListBox Add gDlg, %LbxVariableType, "String"
            ListBox Add gDlg, %LbxVariableType, "WString"
            Control Set Text gDlg, %TxtInstructions, "Select variable type."
        Case "Stack"
            ListBox Add gDlg, %LbxVariableType, "Byte"
            ListBox Add gDlg, %LbxVariableType, "Word"
            ListBox Add gDlg, %LbxVariableType, "Integer"
            ListBox Add gDlg, %LbxVariableType, "Long"
            ListBox Add gDlg, %LbxVariableType, "Dword"
            ListBox Add gDlg, %LbxVariableType, "Quad"
            ListBox Add gDlg, %LbxVariableType, "Single"
            ListBox Add gDlg, %LbxVariableType, "Double"
            ListBox Add gDlg, %LbxVariableType, "Currency"
            ListBox Add gDlg, %LbxVariableType, "CurrencyX"
            ListBox Add gDlg, %LbxVariableType, "Extended"
            Control Set Text gDlg, %TxtInstructions, "Select variable type."
        Case "Queue"
            ListBox Add gDlg, %LbxVariableType, "Byte"
            ListBox Add gDlg, %LbxVariableType, "Word"
            ListBox Add gDlg, %LbxVariableType, "Integer"
            ListBox Add gDlg, %LbxVariableType, "Long"
            ListBox Add gDlg, %LbxVariableType, "Dword"
            ListBox Add gDlg, %LbxVariableType, "Quad"
            ListBox Add gDlg, %LbxVariableType, "Single"
            ListBox Add gDlg, %LbxVariableType, "Double"
            ListBox Add gDlg, %LbxVariableType, "Currency"
            ListBox Add gDlg, %LbxVariableType, "CurrencyX"
            ListBox Add gDlg, %LbxVariableType, "Extended"
            Control Set Text gDlg, %TxtInstructions, "Select variable type."
    End Select
End Sub

Sub LbxVariableTypeSelectionChange()
    Control Set Text gDlg, %TxtInstructions, ""
    ListBox Get Text gDlg, %LbxVariableType To gVariableType
    Select Case gContainerType
        Case "Array"
            Control Set Text gDlg, %TxtInstructions, "Designate output file and click [Create]."
            BuildArray()
        Case "String Container"
            Control Set Text gDlg, %TxtInstructions, "Designate output file and click [Create]."
            BuildStringContainer()
        Case "Stack"
            Control Set Text gDlg, %TxtInstructions, "Designate output file and click [Create]."
            BuildStack()
        Case "Queue"
            Control Set Text gDlg, %TxtInstructions, "Designate output file and click [Create]."
            BuildQueue()
    End Select
End Sub

Sub BuildQueue()
    Select Case gVariableType
        Case "Byte"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Byt" In gCode
            Replace "VARLONG" With "Byte" In gCode
            Replace "VARSIZE" With "1" In gCode
        Case "Word"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Wrd" In gCode
            Replace "VARLONG" With "Word" In gCode
            Replace "VARSIZE" With "2" In gCode
        Case "Integer"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Int" In gCode
            Replace "VARLONG" With "Integer" In gCode
            Replace "VARSIZE" With "2" In gCode
        Case "Long"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Lng" In gCode
            Replace "VARLONG" With "Long" In gCode
            Replace "VARSIZE" With "4" In gCode
        Case "Dword"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Dwd" In gCode
            Replace "VARLONG" With "Dword" In gCode
            Replace "VARSIZE" With "4" In gCode
        Case "Quad"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Qud" In gCode
            Replace "VARLONG" With "Quad" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "Single"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Sng" In gCode
            Replace "VARLONG" With "Single" In gCode
            Replace "VARSIZE" With "4" In gCode
        Case "Double"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Dbl" In gCode
            Replace "VARLONG" With "Double" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "Currency"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Cur" In gCode
            Replace "VARLONG" With "Currency" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "CurrencyX"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Cux" In gCode
            Replace "VARLONG" With "CurrencyX" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "Extended"
            AddMemoryCode()
            AddQueueCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Ext" In gCode
            Replace "VARLONG" With "Extended" In gCode
            Replace "VARSIZE" With "10" In gCode
    End Select
End Sub

Sub BuildStack()
    Select Case gVariableType
        Case "Byte"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Byt" In gCode
            Replace "VARLONG" With "Byte" In gCode
            Replace "VARSIZE" With "1" In gCode
        Case "Word"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Wrd" In gCode
            Replace "VARLONG" With "Word" In gCode
            Replace "VARSIZE" With "2" In gCode
        Case "Integer"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Int" In gCode
            Replace "VARLONG" With "Integer" In gCode
            Replace "VARSIZE" With "2" In gCode
        Case "Long"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Lng" In gCode
            Replace "VARLONG" With "Long" In gCode
            Replace "VARSIZE" With "4" In gCode
        Case "Dword"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Dwd" In gCode
            Replace "VARLONG" With "Dword" In gCode
            Replace "VARSIZE" With "4" In gCode
        Case "Quad"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Qud" In gCode
            Replace "VARLONG" With "Quad" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "Single"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Sng" In gCode
            Replace "VARLONG" With "Single" In gCode
            Replace "VARSIZE" With "4" In gCode
        Case "Double"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Dbl" In gCode
            Replace "VARLONG" With "Double" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "Currency"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Cur" In gCode
            Replace "VARLONG" With "Currency" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "CurrencyX"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Cux" In gCode
            Replace "VARLONG" With "CurrencyX" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "Extended"
            AddMemoryCode()
            AddStackCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Ext" In gCode
            Replace "VARLONG" With "Extended" In gCode
            Replace "VARSIZE" With "10" In gCode
    End Select
End Sub

Sub BuildArray()
    Select Case gVariableType
        Case "Byte"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Byt" In gCode
            Replace "VARLONG" With "Byte" In gCode
            Replace "VARSIZE" With "1" In gCode
        Case "Word"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Wrd" In gCode
            Replace "VARLONG" With "Word" In gCode
            Replace "VARSIZE" With "2" In gCode
        Case "Integer"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Int" In gCode
            Replace "VARLONG" With "Integer" In gCode
            Replace "VARSIZE" With "2" In gCode
        Case "Long"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Lng" In gCode
            Replace "VARLONG" With "Long" In gCode
            Replace "VARSIZE" With "4" In gCode
        Case "Dword"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Dwd" In gCode
            Replace "VARLONG" With "Dword" In gCode
            Replace "VARSIZE" With "4" In gCode
        Case "Quad"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Qud" In gCode
            Replace "VARLONG" With "Quad" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "Single"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Sng" In gCode
            Replace "VARLONG" With "Single" In gCode
            Replace "VARSIZE" With "4" In gCode
        Case "Double"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Dbl" In gCode
            Replace "VARLONG" With "Double" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "Currency"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Cur" In gCode
            Replace "VARLONG" With "Currency" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "CurrencyX"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Cux" In gCode
            Replace "VARLONG" With "CurrencyX" In gCode
            Replace "VARSIZE" With "8" In gCode
        Case "Extended"
            AddMemoryCode()
            AddNumberArrayCode()
            gCode = gSB.String
            gSB.Clear
            Replace "VARSHORT" With "Ext" In gCode
            Replace "VARLONG" With "Extended" In gCode
            Replace "VARSIZE" With "10" In gCode
        Case "String"
            AddMemoryCode()
            AddFileUtilities()
            AddStringContainerCode()
            AddStringArrayCode()
            AddStringArrayExtraCode()
            gCode = gSB.String
            gSB.Clear
            Replace "CONTAINERUDT" With "StrT" In gCode
            Replace "VARSHORT" With "Str" In gCode
            Replace "VARLONG" With "String" In gCode
            Replace "VARSIZE" With "1" In gCode
            Replace "PEEKTYPE" With "Peek$" In gCode
        Case "WString"
            AddMemoryCode()
            AddFileUtilities()
            AddStringContainerCode()
            AddStringArrayCode()
            AddWStringArrayExtraCode()
            gCode = gSB.String
            gSB.Clear
            Replace "CONTAINERUDT" With "WStrT" In gCode
            Replace "VARSHORT" With "WStr" In gCode
            Replace "VARLONG" With "WString" In gCode
            Replace "VARSIZE" With "2" In gCode
            Replace "PEEKTYPE" With "Peek$$" In gCode
    End Select
End Sub

Sub BuildStringContainer()
    Select Case gVariableType
        Case "String"
            AddMemoryCode()
            AddStringContainerCode()
            gCode = gSB.String
            gSB.Clear
            Replace "CONTAINERUDT" With "StrT" In gCode
            Replace "VARSHORT" With "Str" In gCode
            Replace "VARLONG" With "String" In gCode
            Replace "VARSIZE" With "1" In gCode
            Replace "PEEKTYPE" With "Peek$" In gCode
        Case "WString"
            AddMemoryCode()
            AddStringContainerCode()
            gCode = gSB.String
            gSB.Clear
            Replace "CONTAINERUDT" With "WStrT" In gCode
            Replace "VARSHORT" With "WStr" In gCode
            Replace "VARLONG" With "WString" In gCode
            Replace "VARSIZE" With "2" In gCode
            Replace "PEEKTYPE" With "Peek$$" In gCode
    End Select
End Sub

Sub AddQueueCode()
    SS ""
    SS "#If Not %Def(%VARSHORTQueue230424)"
    SS "    %VARSHORTQueue230424 = 1"
    SS "    %VARSHORTQueueMax = 550"
    SS "    Type VARSHORTQueueNodeT"
    SS "        next As VARSHORTQueueNodeT Ptr"
    SS "        first As Long"
    SS "        last As Long"
    SS "        arr(1 To %VARSHORTQueueMax) As VARLONG"
    SS "    End Type"
    SS "    Type VARSHORTQueueT"
    SS "        tag As Long"
    SS "        count As Long"
    SS "        first As VARSHORTQueueNodeT Ptr"
    SS "        last As VARSHORTQueueNodeT Ptr"
    SS "    End Type"
    SS "    Sub VARSHORTQueueFinal(t As VARSHORTQueueT)"
    SS "        'call before variable goes out of scope to free memory"
    SS "        'not necessary to call if queue empty but good practice"
    SS "        VARSHORTQueueClear t"
    SS "    End Sub"
    SS "    Sub VARSHORTQueueClear(t As VARSHORTQueueT)"
    SS "        'empty queue"
    SS "        Local n As VARSHORTQueueNodeT Ptr"
    SS "        While t.first"
    SS "            n = t.first"
    SS "            t.first = @n.next"
    SS "            MemFree(n)"
    SS "        Wend"
    SS "        t.first = 0"
    SS "        t.last = 0"
    SS "        t.count = 0"
    SS "    End Sub"
    SS "    Function VARSHORTQueueCount(t As VARSHORTQueueT) As Long"
    SS "        'get item count"
    SS "        Function = t.count"
    SS "    End Function"
    SS "    Sub VARSHORTQueueAdd(t As VARSHORTQueueT, ByVal value As VARLONG)"
    SS "        'add value to end of queue"
    SS "        Local n As VARSHORTQueueNodeT Ptr"
    SS "        If t.count = 0 Then"
    SS "            t.last = MemAlloc(SizeOf(VARSHORTQueueNodeT))"
    SS "            If t.last = 0 Then Exit Sub"
    SS "            t.@last.arr(1) = value"
    SS "            t.@last.first = 1"
    SS "            t.@last.last = 1"
    SS "            t.first = t.last"
    SS "            t.count = 1"
    SS "        Else"
    SS "            If t.last = 0 Then Exit Sub"
    SS "            If t.@last.last < %VARSHORTQueueMax Then"
    SS "                Incr t.@last.last"
    SS "                t.@last.arr(t.@last.last) = value"
    SS "                Incr t.count"
    SS "            Else"
    SS "                n = MemAlloc(SizeOf(VARSHORTQueueNodeT))"
    SS "                If n = 0 Then Exit Sub"
    SS "                @n.arr(1) = value"
    SS "                @n.first = 1"
    SS "                @n.last = 1"
    SS "                t.@last.next = n"
    SS "                t.last = n"
    SS "                Incr t.count"
    SS "            End If"
    SS "        End If"
    SS "    End Sub"
    SS "    Function VARSHORTQueuePeek(t As VARSHORTQueueT) As VARLONG"
    SS "        'get first value in queue"
    SS "        If t.count Then"
    SS "            If t.first = 0 Then Exit Function"
    SS "            Function = t.@first.arr(t.@first.first)"
    SS "        End If"
    SS "    End Function"
    SS "    Function VARSHORTQueueGet(t As VARSHORTQueueT) As VARLONG"
    SS "        'get and remove first value in queue"
    SS "        Local n As VARSHORTQueueNodeT Ptr"
    SS "        If t.count Then"
    SS "            If t.first = 0 Then Exit Function"
    SS "            Function = t.@first.arr(t.@first.first)"
    SS "            Decr t.count"
    SS "            If t.count = 0 Then"
    SS "                VARSHORTQueueClear t"
    SS "            Else"
    SS "                Incr t.@first.first"
    SS "                If t.@first.first > t.@first.last Then"
    SS "                    n = t.first"
    SS "                    t.first = t.@first.next"
    SS "                    MemFree(n)"
    SS "                End If"
    SS "            End If"
    SS "        End If"
    SS "    End Function"
    SS "#EndIf '%VARSHORTQueue230424"
End Sub

Sub AddStackCode()
    SS ""
    SS "#If Not %Def(%VARSHORTStack231018)"
    SS "    %VARSHORTStack231018 = 1"
    SS "    %VARSHORTStackMax = 550"
    SS "    Type VARSHORTStackNodeT"
    SS "        prev As VARSHORTStackNodeT Ptr"
    SS "        index As Long"
    SS "        arr(1 To %VARSHORTStackMax) As VARLONG"
    SS "    End Type"
    SS "    Type VARSHORTStackT"
    SS "        count As Long"
    SS "        top As VARSHORTStackNodeT Ptr"
    SS "    End Type"
    SS "    Sub VARSHORTStackFinal(t As VARSHORTStackT)"
    SS "        'call before variable goes out of scope to free memory"
    SS "        'not necessary if stack empty but good practice"
    SS "        VARSHORTStackClear(t)"
    SS "    End Sub"
    SS "    Sub VARSHORTStackClear(t As VARSHORTStackT)"
    SS "        'empty stack"
    SS "        Local n As VARSHORTStackNodeT Ptr"
    SS "        While t.top"
    SS "            n = t.top"
    SS "            t.top = t.@top.prev"
    SS "            MemFree(n)"
    SS "        Wend"
    SS "        t.top = 0"
    SS "        t.count = 0"
    SS "    End Sub"
    SS "    Function VARSHORTStackCount(t As VARSHORTStackT) As Long"
    SS "        'get item count"
    SS "        Function = t.count"
    SS "    End Function"
    SS "    Sub VARSHORTStackPush(t As VARSHORTStackT, ByVal value As VARLONG)"
    SS "        'push value on top of stack"
    SS "        Local n As VARSHORTStackNodeT Ptr"
    SS "        If t.count = 0 Then"
    SS "            t.top = MemAlloc(SizeOf(VARSHORTStackNodeT))"
    SS "            If t.top Then"
    SS "                t.@top.arr(1) = value"
    SS "                t.@top.index = 1"
    SS "                t.count = 1"
    SS "            End If"
    SS "        ElseIf t.@top.index < %VARSHORTStackMax Then"
    SS "            Incr t.@top.index"
    SS "            t.@top.arr(t.@top.index) = value"
    SS "            Incr t.count"
    SS "        Else"
    SS "            n = MemAlloc(SizeOf(VARSHORTStackNodeT))"
    SS "            If n Then"
    SS "                @n.arr(1) = value"
    SS "                @n.index = 1"
    SS "                @n.prev = t.top"
    SS "                t.top = n"
    SS "                Incr t.count"
    SS "            End If"
    SS "        End If"
    SS "    End Sub"
    SS "    Function VARSHORTStackPeek(t As VARSHORTStackT) As VARLONG"
    SS "        'get tope value on stack"
    SS "        If t.count Then Function = t.@top.arr(t.@top.index)"
    SS "    End Function"
    SS "    Function VARSHORTStackPop(t As VARSHORTStackT) As VARLONG"
    SS "        'get and remove top value on stack"
    SS "        Local n As VARSHORTStackNodeT Ptr"
    SS "        If t.count Then"
    SS "            Function = t.@top.arr(t.@top.index)"
    SS "            Decr t.@top.index"
    SS "            Decr t.count"
    SS "            If t.@top.index = 0 Then"
    SS "                n = t.top"
    SS "                t.top = t.@top.prev"
    SS "                MemFree(n)"
    SS "            End If"
    SS "        End If"
    SS "    End Function"
    SS "#EndIf '%VARSHORTStack231018"
End Sub

Sub AddStringArrayCode()
    SS ""
    SS "#If Not %Def(%VARSHORTArr231018)"
    SS "    %VARSHORTArr231018 = 1"
    SS "    %VARSHORTArrMultiplier = 2"
    SS "    %VARSHORTArrBufferMax = 1000000"
    SS "    %VARSHORTArrBufferMin = 1"
    SS "    Type VARSHORTArrT"
    SS "        mem As Long"
    SS "        arr As VARSHORTT Ptr"
    SS "        count As Long"
    SS "        max As Long"
    SS "        compareCB As Long"
    SS "    End Type"
    SS "    Sub VARSHORTArrFinal(t As VARSHORTArrT)"
    SS "        'must call before variable goes out of scope to free memory"
    SS "        VARSHORTArrClear t"
    SS "    End Sub"
    SS "    Sub VARSHORTArrCompare(t As VARSHORTArrT, ByVal compareCB As Long)"
    SS "        ' set compare callback"
    SS "        ' default = case sensitive CodePtr(VARSHORTCompare)"
    SS "        ' set CodePtr(VARSHORTCompareIgnore) to ignore case"
    SS "        ' use custom callback CodePtr(procedure name)"
    SS "        t.compareCB = compareCB"
    SS "    End Sub"
    SS "    Sub VARSHORTArrClear(t As VARSHORTArrT)"
    SS "        'empty container"
    SS "        Register i As Long"
    SS "        For i = 1 To t.count"
    SS "            VARSHORTFinal t.@arr[i]"
    SS "        Next i"
    SS "        t.mem = MemFree(t.mem)"
    SS "        t.arr = 0"
    SS "        t.count = 0"
    SS "        t.max = 0"
    SS "    End Sub"
    SS "    Function VARSHORTArrCount(t As VARSHORTArrT) As Long"
    SS "        'get item count"
    SS "        Function = t.count"
    SS "    End Function"
    SS "    Function VARSHORTArrGet(t As VARSHORTArrT, ByVal index As Long) As VARLONG"
    SS "        'get value at one-based index"
    SS "        If index > 0 And index <= t.count Then Function = VARSHORTGet(t.@arr[index])"
    SS "    End Function"
    SS "    Sub VARSHORTArrSet(t As VARSHORTArrT, ByVal index As Long, ByRef value As VARLONG)"
    SS "        'set value at one-based index"
    SS "        If index > 0 And index <= t.count Then VARSHORTSet t.@arr[index], value"
    SS "    End Sub"
    SS "    Sub VARSHORTArrAdd(t As VARSHORTArrT, ByRef value As VARLONG)"
    SS "        'append value : memory management automatic"
    SS "        VARSHORTArrGrow t, 1"
    SS "        If t.mem = 0 Then Exit Sub"
    SS "        Incr t.count"
    SS "        VARSHORTSet t.@arr[t.count], value"
    SS "    End Sub"
    SS "    Sub VARSHORTArrInsert(t As VARSHORTArrT, ByVal index As Long, ByRef value As VARLONG)"
    SS "        'insert value at one-based index : memory management automatic"
    SS "        If index > 0 And index <= t.count Then"
    SS "            VARSHORTArrGrow t, 1"
    SS "            If t.mem = 0 Then Exit Sub"
    SS "            Incr t.count"
    SS "            VARSHORTArrMove(t, index, index + 1, t.count - index)"
    SS "            VARSHORTSet t.@arr[index], value"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrDelete(t As VARSHORTArrT, ByVal index As Long)"
    SS "        'delete value at one-based index : memory management automatic"
    SS "        If index > 0 And index <= t.count Then"
    SS "            VARSHORTFinal t.@arr[index]"
    SS "            If index < t.count Then VARSHORTArrMove(t, index + 1, index, t.count - index)"
    SS "            Decr t.count"
    SS "            If t.max - t.count > (2 * (t.count * %VARSHORTArrMultiplier)) Then VARSHORTArrShrink(t)"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrFastDelete(t As VARSHORTArrT, ByVal index As Long)"
    SS "        'fast delete value at one-based index : memory management automatic"
    SS "        'fast on massive array but destroys array order"
    SS "        'traverse back to front to use"
    SS "        If index > 0 And index <= t.count Then"
    SS "            VARSHORTFinal t.@arr[index]"
    SS "            If index < t.count Then Swap t.@arr[index], t.@arr[t.count]"
    SS "            Decr t.count"
    SS "            If t.max - t.count > (2 * (t.count * %VARSHORTArrMultiplier)) Then VARSHORTArrShrink(t)"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrSort(t As VARSHORTArrT)"
    SS "        'sort array"
    SS "        Register i As Long"
    SS "        Register j As Long"
    SS "        Local k, leftIndex, rightIndex, counter, compare As Long"
    SS "        Local value As VARLONG"
    SS "        If t.compareCB = 0 Then t.compareCB = CodePtr(VARSHORTCompare)"
    SS "        If t.count > 1 Then"
    SS "            leftIndex = 1 : rightIndex = t.count : counter = 1"
    SS "            !PUSH leftIndex"
    SS "            !PUSH rightIndex"
    SS "            While counter"
    SS "                Decr counter"
    SS "                !POP rightIndex"
    SS "                !POP leftIndex"
    SS "                i = leftIndex : j = rightIndex : k = i + j : Shift Right k, 1: value = VARSHORTGet(t.@arr[k])"
    SS "                While i <= j"
    SS "                    Call Dword t.compareCB Using VARSHORTCompare(VARSHORTGet(t.@arr[i]), value) To compare"
    SS "                    While compare < 0"
    SS "                        Incr i"
    SS "                        Call Dword t.compareCB Using VARSHORTCompare(VARSHORTGet(t.@arr[i]), value) To compare"
    SS "                    Wend"
    SS "                    Call Dword t.compareCB Using VARSHORTCompare(VARSHORTGet(t.@arr[j]), value) To compare"
    SS "                    While compare > 0"
    SS "                        Decr j"
    SS "                        Call Dword t.compareCB Using VARSHORTCompare(VARSHORTGet(t.@arr[j]), value) To compare"
    SS "                    Wend"
    SS "                    If i <= j Then"
    SS "                        Swap t.@arr[i], t.@arr[j] : Incr i : Decr j"
    SS "                    End If"
    SS "                Wend"
    SS "                If leftIndex < j Then"
    SS "                    !PUSH leftIndex"
    SS "                    !PUSH j"
    SS "                    Incr counter"
    SS "                End If"
    SS "                If i < rightIndex Then"
    SS "                    !PUSH i"
    SS "                    !PUSH rightIndex"
    SS "                    Incr counter"
    SS "                End If"
    SS "            Wend"
    SS "        End If"
    SS "    End Sub"
    SS "    Function VARSHORTArrSortSearch(t As VARSHORTArrT, ByRef value As VARLONG) As Long"
    SS "        'binary search for value : return index : zero if not found : array must be sorted"
    SS "        Register i As Long"
    SS "        Local bot, top, compare As Long"
    SS "        If t.compareCB = 0 Then t.compareCB = CodePtr(VARSHORTCompare)"
    SS "        If t.count Then"
    SS "            bot = 1 : top = t.count"
    SS "            While top >= bot"
    SS "                i = bot + top : Shift Right i, 1"
    SS "                Call Dword t.compareCB Using VARSHORTCompare(value, VARSHORTGet(t.@arr[i])) To compare"
    SS "                If compare > 0 Then"
    SS "                    bot = i + 1"
    SS "                ElseIf compare < 0 Then"
    SS "                    top = i - 1"
    SS "                Else"
    SS "                    Function = i : Exit Function"
    SS "                End If"
    SS "            Wend"
    SS "        End If"
    SS "    End Function"
    SS "    Sub VARSHORTArrSortInsert(t As VARSHORTArrT, ByRef value As VARLONG)"
    SS "        'insert value at sort position : added if empty : array must be sorted or empty"
    SS "        Register i As Long"
    SS "        Local bot, top, compare As Long"
    SS "        If t.compareCB = 0 Then t.compareCB = CodePtr(VARSHORTCompare)"
    SS "        If t.count Then"
    SS "            bot = 1 : top = t.count"
    SS "            While top >= bot"
    SS "                i = bot + top : Shift Right i, 1"
    SS "                Call Dword t.compareCB Using VARSHORTCompare(value, VARSHORTGet(t.@arr[i])) To compare"
    SS "                If compare > 0 Then"
    SS "                    bot = i + 1"
    SS "                ElseIf compare < 0 Then"
    SS "                    top = i - 1"
    SS "                Else"
    SS "                    VARSHORTArrInsert(t, i, value) : Exit Sub"
    SS "                End If"
    SS "            Wend"
    SS "            If compare < 0 Then"
    SS "                VARSHORTArrInsert(t, i, value)"
    SS "            ElseIf i < t.count Then"
    SS "                VARSHORTArrInsert(t, i + 1, value)"
    SS "            Else"
    SS "               VARSHORTArrAdd(t, value)"
    SS "            End If"
    SS "        Else"
    SS "            VARSHORTArrAdd(t, value)"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrSortDelete(t As VARSHORTArrT, ByRef value As VARLONG)"
    SS "        'binary search for value : delete one instance if found : array must be sorted"
    SS "        Local x As Long"
    SS "        x = VARSHORTArrSortSearch(t, value)"
    SS "        If x Then VARSHORTArrDelete(t, x)"
    SS "    End Sub"
    SS "    Sub VARSHORTArrUnique(t As VARSHORTArrT)"
    SS "        'delete all duplicates using current compare callback : not sorted when done"
    SS "        Register i As Long"
    SS "        Local compare As Long"
    SS "        If t.compareCB = 0 Then t.compareCB = CodePtr(VARSHORTCompare)"
    SS "        If t.count > 1 Then"
    SS "            VARSHORTArrSort(t)"
    SS "            For i = t.count - 1 To 1 Step -1"
    SS "                Call Dword t.compareCB Using VARSHORTCompare(VARSHORTGet(t.@arr[i]), VARSHORTGet(t.@arr[i + 1])) To compare"
    SS "                If compare = 0 Then VARSHORTArrFastDelete(t, i + 1)"
    SS "            Next i"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrReverse(t As VARSHORTArrT)"
    SS "        'reverse array"
    SS "        Register i As Long"
    SS "        Register j As Long"
    SS "        If t.count > 1 Then"
    SS "            i = 1 : j = t.count"
    SS "            While i < j"
    SS "                Swap t.@arr[i], t.@arr[j] : Incr i : Decr j"
    SS "            Wend"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrSwap(t As VARSHORTArrT, ByVal a As Long, ByVal b As Long)"
    SS "        'swap index a and and index b"
    SS "        If a > 0 And b > 0 And a <= t.count And b <= t.count Then"
    SS "            Swap t.@arr[a], t.@arr[b]"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrSplit(t As VARSHORTArrT, ByVal delimited As WString, ByVal delimiter As WString)"
    SS "        'split array on delimited string"
    SS "        Local i, items As Long"
    SS "        Local a() As VARLONG"
    SS "        VARSHORTArrClear(t)"
    SS "        If Len(delimited) Then"
    SS "            items = ParseCount(delimited, delimiter)"
    SS "            Dim a(1 To items)"
    SS "            Parse delimited, a(), delimiter"
    SS "            For i = 1 To items"
    SS "                VARSHORTArrAdd t, a(i)"
    SS "            Next i"
    SS "        End If"
    SS "    End Sub"
    SS "    Function VARSHORTArrJoin(t As VARSHORTArrT, ByVal delimiter As WString) As WString"
    SS "        'join array as delimited string"
    SS "        Local i As Long"
    SS "        Local a() As VARLONG"
    SS "        If t.count Then"
    SS "            Dim a(1 To t.count)"
    SS "            For i = 1 To t.count"
    SS "                a(i) = VARSHORTArrGet(t, i)"
    SS "            Next i"
    SS "            Function = Join$(a(), delimiter)"
    SS "        End If"
    SS "    End Function"
    SS "    Sub VARSHORTArrPushFirst(t As VARSHORTArrT, ByRef value As VARLONG)"
    SS "        'insert at front"
    SS "        If VARSHORTArrCount(t) Then VARSHORTArrInsert(t, 1, value) Else VARSHORTArrAdd(t, value)"
    SS "    End Sub"
    SS "    Function VARSHORTArrPeekFirst(t As VARSHORTArrT) As VARLONG"
    SS "        'get first value"
    SS "        If VARSHORTArrCount(t) Then Function = VARSHORTArrGet(t, 1)"
    SS "    End Function"
    SS "    Function VARSHORTArrPopFirst(t As VARSHORTArrT) As VARLONG"
    SS "        'get and remove first value"
    SS "        If VARSHORTArrCount(t) Then"
    SS "            Function = VARSHORTArrGet(t, 1)"
    SS "            VARSHORTArrDelete(t, 1)"
    SS "        End If"
    SS "    End Function"
    SS "    Sub VARSHORTArrPushLast(t As VARSHORTArrT, ByRef value As VARLONG)"
    SS "        'append to end"
    SS "        VARSHORTArrAdd(t, value)"
    SS "    End Sub"
    SS "    Function VARSHORTArrPeekLast(t As VARSHORTArrT) As VARLONG"
    SS "        'get last value"
    SS "        If VARSHORTArrCount(t) Then Function = VARSHORTArrGet(t, VARSHORTArrCount(t))"
    SS "    End Function"
    SS "    Function VARSHORTArrPopLast(t As VARSHORTArrT) As VARLONG"
    SS "        'get and remove last value"
    SS "        If VARSHORTArrCount(t) Then"
    SS "            Function = VARSHORTArrGet(t, VARSHORTArrCount(t))"
    SS "            VARSHORTArrDelete(t, VARSHORTArrCount(t))"
    SS "        End If"
    SS "    End Function"
    SS "    Sub VARSHORTArrGrow(t As VARSHORTArrT, ByVal items As Long)"
    SS "        'make room for items : not necessary to call : memory management automatic"
    SS "        Local buffer, currentcount, newmax As Long"
    SS "        If t.max - t.count < items Then"
    SS "            buffer = t.count * %VARSHORTArrMultiplier"
    SS "            If buffer > %VARSHORTArrBufferMax Then buffer = %VARSHORTArrBufferMax"
    SS "            If buffer < %VARSHORTArrBufferMin Then buffer = %VARSHORTArrBufferMin"
    SS "            newmax = t.count + buffer + items"
    SS "            currentcount = t.count"
    SS "            t.arr = 0"
    SS "            t.count = 0"
    SS "            t.max = 0"
    SS "            t.mem = MemReAlloc(t.mem, newmax * 8)"
    SS "            If t.mem = 0 Then Exit Sub"
    SS "            t.arr = t.mem - 8"
    SS "            t.count = currentcount"
    SS "            t.max = newmax"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrShrink(t As VARSHORTArrT)"
    SS "        'free excess memory"
    SS "        Local currentcount As Long"
    SS "        If t.count = 0 Then"
    SS "            VARSHORTArrClear(t)"
    SS "        ElseIf t.max > t.count Then"
    SS "            currentcount = t.count"
    SS "            t.arr = 0"
    SS "            t.count = 0"
    SS "            t.max = 0"
    SS "            t.mem = MemReAlloc(t.mem, currentcount * 8)"
    SS "            If t.mem = 0 Then Exit Sub"
    SS "            t.arr = t.mem - 8"
    SS "            t.count = currentcount"
    SS "            t.max = currentcount"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrMove(t As VARSHORTArrT, ByVal fromIndex As Long, ByVal toIndex As Long, ByVal items As Long) Private"
    SS "        'PRIVATE: move memory block"
    SS "        Memory Copy t.arr + (fromIndex * 8), t.arr + (toIndex * 8), items * 8"
    SS "    End Sub"
    SS "#EndIf '%VARSHORTArr231018"
End Sub

Sub AddStringArrayExtraCode()
    SS ""
    SS "#If Not %Def(%StrArrExtra231018)"
    SS "    %StrArrExtra231018 = 1"
    SS "    Sub StrArrToTextFile(t As StrArrT, ByVal file As WString)"
    SS "        'store array as text file"
    SS "        StrToFile file, Trim$(StrArrJoin(t, $CrLf), $CrLf) + $CrLf"
    SS "    End Sub"
    SS "    Sub StrArrFromTextFile(t As StrArrT, ByVal file As WString)"
    SS "        'load text file"
    SS "        StrArrClear t"
    SS "        StrArrSplit t, Trim$(StrFromFile(file), $CrLf), $CrLf"
    SS "    End Sub"
    SS "#EndIf '%StrArrExtra231018"
End Sub

Sub AddWStringArrayExtraCode()
    SS ""
    SS "#If Not %Def(%WStrArrExtra231018)"
    SS "    %WStrArrExtra231018 = 1"
    SS "    Sub WStrArrToTextFile(t As WStrArrT, ByVal file As WString)"
    SS "        'store array as text file converting to UTF8"
    SS "        WStrToTextFile file, Trim$(WStrArrJoin(t, $CrLf), $CrLf) + $CrLf"
    SS "    End Sub"
    SS "    Sub WStrArrFromTextFile(t As WStrArrT, ByVal file As WString)"
    SS "        'load text file converted from UTF8 fixing unix (android) line endings if present"
    SS "        WStrArrClear t"
    SS "        WStrArrSplit t, Trim$(WStrFromTextFileFixed(file), $CrLf), $CrLf"
    SS "    End Sub"
    SS "    Sub WStrArrFolders(t As WStrArrT, ByVal rootFolder As WString)"
    SS "        'get all folders in root folder"
    SS "        Local folder, folderMask, rootPath As WString"
    SS "        Local DrD As DirData"
    SS "        WStrArrClear t"
    SS "        If IsFalse IsFolder(rootFolder) Then Exit Sub"
    SS "        rootPath = RTrim$(rootFolder, ""\"") + ""\"""
    SS "        folderMask = rootPath"
    SS "        folder = Dir$(folderMask, Only %SubDir To DrD)"
    SS "        While Len(folder)"
    SS "            WStrArrAdd t, rootPath + folder"
    SS "            folder = Dir$"
    SS "        Wend"
    SS "    End Sub"
    SS "    Sub WStrArrFiles(t As WStrArrT, ByVal folder As WString, ByVal mask As WString)"
    SS "        'get all files in folder matching mask"
    SS "        Local file, fileMask As WString"
    SS "        WStrArrClear t"
    SS "        If IsFalse IsFolder(folder) Then Exit Sub"
    SS "        folder = RTrim$(folder, ""\"") + ""\"""
    SS "        fileMask = folder + mask"
    SS "        file = Dir$(fileMask)"
    SS "        While Len(file)"
    SS "            WStrArrAdd t, folder + file"
    SS "            file = Dir$"
    SS "        Wend"
    SS "    End Sub"
    SS "    Sub WStrArrAllFolders(t As WStrArrT, ByVal rootFolder As WString)"
    SS "        'get all folders in root folder and sub-folders, including root folder"
    SS "        Local folders, subFolders As WStrArrT"
    SS "        Local currentFolder As WString"
    SS "        WStrArrClear t"
    SS "        If IsFalse IsFolder(rootFolder) Then Exit Sub"
    SS "        WStrArrPushLast folders, rootFolder"
    SS "        While WStrArrCount(folders)"
    SS "            currentFolder = WStrArrPopLast(folders)"
    SS "            WStrArrAdd t, currentFolder"
    SS "            WStrArrFolders subFolders, currentFolder"
    SS "            While WStrArrCount(subFolders)"
    SS "                WStrArrPushLast folders, WStrArrPopLast(subFolders)"
    SS "            Wend"
    SS "        Wend"
    SS "        WStrArrFinal(folders) : WStrArrFinal(subFolders)"
    SS "    End Sub"
    SS "    Sub WStrArrAllFiles(t As WStrArrT, ByVal rootFolder As WString, ByVal mask As WString)"
    SS "        'get all files in root folder, and sub-folders, matching mask"
    SS "        Local allFolders, folderFiles As WStrArrT"
    SS "        WStrArrClear t"
    SS "        If IsFalse IsFolder(rootFolder) Then Exit Sub"
    SS "        WStrArrAllFolders allFolders, rootFolder"
    SS "        While WStrArrCount(allFolders)"
    SS "            WStrArrFiles folderFiles, WStrArrPopLast(allFolders), mask"
    SS "            While WStrArrCount(folderFiles)"
    SS "                WStrArrAdd t, WStrArrPopLast(folderFiles)"
    SS "            Wend"
    SS "        Wend"
    SS "        WStrArrFinal(allFolders) : WStrArrFinal(folderFiles)"
    SS "    End Sub"
    SS "#EndIf '%WStrArrExtra231018"
End Sub

Sub AddNumberArrayCode()
    SS ""
    SS "#If Not %Def(%VARSHORTArr231018)"
    SS "    %VARSHORTArr231018 = 1"
    SS "    %VARSHORTArrMultiplier = 2"
    SS "    %VARSHORTArrBufferMax = 1000000"
    SS "    %VARSHORTArrBufferMin = 1"
    SS "    Type VARSHORTArrT"
    SS "        mem As Long"
    SS "        arr As VARLONG Ptr"
    SS "        count As Long"
    SS "        max As Long"
    SS "    End Type"
    SS "    Sub VARSHORTArrFinal(t As VARSHORTArrT)"
    SS "        'must call before variable goes out of scope to free memory"
    SS "        VARSHORTArrClear t"
    SS "    End Sub"
    SS "    Sub VARSHORTArrClear(t As VARSHORTArrT)"
    SS "        'empty container"
    SS "        t.mem = MemFree(t.mem)"
    SS "        t.arr = 0"
    SS "        t.count = 0"
    SS "        t.max = 0"
    SS "    End Sub"
    SS "    Function VARSHORTArrCount(t As VARSHORTArrT) As Long"
    SS "        'get item count"
    SS "        Function = t.count"
    SS "    End Function"
    SS "    Function VARSHORTArrGet(t As VARSHORTArrT, ByVal index As Long) As VARLONG"
    SS "        'get value at one-based index"
    SS "        If index > 0 And index <= t.count Then Function = t.@arr[index]"
    SS "    End Function"
    SS "    Sub VARSHORTArrSet(t As VARSHORTArrT, ByVal index As Long, ByVal value As VARLONG)"
    SS "        'set value at one-based index"
    SS "        If index > 0 And index <= t.count Then t.@arr[index] = value"
    SS "    End Sub"
    SS "    Sub VARSHORTArrAdd(t As VARSHORTArrT, ByVal value As VARLONG)"
    SS "        'append value : memory management automatic"
    SS "        VARSHORTArrGrow t, 1"
    SS "        If t.mem = 0 Then Exit Sub"
    SS "        Incr t.count"
    SS "        t.@arr[t.count] = value"
    SS "    End Sub"
    SS "    Sub VARSHORTArrInsert(t As VARSHORTArrT, ByVal index As Long, ByVal value As VARLONG)"
    SS "        'insert value at one-based index : memory management automatic"
    SS "        If index > 0 And index <= t.count Then"
    SS "            VARSHORTArrGrow t, 1"
    SS "            If t.mem = 0 Then Exit Sub"
    SS "            Incr t.count"
    SS "            VARSHORTArrMove(t, index, index + 1, t.count - index)"
    SS "            t.@arr[index] = value"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrDelete(t As VARSHORTArrT, ByVal index As Long)"
    SS "        'delete value at one-based index : memory management automatic"
    SS "        If index > 0 And index <= t.count Then"
    SS "            If index < t.count Then VARSHORTArrMove(t, index + 1, index, t.count - index)"
    SS "            Decr t.count"
    SS "            If t.max - t.count > (2 * (t.count * %VARSHORTArrMultiplier)) Then VARSHORTArrShrink(t)"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrFastDelete(t As VARSHORTArrT, ByVal index As Long)"
    SS "        'fast delete value at one-based index : memory management automatic"
    SS "        'fast on massive array but destroys array order"
    SS "        'traverse back to front to use"
    SS "        If index > 0 And index <= t.count Then"
    SS "            If index < t.count Then Swap t.@arr[index], t.@arr[t.count]"
    SS "            Decr t.count"
    SS "            If t.max - t.count > (2 * (t.count * %VARSHORTArrMultiplier)) Then VARSHORTArrShrink(t)"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrSort(t As VARSHORTArrT)"
    SS "        'sort array"
    SS "        Register i As Long"
    SS "        Register j As Long"
    SS "        Local k, leftIndex, rightIndex, counter As Long"
    SS "        Local value As VARLONG"
    SS "        If t.count > 1 Then"
    SS "            leftIndex = 1 : rightIndex = t.count : counter = 1"
    SS "            !PUSH leftIndex"
    SS "            !PUSH rightIndex"
    SS "            While counter"
    SS "                Decr counter"
    SS "                !POP rightIndex"
    SS "                !POP leftIndex"
    SS "                i = leftIndex : j = rightIndex : k = i + j : Shift Right k, 1: value = t.@arr[k]"
    SS "                While i <= j"
    SS "                    While t.@arr[i] < value"
    SS "                        Incr i"
    SS "                    Wend"
    SS "                    While t.@arr[j] > value"
    SS "                        Decr j"
    SS "                    Wend"
    SS "                    If i <= j Then"
    SS "                        Swap t.@arr[i], t.@arr[j] : Incr i : Decr j"
    SS "                    End If"
    SS "                Wend"
    SS "                If leftIndex < j Then"
    SS "                    !PUSH leftIndex"
    SS "                    !PUSH j"
    SS "                    Incr counter"
    SS "                End If"
    SS "                If i < rightIndex Then"
    SS "                    !PUSH i"
    SS "                    !PUSH rightIndex"
    SS "                    Incr counter"
    SS "                End If"
    SS "            Wend"
    SS "        End If"
    SS "    End Sub"
    SS "    Function VARSHORTArrSortSearch(t As VARSHORTArrT, ByVal value As VARLONG) As Long"
    SS "        'binary search for value : return index : zero if not found : array must be sorted"
    SS "        Register i As Long"
    SS "        Local bot, top, compare As Long"
    SS "        If t.count Then"
    SS "            bot = 1 : top = t.count"
    SS "            While top >= bot"
    SS "                i = bot + top : Shift Right i, 1"
    SS "                compare = Switch&(value < t.@arr[i], -1, value > t.@arr[i], 1)"
    SS "                If compare > 0 Then"
    SS "                    bot = i + 1"
    SS "                ElseIf compare < 0 Then"
    SS "                    top = i - 1"
    SS "                Else"
    SS "                    Function = i : Exit Function"
    SS "                End If"
    SS "            Wend"
    SS "        End If"
    SS "    End Function"
    SS "    Sub VARSHORTArrSortInsert(t As VARSHORTArrT, ByVal value As VARLONG)"
    SS "        'insert value at sort position : added if empty : array must be sorted or empty"
    SS "        Register i As Long"
    SS "        Local bot, top, compare As Long"
    SS "        If t.count Then"
    SS "            bot = 1 : top = t.count"
    SS "            While top >= bot"
    SS "                i = bot + top : Shift Right i, 1"
    SS "                compare = Switch&(value < t.@arr[i], -1, value > t.@arr[i], 1)"
    SS "                If compare > 0 Then"
    SS "                    bot = i + 1"
    SS "                ElseIf compare < 0 Then"
    SS "                    top = i - 1"
    SS "                Else"
    SS "                    VARSHORTArrInsert(t, i, value) : Exit Sub"
    SS "                End If"
    SS "            Wend"
    SS "            If compare < 0 Then"
    SS "                VARSHORTArrInsert(t, i, value)"
    SS "            ElseIf i < t.count Then"
    SS "                VARSHORTArrInsert(t, i + 1, value)"
    SS "            Else"
    SS "               VARSHORTArrAdd(t, value)"
    SS "            End If"
    SS "        Else"
    SS "            VARSHORTArrAdd(t, value)"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrSortDelete(t As VARSHORTArrT, ByVal value As VARLONG)"
    SS "        'binary search for value : delete one instance if found : array must be sorted"
    SS "        Local x As Long"
    SS "        x = VARSHORTArrSortSearch(t, value)"
    SS "        If x Then VARSHORTArrDelete(t, x)"
    SS "    End Sub"
    SS "    Sub VARSHORTArrUnique(t As VARSHORTArrT)"
    SS "        'delete all duplicates using current compare callback : not sorted when done"
    SS "        Register i As Long"
    SS "        If t.count > 1 Then"
    SS "            VARSHORTArrSort(t)"
    SS "            For i = t.count - 1 To 1 Step -1"
    SS "                If t.@arr[i] = t.@arr[i + 1] Then VARSHORTArrFastDelete(t, i + 1)"
    SS "            Next i"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrReverse(t As VARSHORTArrT)"
    SS "        'reverse array"
    SS "        Register i As Long"
    SS "        Register j As Long"
    SS "        If t.count > 1 Then"
    SS "            i = 1 : j = t.count"
    SS "            While i < j"
    SS "                Swap t.@arr[i], t.@arr[j] : Incr i : Decr j"
    SS "            Wend"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrSwap(t As VARSHORTArrT, ByVal a As Long, ByVal b As Long)"
    SS "        'swap index a and and index b"
    SS "        If a > 0 And b > 0 And a <= t.count And b <= t.count Then"
    SS "            Swap t.@arr[a], t.@arr[b]"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrSplit(t As VARSHORTArrT, ByVal delimited As WString, ByVal delimiter As WString)"
    SS "        'split array on delimited string"
    SS "        Local i, items As Long"
    SS "        Local a() As String"
    SS "        VARSHORTArrClear(t)"
    SS "        If Len(delimited) Then"
    SS "            items = ParseCount(delimited, delimiter)"
    SS "            Dim a(1 To items)"
    SS "            Parse delimited, a(), delimiter"
    SS "            For i = 1 To items"
    SS "                VARSHORTArrAdd t, Val(a(i))"
    SS "            Next i"
    SS "        End If"
    SS "    End Sub"
    SS "    Function VARSHORTArrJoin(t As VARSHORTArrT, ByVal delimiter As WString) As WString"
    SS "        'join array as delimited string"
    SS "        Local i As Long"
    SS "        Local a() As String"
    SS "        If t.count Then"
    SS "            Dim a(1 To t.count)"
    SS "            For i = 1 To t.count"
    SS "                a(i) = Format$(VARSHORTArrGet(t, i))"
    SS "            Next i"
    SS "            Function = Join$(a(), delimiter)"
    SS "        End If"
    SS "    End Function"
    SS "    Sub VARSHORTArrPushFirst(t As VARSHORTArrT, ByVal value As VARLONG)"
    SS "        'insert at front"
    SS "        If VARSHORTArrCount(t) Then VARSHORTArrInsert(t, 1, value) Else VARSHORTArrAdd(t, value)"
    SS "    End Sub"
    SS "    Function VARSHORTArrPeekFirst(t As VARSHORTArrT) As VARLONG"
    SS "        'get first value"
    SS "        If VARSHORTArrCount(t) Then Function = VARSHORTArrGet(t, 1)"
    SS "    End Function"
    SS "    Function VARSHORTArrPopFirst(t As VARSHORTArrT) As VARLONG"
    SS "        'get and remove first value"
    SS "        If VARSHORTArrCount(t) Then"
    SS "            Function = VARSHORTArrGet(t, 1)"
    SS "            VARSHORTArrDelete(t, 1)"
    SS "        End If"
    SS "    End Function"
    SS "    Sub VARSHORTArrPushLast(t As VARSHORTArrT, ByVal value As VARLONG)"
    SS "        'append to end"
    SS "        VARSHORTArrAdd(t, value)"
    SS "    End Sub"
    SS "    Function VARSHORTArrPeekLast(t As VARSHORTArrT) As VARLONG"
    SS "        'get last value"
    SS "        If VARSHORTArrCount(t) Then Function = VARSHORTArrGet(t, VARSHORTArrCount(t))"
    SS "    End Function"
    SS "    Function VARSHORTArrPopLast(t As VARSHORTArrT) As VARLONG"
    SS "        'get and remove last value"
    SS "        If VARSHORTArrCount(t) Then"
    SS "            Function = VARSHORTArrGet(t, VARSHORTArrCount(t))"
    SS "            VARSHORTArrDelete(t, VARSHORTArrCount(t))"
    SS "        End If"
    SS "    End Function"
    SS "    Sub VARSHORTArrGrow(t As VARSHORTArrT, ByVal items As Long)"
    SS "        'make room for items : not necessary to call : memory management automatic"
    SS "        Local buffer, currentcount, newmax As Long"
    SS "        If t.max - t.count < items Then"
    SS "            buffer = t.count * %VARSHORTArrMultiplier"
    SS "            If buffer > %VARSHORTArrBufferMax Then buffer = %VARSHORTArrBufferMax"
    SS "            If buffer < %VARSHORTArrBufferMin Then buffer = %VARSHORTArrBufferMin"
    SS "            newmax = t.count + buffer + items"
    SS "            currentcount = t.count"
    SS "            t.arr = 0"
    SS "            t.count = 0"
    SS "            t.max = 0"
    SS "            t.mem = MemReAlloc(t.mem, newmax * VARSIZE)"
    SS "            If t.mem = 0 Then Exit Sub"
    SS "            t.arr = t.mem - VARSIZE"
    SS "            t.count = currentcount"
    SS "            t.max = newmax"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrShrink(t As VARSHORTArrT)"
    SS "        'free excess memory"
    SS "        Local currentcount As Long"
    SS "        If t.count = 0 Then"
    SS "            VARSHORTArrClear(t)"
    SS "        ElseIf t.max > t.count Then"
    SS "            currentcount = t.count"
    SS "            t.arr = 0"
    SS "            t.count = 0"
    SS "            t.max = 0"
    SS "            t.mem = MemReAlloc(t.mem, currentcount * VARSIZE)"
    SS "            If t.mem = 0 Then Exit Sub"
    SS "            t.arr = t.mem - VARSIZE"
    SS "            t.count = currentcount"
    SS "            t.max = currentcount"
    SS "        End If"
    SS "    End Sub"
    SS "    Sub VARSHORTArrMove(t As VARSHORTArrT, ByVal fromIndex As Long, ByVal toIndex As Long, ByVal items As Long) Private"
    SS "        'PRIVATE: move memory block"
    SS "        Memory Copy t.arr + (fromIndex * VARSIZE), t.arr + (toIndex * VARSIZE), items * VARSIZE"
    SS "    End Sub"
    SS "#EndIf '%VARSHORTArr231018"
End Sub

Sub AddStringContainerCode()
    SS ""
    SS "#If Not %Def(%VARSHORT231018)"
    SS "    %VARSHORT231018 = 1"
    SS "    Declare Function VARSHORTCompare(ByRef a As VARLONG, ByRef b As VARLONG) As Long"
    SS "        'a < b : return < 0"
    SS "        'a = b : return = 0"
    SS "        'a > b : return > 0"
    SS "    Type CONTAINERUDT"
    SS "        count As Long"
    SS "        mem As Long"
    SS "    End Type"
    SS "    Sub VARSHORTFinal(t As CONTAINERUDT)"
    SS "        'must call before variable goes out of scope"
    SS "        VARSHORTClear t"
    SS "    End Sub"
    SS "    Sub VARSHORTClear(t As CONTAINERUDT)"
    SS "        'empty container"
    SS "        t.count = 0"
    SS "        t.mem = MemFree(t.mem)"
    SS "    End Sub"
    SS "    Function VARSHORTCount(t As CONTAINERUDT) As Long"
    SS "        'get character count"
    SS "        Function = t.count"
    SS "    End Function"
    SS "    Sub VARSHORTSet(t As CONTAINERUDT, ByRef value As VARLONG)"
    SS "        'set string"
    SS "        Local lenValue As Long : lenValue = Len(value)"
    SS "        VARSHORTClear t"
    SS "        If lenValue Then"
    SS "            t.mem = MemAlloc(lenValue * VARSIZE)"
    SS "            If t.mem = 0 Then Exit Sub"
    SS "            t.count = lenValue"
    SS "            Memory Copy StrPtr(value), t.mem, lenValue * VARSIZE"
    SS "        End If"
    SS "    End Sub"
    SS "    Function VARSHORTGet(t As CONTAINERUDT) As VARLONG"
    SS "        'get string"
    SS "        If t.count Then Function = PEEKTYPE(t.mem, t.count)"
    SS "    End Function"
    SS "    Function VARSHORTCompare(ByRef a As VARLONG, ByRef b As VARLONG) As Long"
    SS "        'case sensitive compare callback"
    SS "        Function = Switch&(a < b, -1, a > b, 1) 'else match"
    SS "    End Function"
    SS "    Function VARSHORTCompareIgnore(ByRef a As VARLONG, ByRef b As VARLONG) As Long"
    SS "        'ignore calse compare callback"
    SS "        Local sa As VARLONG : sa = UCase$(a)"
    SS "        Local sb As VARLONG : sb = UCase$(b)"
    SS "        Function = Switch&(sa < sb, -1, sa > sb, 1) 'else match"
    SS "    End Function"
    SS "#EndIf '%VARSHORT231018"
End Sub

Sub AddFileUtilities()
    SS ""
    SS "#If Not %Def(%FileUtilities231018)"
    SS "    %FileUtilities231018 = 1"
    SS "    Sub StrToFile(ByRef file As WString, ByRef value As String)"
    SS "        'store string to File"
    SS "        Local f As Long"
    SS "        If Len(file) = 0 Then Exit Sub"
    SS "        f = FreeFile"
    SS "        Open file For Binary As f"
    SS "        SetEof f"
    SS "        Put$ f, value"
    SS "        Close f"
    SS "    End Sub"
    SS "    Function StrFromFile(ByRef file As WString) As String"
    SS "        'get file contents as string"
    SS "        Local f As Long"
    SS "        Local value As String"
    SS "        If IsFalse IsFile(file) Then Exit Function"
    SS "        f = FreeFile"
    SS "        Open file For Binary As f"
    SS "        Get$ f, Lof(f), value"
    SS "        Function = value"
    SS "        Close f"
    SS "    End Function"
    SS "    Function StrFromFileFixed(ByRef file As WString) As String"
    SS "        'get file contents converted from Unix line endings if any"
    SS "        Local value As String"
    SS "        value = StrFromFile(file)"
    SS "        Replace $CrLf With $Lf In value"
    SS "        Replace $CrLf With $Lf In value"
    SS "        Replace $Cr With $Lf In value"
    SS "        Replace $Cr With $Lf In value"
    SS "        Replace $Lf With $CrLf In value"
    SS "        Function = value"
    SS "    End Function"
    SS "    Sub WStrToFile(ByRef file As WString, ByRef value As WString)"
    SS "        'store string to File"
    SS "        Local f As Long"
    SS "        If Len(file) = 0 Then Exit Sub"
    SS "        f = FreeFile"
    SS "        Open file For Binary As f"
    SS "        SetEof f"
    SS "        Put$$ f, value"
    SS "        Close f"
    SS "    End Sub"
    SS "    Function WStrFromFile(ByRef file As WString) As WString"
    SS "        'get file contents as string"
    SS "        Local f As Long"
    SS "        Local value As WString"
    SS "        If IsFalse IsFile(file) Then Exit Function"
    SS "        f = FreeFile"
    SS "        Open file For Binary As f"
    SS "        Get$$ f, Lof(f), value"
    SS "        Function = value"
    SS "        Close f"
    SS "    End Function"
    SS "    Sub WStrToTextFile(ByRef file As WString, ByRef value As WString)"
    SS "        'store string converted to UTF8 to File"
    SS "        StrToFile file, ChrToUtf8$(value)"
    SS "    End Sub"
    SS "    Function WStrFromTextFile(ByRef file As WString) As WString"
    SS "        'get file contents converted from UTF8"
    SS "        Function = Utf8ToChr$(StrFromFile(file))"
    SS "    End Function"
    SS "    Function WStrFromTextFileFixed(ByRef file As WString) As WString"
    SS "        'get file contents converted from UTF8 fixing Unix line endings if any"
    SS "        Local value As WString"
    SS "        value = Utf8ToChr$(StrFromFile(file))"
    SS "        Replace $CrLf With $Lf In value"
    SS "        Replace $CrLf With $Lf In value"
    SS "        Replace $Cr With $Lf In value"
    SS "        Replace $Cr With $Lf In value"
    SS "        Replace $Lf With $CrLf In value"
    SS "        Function = value"
    SS "    End Function"
    SS "#EndIf '%FileUtilities231018"
End Sub

Sub AddMemoryCode()
    SS "'Public domain, use at own risk. SDurham "
    SS ""
    SS "#If Not %Def(%Memory231018)"
    SS tb + "%Memory231018 = 1"
    SS tb + "Declare Function GlobalAlloc Lib ""Kernel32.dll"" Alias ""GlobalAlloc"" (ByVal uFlags As Dword, ByVal dwBytes As Dword) As Dword"
    SS tb + "Declare Function GlobalReAlloc Lib ""Kernel32.dll"" Alias ""GlobalReAlloc"" (ByVal hMem As Dword, ByVal dwBytes As Dword, ByVal uFlags As Dword) As Dword"
    SS tb + "Declare Function GlobalFree Lib ""Kernel32.dll"" Alias ""GlobalFree"" (ByVal hMem As Dword) As Dword"
    SS tb + "%MEMFIXED = &H0000 : %MEMMOVEABLE = &H0002 : %MEMZEROINIT = &H0040 : %MEMGPTR = (%MEMZEROINIT Or %MEMFIXED)"
    SS tb + "Function MemAlloc(ByVal bytes As Long) As Long"
    SS tb + tb + "'allocate memory"
    SS tb + tb + "If bytes Then Function = GlobalAlloc(ByVal %MEMGPTR, ByVal bytes)"
    SS tb + "End Function"
    SS tb + "Function MemReAlloc(ByVal hMem As Long, ByVal bytes As Long) As Long"
    SS tb + tb + "'reallocate new size"
    SS tb + tb + "If hMem And bytes Then"
    SS tb + tb + tb + "Function = GlobalReAlloc(ByVal hMem, ByVal bytes, ByVal %MEMMOVEABLE Or %MEMZEROINIT)"
    SS tb + tb + "ElseIf bytes Then"
    SS tb + tb + tb + "Function = GlobalAlloc(ByVal %MEMGPTR, ByVal bytes)"
    SS tb + tb + "ElseIf hMem Then"
    SS tb + tb + tb + "Function = GlobalFree(ByVal hMem)"
    SS tb + tb + "End If"
    SS tb + "End Function"
    SS tb + "Function MemFree(ByVal hMem As Long) As Long"
    SS tb + tb + "'free memory"
    SS tb + tb + "If hMem Then GlobalFree(ByVal hMem)"
    SS tb + "End Function"
    SS "#EndIf '%Memory231018"
End Sub

Sub StrToFile(ByRef file As WString, ByRef value As String)
    Local f As Long
    If Len(file) = 0 Then Exit Sub
    f = FreeFile
    Open file For Binary As f
    SetEof f
    Put$ f, value
    Close f
End Sub�

Zlatko Vid

when i try to compile this one i get this error :
QuoteCompiler file not found/accessible
  Line 10: #INCLUDE ONCE "WIN32API.INC" 

Theo Gottwald

Check that the Include Path for your Powerbasic or Jose-Include Files is properly configured.

PS: This is for Powerbasic.While it shall also be an inspiration for all other systems here ...