StrListLib — String List Library

Dynamic string collections based on Delphi’s TStringList. File I/O, key-value pairs, sorting, CSV parsing, event callbacks, and batch updates. 55 functions.

CategoryCountDescription
Creation/Destruction2strings#, strings_free
Text Content6text, commatext, delimitedtext (get/set)
Item Access5strings/strings$, count, capacity (get/set)
Delimiters & Formatting10delimiter, quotechar, strictdelimiter, linebreak, trailinglinebreak
Key-Value Pairs8values, names$, keynames$, valuefromindex, namevalueseparator
Sorting & Duplicates6sorted, duplicates, casesensitive
Encoding5defaultencoding, encoding$, writebom
Add/Remove5add, append, insert, delete, clear
Searching3indexof, find (binary), indexofname
Manipulation4exchange, move, sort, equals
Batch Updates2beginupdate, endupdate
File I/O4load, save, loadfromfile, savetofile
Stream I/O2loadfromstream, savetostream
Events4onchange, onchanging (get/set)

Creation & Destruction

FunctionSignatureDescription
strings#()strings#@Create a new string list (returns pointer)
strings_free(sl#)strings_free@#Free a string list
╯ plan9basic
sl# = strings#()
strings_add(sl#, "Apple")
strings_add(sl#, "Banana")
println "Count: "; strings_count(sl#)
strings_free(sl#)

Text Content Properties

FunctionSignatureDescription
strings_text(sl#, s$)strings_text@#$Set entire text content (CRLF-separated lines)
strings_text$(sl#)strings_text$@#Get entire text content
strings_commatext(sl#, s$)strings_commatext@#$Set comma-separated text
strings_commatext$(sl#)strings_commatext$@#Get comma-separated text
strings_delimitedtext(sl#, s$)strings_delimitedtext@#$Set delimited text (uses current delimiter/quotechar)
strings_delimitedtext$(sl#)strings_delimitedtext$@#Get delimited text

Item Access

FunctionSignatureDescription
strings_strings(sl#, idx, s$)strings_strings@#n$Set string at index (0-based)
strings_strings$(sl#, idx)strings_strings$@#nGet string at index (0-based)
strings_count(sl#)strings_count@#Number of items
strings_capacity(sl#, n)strings_capacity@#nSet capacity (pre-allocate)
strings_capacity(sl#)strings_capacity@#Get current capacity
╯ plan9basic
sl# = strings#()
strings_add(sl#, "First")
strings_add(sl#, "Second")
strings_add(sl#, "Third")

println "Count: "; strings_count(sl#)
println "Item 0: "; strings_strings$(sl#, 0)
println "Item 2: "; strings_strings$(sl#, 2)

' Modify item
strings_strings(sl#, 1, "Modified")
println "Item 1: "; strings_strings$(sl#, 1)
strings_free(sl#)
ⓘ Note: Indices are 0-based. Accessing an out-of-bounds index raises an error.

Delimiters & Formatting

FunctionSignatureDescription
strings_delimiter(sl#, c$)strings_delimiter@#$Set delimiter character
strings_delimiter$(sl#)strings_delimiter$@#Get delimiter character
strings_quotechar(sl#, c$)strings_quotechar@#$Set quote character
strings_quotechar$(sl#)strings_quotechar$@#Get quote character
strings_strictdelimiter(sl#, n)strings_strictdelimiter@#nSet strict delimiter mode (0/1)
strings_strictdelimiter(sl#)strings_strictdelimiter@#Get strict delimiter mode
strings_linebreak(sl#, s$)strings_linebreak@#$Set line break string
strings_linebreak$(sl#)strings_linebreak$@#Get line break string
strings_trailinglinebreak(sl#, n)strings_trailinglinebreak@#nSet trailing linebreak (0/1)
strings_trailinglinebreak(sl#)strings_trailinglinebreak@#Get trailing linebreak

CSV Parsing

╯ csv_parse.bas
sl# = strings#()

' Configure for CSV
strings_delimiter(sl#, ",")
strings_strictdelimiter(sl#, 1)
strings_quotechar(sl#, "\"")

' Parse a CSV line
strings_delimitedtext(sl#, "John,Doe,30,\"New York, NY\"")

println "First: "; strings_strings$(sl#, 0)
println "Last:  "; strings_strings$(sl#, 1)
println "Age:   "; strings_strings$(sl#, 2)
println "City:  "; strings_strings$(sl#, 3)
strings_free(sl#)

Key-Value Pairs

INI-style Name=Value support. Each string in the list can be a key-value pair separated by = (configurable).

FunctionSignatureDescription
strings_values(sl#, key$, val$)strings_values@#$$Set value by key name
strings_values$(sl#, key$)strings_values$@#$Get value by key name
strings_names$(sl#, idx)strings_names$@#nGet name part at index
strings_keynames$(sl#, idx)strings_keynames$@#nGet key name at index
strings_valuefromindex(sl#, idx, s$)strings_valuefromindex@#n$Set value at index
strings_valuefromindex$(sl#, idx)strings_valuefromindex$@#nGet value at index
strings_namevalueseparator(sl#, c$)strings_namevalueseparator@#$Set separator (default "=")
strings_namevalueseparator$(sl#)strings_namevalueseparator$@#Get separator
╯ plan9basic
sl# = strings#()
strings_add(sl#, "name=John Doe")
strings_add(sl#, "age=30")
strings_add(sl#, "city=New York")

println "Name: "; strings_values$(sl#, "name")
println "Age:  "; strings_values$(sl#, "age")

' Update value
strings_values(sl#, "age", "31")

' Find by key
idx = strings_indexofname(sl#, "city")
if idx >= 0 then
    println "City: "; strings_valuefromindex$(sl#, idx)
endif
strings_free(sl#)

Sorting & Duplicates

FunctionSignatureDescription
strings_sorted(sl#, n)strings_sorted@#nEnable/disable sorting (0/1)
strings_sorted(sl#)strings_sorted@#Get sorted mode
strings_duplicates(sl#, mode$)strings_duplicates@#$Set mode: "ignore", "accept", "error"
strings_duplicates$(sl#)strings_duplicates$@#Get duplicate mode
strings_casesensitive(sl#, n)strings_casesensitive@#nSet case sensitivity (0/1)
strings_casesensitive(sl#)strings_casesensitive@#Get case sensitivity
╯ sorted_list.bas
sl# = strings#()
strings_sorted(sl#, 1)
strings_duplicates(sl#, "ignore")

strings_add(sl#, "Banana")
strings_add(sl#, "Apple")
strings_add(sl#, "Cherry")
strings_add(sl#, "Apple")  ' Ignored (duplicate)

' Binary search (fast on sorted lists)
idx = strings_find(sl#, "Cherry")
println "Cherry at: "; idx

for i = 0 to strings_count(sl#) - 1
    println strings_strings$(sl#, i)
next
strings_free(sl#)
ⓘ Note: strings_find() uses binary search and only works on sorted lists. For unsorted lists, use strings_indexof().

Encoding

FunctionSignatureDescription
strings_defaultencoding(sl#, enc$)strings_defaultencoding@#$Set default encoding
strings_defaultencoding$(sl#)strings_defaultencoding$@#Get default encoding
strings_encoding$(sl#)strings_encoding$@#Get current encoding (read-only)
strings_writebom(sl#, n)strings_writebom@#nSet write BOM flag (0/1)
strings_writebom(sl#)strings_writebom@#Get write BOM flag
EncodingDescription
utf-8Default, recommended
utf-7Legacy
utf-16 / utf-16leUTF-16 Little Endian
utf-16beUTF-16 Big Endian
ansiSystem default ANSI
ascii7-bit ASCII

Adding & Removing

FunctionSignatureDescription
strings_add(sl#, s$)strings_add@#$Add string to end (returns index)
strings_append(sl#, s$)strings_append@#$Append string (returns new count)
strings_insert(sl#, idx, s$)strings_insert@#n$Insert at index (returns new count)
strings_delete(sl#, idx)strings_delete@#nDelete at index (returns new count)
strings_clear(sl#)strings_clear@#Remove all items

Searching

FunctionSignatureDescription
strings_indexof(sl#, s$)strings_indexof@#$Find string (returns index or -1)
strings_find(sl#, s$)strings_find@#$Binary search — sorted lists only (returns index or -1)
strings_indexofname(sl#, name$)strings_indexofname@#$Find by key name (returns index or -1)

Manipulation

FunctionSignatureDescription
strings_exchange(sl#, i1, i2)strings_exchange@#nnSwap two items
strings_move(sl#, cur, new)strings_move@#nnMove item to new position
strings_sort(sl#)strings_sort@#Sort the list
strings_equals(sl1#, sl2#)strings_equals@##Compare two lists (1/0)

Batch Updates

FunctionSignatureDescription
strings_beginupdate(sl#)strings_beginupdate@#Begin batch (suppress events)
strings_endupdate(sl#)strings_endupdate@#End batch (fire single event)
╯ plan9basic
sl# = strings#()
strings_onchange(sl#, "on_change")

' Without batch: fires event for each add
strings_add(sl#, "Item 1")  ' Event fires
strings_add(sl#, "Item 2")  ' Event fires

' With batch: single event at the end
strings_beginupdate(sl#)
for i = 1 to 1000
    strings_add(sl#, "Item " + str$(i))
next
strings_endupdate(sl#)  ' Single event
strings_free(sl#)
ⓘ Note: Use beginupdate/endupdate when adding many items at once to avoid firing events per add and improve performance.

File I/O

FunctionSignatureDescription
strings_load(sl#, file$)strings_load@#$Load file (UTF-8 default, returns line count)
strings_save(sl#, file$)strings_save@#$Save file (UTF-8 default, returns line count)
strings_loadfromfile(sl#, file$, enc$)strings_loadfromfile@#$$Load with encoding
strings_savetofile(sl#, file$, enc$)strings_savetofile@#$$Save with encoding
╯ plan9basic
sl# = strings#()
strings_load(sl#, "data.txt")

for i = 0 to strings_count(sl#) - 1
    println strings_strings$(sl#, i)
next

strings_save(sl#, "output.txt")

' With explicit encoding
strings_loadfromfile(sl#, "legacy.txt", "ansi")
strings_savetofile(sl#, "unicode.txt", "utf-16")
strings_free(sl#)

Stream I/O

FunctionSignatureDescription
strings_loadfromstream(sl#, stream#, enc$)strings_loadfromstream@##$Load from stream (returns line count)
strings_savetostream(sl#, stream#, enc$)strings_savetostream@##$Save to stream (returns line count)

Events

FunctionSignatureDescription
strings_onchange(sl#, func$)strings_onchange@#$Set OnChange handler ("" to remove)
strings_onchange$(sl#)strings_onchange$@#Get OnChange handler name
strings_onchanging(sl#, func$)strings_onchanging@#$Set OnChanging handler
strings_onchanging$(sl#)strings_onchanging$@#Get OnChanging handler name
╯ events.bas
function on_list_change#(sender#)
    println "Changed! Count: "; strings_count(sender#)
    return sender#
endfunction

function on_list_changing#(sender#)
    println "About to change..."
    return sender#
endfunction

sl# = strings#()
strings_onchange(sl#, "on_list_change")
strings_onchanging(sl#, "on_list_changing")

strings_add(sl#, "First")   ' Fires: changing, then changed
strings_add(sl#, "Second")  ' Fires: changing, then changed

' Remove handler
strings_onchange(sl#, "")
strings_free(sl#)
ⓘ Note: Event handler signature: function handler#(sender#) — receives the string list as parameter, must return a pointer.

Complete Examples

Configuration File Handler

╯ config_handler.bas
function config_load#(filename$) local cfg#
    cfg# = strings#()
    strings_namevalueseparator(cfg#, "=")
    strings_load(cfg#, filename$)
    return cfg#
endfunction

function config_get$(cfg#, key$, default$) local value$
    value$ = strings_values$(cfg#, key$)
    if value$ = "" then
        return default$
    endif
    return value$
endfunction

function config_set#(cfg#, key$, value$)
    strings_values(cfg#, key$, value$)
    return cfg#
endfunction

' Usage
cfg# = config_load#("settings.ini")
theme$ = config_get$(cfg#, "theme", "dark")
config_set#(cfg#, "last_run", date$())
strings_save(cfg#, "settings.ini")
strings_free(cfg#)

CSV Parser

╯ csv_parser.bas
function parse_csv#(line$) local fields#
    fields# = strings#()
    strings_delimiter(fields#, ",")
    strings_strictdelimiter(fields#, 1)
    strings_quotechar(fields#, "\"")
    strings_delimitedtext(fields#, line$)
    return fields#
endfunction

function csv_get$(fields#, index)
    if index < 0 or index >= strings_count(fields#) then
        return ""
    endif
    return strings_strings$(fields#, index)
endfunction

' Usage
row# = parse_csv#("John,Doe,30,\"San Francisco, CA\"")
println "Name: "; csv_get$(row#, 0); " "; csv_get$(row#, 1)
println "Age:  "; csv_get$(row#, 2)
println "City: "; csv_get$(row#, 3)
strings_free(row#)

Unique Sorted Collection

╯ unique_sorted.bas
function unique_collection#() local coll#
    coll# = strings#()
    strings_sorted(coll#, 1)
    strings_duplicates(coll#, "ignore")
    return coll#
endfunction

function collection_contains(coll#, item$)
    if strings_find(coll#, item$) >= 0 then
        return 1
    else
        return 0
    end if
end function

tags# = unique_collection#()
strings_add(tags#, "programming")
strings_add(tags#, "basic")
strings_add(tags#, "programming")  ' Ignored
strings_add(tags#, "delphi")

if collection_contains(tags#, "basic") = 1 then
    println "Has 'basic' tag"
endif

for i = 0 to strings_count(tags#) - 1
    println strings_strings$(tags#, i)
next
strings_free(tags#)

StrListLib vs StrLib

FeatureStrLibStrListLib
PurposeString manipulationString collections
Data typeSingle stringList of strings
File I/ONoYes
SortingNoYes
EventsNoYes
Key-ValueNoYes
CSV parsingNoYes

Error Handling

ErrorDescription
Undefined or nil string listPointer is nil
Index out of bounds: N (count: M)Index N invalid for M items
Empty string provided where character expectedDelimiter/quote char is empty
Invalid callback function name: XFunction name not a valid identifier

Quick Reference

Creation & Content (13)

FunctionSignatureDescription
strings#()strings#@Create list
strings_free(sl#)strings_free@#Free list
strings_text/text$@#$ / @#Set/get full text
strings_commatext/commatext$@#$ / @#Set/get comma-separated
strings_delimitedtext/delimitedtext$@#$ / @#Set/get delimited
strings_strings/strings$@#n$ / @#nSet/get by index
strings_count(sl#)strings_count@#Item count

Properties (21)

FunctionSignatureDescription
strings_delimiter/$ | quotechar/$variousDelimiter config
strings_strictdelimiter | linebreak/$ | trailinglinebreakvariousFormatting
strings_values/$ | names$ | keynames$ | valuefromindex/$variousKey-value (8)
strings_sorted | duplicates/$ | casesensitivevariousSorting (6)
strings_defaultencoding/$ | encoding$ | writebomvariousEncoding (5)

Methods (20)

FunctionSignatureDescription
strings_add/append/insert/delete/clearvariousAdd/remove (5)
strings_indexof/find/indexofnamevariousSearch (3)
strings_exchange/move/sort/equalsvariousManipulation (4)
strings_beginupdate/endupdatevariousBatch (2)
strings_load/save/loadfromfile/savetofilevariousFile I/O (4)
strings_loadfromstream/savetostreamvariousStream I/O (2)

Events (4)

FunctionSignatureDescription
strings_onchange/onchange$@#$ / @#OnChange handler
strings_onchanging/onchanging$@#$ / @#OnChanging handler

55 functions across 14 categories.