Tutorial 02: StrLib - String Manipulation
Overview
This tutorial covers advanced string manipulation operations in FreshLib's StrLib. You'll learn how to insert, extract, transform, and trim strings using the comprehensive set of string manipulation functions.
Topics Covered
String Modification - Inserting characters and strings at specific positions
Substring Operations - Extracting parts of strings, splitting, trimming
Case Conversion - Converting between uppercase and lowercase
Whitespace Handling - Trimming spaces, handling duplicate spaces
Quote Handling - Adding and removing quotes
Memory Management - Setting capacity, fixing length
Prerequisites
Completion of Tutorial 01: StrLib Basics
Understanding of string handles vs pointers
Familiarity with carry flag error checking
Functions in This Tutorial
String Modification
| Function | Purpose |
StrInsert | Insert string at position |
StrCatMem | Append from memory buffer |
StrCharInsert | Insert up to 4 characters at position |
StrSetCapacity | Expand/collapse string capacity |
Substring Operations
| Function | Purpose |
StrExtract | Extract substring (returns new string) |
StrCopyPart | Copy part of string to destination |
StrSplit | Split string at position |
StrTrim | Trim string at position |
Case Conversion
| Function | Purpose |
StrLCase | Convert to lowercase |
StrUCase | Convert to uppercase |
Whitespace Handling
| Function | Purpose |
StrClipSpacesR | Trim trailing whitespace |
StrClipSpacesL | Trim leading whitespace |
StrCleanDupSpaces | Remove duplicate spaces |
StrClipQuotes | Remove surrounding quotes |
StrSetQuotes | Add surrounding quotes |
StrFixLen | Fix length for external strings |
Advanced
| Function | Purpose |
StrCompSort2 | Sort comparison (returns -1, 0, 1) |
SetString | Create/set string variable |
Demo Programs
Demo 05: String Modification
File: demo05_string_modify.asm
Demonstrates:
Inserting strings at specific positions with
StrInsertAppending from memory buffers with
StrCatMemInserting characters with
StrCharInsertExpanding string capacity with
StrSetCapacityKey Concepts:
Positions are 0-based (0 = start of string)
Insert at -1 to append to end
StrInsertshifts existing content to make roomStrSetCapacitypre-allocates memory for efficiency
Demo 06: Substring Operations
File: demo06_string_substring.asm
Demonstrates:
Extracting substrings with
StrExtractCopying parts of strings with
StrCopyPartSplitting strings at positions with
StrSplitTrimming strings at positions with
StrTrimKey Concepts:
StrExtractcreates a NEW string (must be freed)StrCopyPartcopies to existing destinationStrSplitcreates two new strings from onePositions are 0-based
Demo 07: Case Conversion
File: demo07_string_case.asm
Demonstrates:
Converting to lowercase with
StrLCaseConverting to uppercase with
StrUCaseLocale handling considerations
Key Concepts:
Case conversion modifies string in place
Works with ASCII and extended characters
Locale-dependent for some characters
Demo 08: String Trimming
File: demo08_string_trim.asm
Demonstrates:
Trailing whitespace removal with
StrClipSpacesRLeading whitespace removal with
StrClipSpacesLCleaning duplicate spaces with
StrCleanDupSpacesAdding/removing quotes with
StrSetQuotes/StrClipQuotesFixing length with
StrFixLenKey Concepts:
Whitespace includes spaces, tabs, newlines
Trimming modifies string in place
Quote functions handle both single and double quotes
StrFixLenfor strings managed by external code
Common Patterns
Inserting at Position
; Insert at specific position
stdcall StrInsert, hString, pos, hToInsert
jc .error_handler
; Insert at end (append)
stdcall StrInsert, hString, -1, hToInsert
jc .error_handler
Extracting Substring
; Extract creates NEW string - must free!
stdcall StrExtract, hSource, start, length
jc .error_handler
mov [hResult], eax
; ... use hResult ...
stdcall StrDel, [hResult] ; Don't forget!
Cleaning User Input
; Remove leading/trailing whitespace
stdcall StrClipSpacesL, hInput
stdcall StrClipSpacesR, hInput
; Clean duplicate spaces
stdcall StrCleanDupSpaces, hInput
Working with Quotes
; Add quotes
stdcall StrSetQuotes, hString, '"' ; Double quotes
; Remove quotes
stdcall StrClipQuotes, hString
Position Indexing
All position-based functions use 0-based indexing:
String: "Hello World"
Position: 0123456789...
StrInsert at pos=5: "Hello<insert>World"
StrExtract from=5, len=5: "World"
StrTrim at pos=5: "Hello"
Special position -1 means "end of string".
Memory Management
Functions That Create New Strings
These functions return a NEW string handle that must be freed:
StrExtract- Creates new substringStrSplit- Creates two new strings
Always pair with StrDel:
stdcall StrExtract, hSource, 0, 5
jc .error
mov [hResult], eax
; ... use hResult ...
stdcall StrDel, [hResult] ; Required!
Functions That Modify In Place
These modify the existing string (no new handle):
StrInsertStrCatMemStrCharInsertStrClipSpacesR/LStrCleanDupSpacesStrClipQuotesStrSetQuotesStrLCaseStrUCase
No need to free - the handle stays the same.
Important Discoveries During Implementation
1. StrInsert Argument Order is Counter-Intuitive
Problem: Initial implementation resulted in segfaults when calling StrInsert.
Discovery: The signature is StrInsert .dest, .source, .pos - the position comes LAST, not second.
Common Mistake:
stdcall StrInsert, [hBase], 6, [hInsert] ; WRONG!
Correct:
stdcall StrInsert, [hBase], [hInsert], 6 ; Position is last
Impact: Wrong argument order causes the position value to be interpreted as a string handle, leading to immediate segmentation faults.
2. StrCharInsert Only Accepts One Character
Problem: Documentation initially suggested it could insert multiple characters.
Discovery: StrCharInsert has signature .hString, .char, .pos - it only accepts a SINGLE character per call.
What Doesn't Work:
stdcall StrCharInsert, [hBase], '*', '*', '*', 6 ; WRONG!
Correct Usage:
stdcall StrCharInsert, [hBase], '*', 6 ; Inserts one asterisk
Workaround: To insert multiple characters, call the function multiple times or use StrInsert with a string.
3. StrSplit Returns One String, Modifies Another
Problem: Initial implementation treated StrSplit as returning an array of handles, causing memory access violations.
Discovery: StrSplit has unique behavior:
Modifies the source string in place to contain the LEFT part
Returns a NEW string handle in EAX containing the RIGHT part
Wrong Assumption:
stdcall StrSplit, [hSource], 15 mov [hArray], eax mov eax, [hArray] mov eax, [eax] ; WRONG! Not an array!Correct Usage:
stdcall StrSplit, [hSource], 15 mov [hRightPart], eax ; EAX = right part (NEW string) ; [hSource] now contains left part (modified in place) ; Display both parts stdcall StrPtr, [hSource], eax ; Left part stdcall StrPtr, [hRightPart], eax ; Right part ; Clean up stdcall StrDel, [hSource] ; Delete left part stdcall StrDel, [hRightPart] ; Delete right partImpact: Understanding this pattern is crucial for correct memory management.
4. StrCatMem Length Must Be Exact
Problem: Using $ - label for length calculation inside iglobal section caused FASM errors.
Discovery: The length calculation $ - cRawBytes only works during preprocessing. In the constants section, you must use the actual byte count.
Wrong:
iglobal
cRawBytes text " Beautiful"
cRawLen = $ - cRawBytes ; Illegal instruction error!
endg
Correct:
iglobal
cRawBytes text " Beautiful"
cRawLen = 10 ; Count the bytes: space + "Beautiful"
endg
Impact: Incorrect length causes either truncated output or buffer overruns.
5. @AllImportEmbeded is Not Supported in This Build
Problem: Initial demo files included @AllImportEmbeded and @AllDataEmbeded macros at the end, causing "illegal instruction" errors.
Discovery: These macros are not available in the console compact binary type configuration used for these tutorials.
Fix: Simply remove these lines from all demo files. The FreshLib framework handles imports automatically for console applications.
Impact: Without removing these macros, demos fail to build with cryptic "illegal instruction" errors.
6. Position -1 is Special
Discovery: Most position-based functions treat -1 as a special value meaning "end of string" or "append".
Example:
stdcall StrInsert, [hString], [hToInsert], -1 ; Appends to end
Benefit: Provides a convenient way to append without calculating string length first.
Building and Running
cd 02-strlib-manipulation
./build.sh
This will compile and test all 4 demos.
Next Steps
After completing this tutorial, continue to:
Tutorial 03: Advanced Features (numbers, encoding, patterns, hash)
Reference
FreshLib Source:
~/Documents/fossil/FreshIDE/freshlib/data/strlib.asmAsmBB Usage:
~/Documents/fossil/asmbb/source/*.asm