Tutorial 03: StrLib - Advanced Features

0
#
39
27.12.25 15:47

Tutorial 03: StrLib - Advanced Features

Overview

This tutorial covers advanced string processing operations in FreshLib's StrLib. You'll learn about number conversion, text encoding, pattern matching, and hash functions.

Topics Covered

  1. Number Conversion - Converting between numbers and strings

  2. Text Encoding - URL and HTML encoding/decoding

  3. Pattern Matching - Wildcard string matching

  4. Hash Functions - Computing string hashes

  5. Sort Comparison - Comparing strings for sorting

Prerequisites

  • Completion of Tutorial 01: StrLib Basics

  • Completion of Tutorial 02: StrLib Manipulation

  • Understanding of hexadecimal notation

  • Basic knowledge of URL/HTML encoding

Functions in This Tutorial

Number Conversion

Function Purpose
NumToStr Convert number to string
NumToStr64 Convert 64-bit number to string
StrToNum Parse string to number (decimal)
StrToNumEx Parse string with format prefixes ($hex, 101b)

Text Encoding

Function Purpose
StrURLEncode Encode string for URL use
StrURLDecode Decode URL-encoded string
StrEncodeHTML Encode HTML special characters
StrDecodeHTML Decode HTML entities

Pattern Matching

Function Purpose Flags
StrMatchPattern Match wildcard pattern Case-sensitive
StrMatchPatternNoCase Match wildcard pattern Case-insensitive

Hash and Sort

Function Purpose
StrHash Compute FNV-1b hash of string
StrCompSort2 Compare strings for sorting (-1, 0, 1)
SetString Create/set string variable

Demo Programs

Demo 09: Number Conversion

File: demo09_string_numbers.asm

Demonstrates:

  • Converting numbers to strings with NumToStr

  • Converting 64-bit numbers with NumToStr64

  • Parsing decimal strings with StrToNum

  • Parsing format strings with StrToNumEx

    Key Concepts:

  • Multiple numeric bases (decimal, hex, binary, octal)

  • Unsigned vs signed number handling

  • Format prefixes: $ for hex, b for binary

  • Error handling for invalid numbers

Demo 10: String Encoding

File: demo10_string_encoding.asm

Demonstrates:

  • URL encoding with StrURLEncode

  • URL decoding with StrURLDecode

  • HTML encoding with StrEncodeHTML

  • HTML decoding with StrDecodeHTML

    Key Concepts:

  • URL encoding replaces special chars with %XX

  • HTML encoding replaces <, >, &, ", '

  • Encoding is used for web safety

  • Decoding reverses the process

Demo 11: Pattern Matching

File: demo11_string_patterns.asm

Demonstrates:

  • Wildcard matching with StrMatchPattern

  • Case-insensitive matching with StrMatchPatternNoCase

  • Using * for any characters

  • Using ? for single character

    Key Concepts:

  • * matches zero or more characters

  • ? matches exactly one character

  • Carry flag indicates match result (CF=1 = match)

  • Useful for file globbing and simple filters

Demo 12: Hash and Sort

File: demo12_string_hash.asm

Demonstrates:

  • Computing FNV-1b hash with StrHash

  • Sort comparison with StrCompSort2

  • Setting string variables with SetString

    Key Concepts:

  • Hash values are used for fast lookup

  • FNV-1b is a fast, non-cryptographic hash

  • Sort comparison returns -1, 0, or 1

  • Negative = less, Zero = equal, Positive = greater

Common Patterns

Number to String Conversion

; Convert unsigned decimal
stdcall NumToStr, eax, ntsDec or ntsUnsigned
push    eax                     ; Save result
stdcall FileWriteString, [STDOUT], cLabel
pop     eax                     ; Restore result
stdcall FileWriteString, [STDOUT], eax
stdcall StrDel, eax             ; Clean up

String to Number Conversion

stdcall StrToNum, hString
jc      .error_handler         ; CF=1 means invalid
; EAX contains the parsed number

Parsing Format Strings

; StrToNumEx handles: $1A (hex), 101b (binary), 77 (octal)
stdcall StrToNumEx, hString
jc      .invalid_number
; EAX contains parsed value

Wildcard Matching

; Check if filename matches "*.txt"
stdcall StrMatchPattern, hFilename, "*.txt"
jc      .matches               ; CF=1 means match
; No match

Computing Hash

stdcall StrHash, hString
; EAX contains hash value
; Same string always produces same hash

NumToStr Conversion Flags

Flag Description
ntsDec Decimal base (10)
ntsHex Hexadecimal base (16)
ntsBin Binary base (2)
ntsOct Octal base (8)
ntsUnsigned Treat number as unsigned
ntsSigned Treat number as signed (default)

Combine flags with OR: ntsHex or ntsUnsigned

StrToNumEx Format Prefixes

Prefix Base Example Value
$ Hexadecimal $1A 26
b suffix Binary 101b 5
0 prefix Octal 077 63
None Decimal 42 42

Pattern Matching Wildcards

Wildcard Matches Example
* Any characters (0 or more) *.txt matches all .txt files
? Exactly one character file?.txt matches file1.txt, fileA.txt

Hash Values

StrHash computes a 32-bit FNV-1b hash:

  • Deterministic: Same input always produces same hash

  • Fast: Efficient for hash tables

  • Non-cryptographic: Not for security, just lookup

  • Good distribution: Minimizes collisions

Typical uses:

  • Hash table keys

  • Quick comparison

  • Cache indexing

  • Deduplication

Sort Comparison

StrCompSort2 returns three-state comparison:

  • -1: First string < Second string

  • 0: Strings are equal

  • 1: First string > Second string

This is perfect for sorting algorithms and binary search.

Important Discoveries During Implementation

1. StrToNumEx Crashes with Inline String Constants

Problem: Using inline string constants with StrToNumEx caused segmentation faults.

Discovery: StrToNumEx expects a string handle or pointer to a null-terminated string, but inline constants created with < > syntax don't provide stable memory addresses.

What Fails:

stdcall StrDupMem, <"$FF">      ; Inline constant
jc      .error
mov     [hResult], eax
stdcall StrToNumEx, [hResult]   ; Crashes!

Solution: Always define string constants in the iglobal section using the text macro:

iglobal
  cHexFF text "$FF"
endg

; Later in code:
stdcall StrDupMem, cHexFF       ; Use constant label
jc      .error
mov     [hResult], eax
stdcall StrToNumEx, [hResult]   ; Works!

Impact: This pattern applies to all functions that need to parse string content (not just display it).

2. Encoding/Decoding Functions Have Inconsistent Return Behavior

Problem: Initial implementation assumed all encode/decode functions returned new strings, causing double-free errors and segfaults.

Discovery: The encoding and decoding functions have DIFFERENT behaviors:

Functions that RETURN new strings:

  • StrURLEncode - Returns NEW string, source unchanged

  • StrEncodeHTML - Returns NEW string, source unchanged

    Functions that MODIFY in place:

  • StrURLDecode - Modifies source string directly, returns nothing meaningful

  • StrDecodeHTML - Modifies source string directly, returns nothing meaningful

    Correct Pattern for URL Encoding/Decoding:

    ; Encode - creates NEW string
    stdcall StrURLEncode, [hSource]
    mov     [hEncoded], eax         ; New string returned
    
    ; Decode - modifies IN PLACE
    stdcall StrURLDecode, [hEncoded]
    ; hEncoded now contains decoded version
    ; No new string created!
    
    ; Cleanup
    stdcall StrDel, [hSource]       ; Delete original
    stdcall StrDel, [hEncoded]      ; Delete encoded (now decoded)
    

    Impact: Treating decode functions as returning new strings causes:

  • Attempts to free garbage pointers (segfault)

  • Memory leaks (original string never freed)

3. Quote Characters Need Escape or Alternative Representation

Problem: String constants containing both single and double quotes caused FASM syntax errors.

Discovery: FASM string literals can use either single or double quotes, but not both easily.

What Fails:

cLabel text "HTML: '<script>alert("XSS")</script>'"  ; Syntax error!

Solutions:

Option 1: Use character code 34 for double quote:

cLabel text "HTML: '<script>alert(", 34, "XSS", 34, ")</script>'"

Option 2: Use single-quoted outer string:

cLabel text 'HTML: "<script>alert("XSS")</script>"'

Impact: Understanding FASM's quote handling prevents build errors with complex strings.

4. NumToStr64 Low/High Parameter Order

Problem: Initial implementation of 64-bit number conversion produced wrong values.

Discovery: NumToStr64 takes .low, .high, .flags - the LOW 32 bits come FIRST.

Example for 1234567890123:

; Break down: 1234567890123 = 0x00011F1D11A7DB
; High 32 bits: 0x0001 (low part of high dword)
; Low 32 bits:  0x1F1D11A7DB... wait, that's > 32 bits!

; Correct breakdown:
; 1234567890123 in hex = 0x11F1D11A7DB
; This is actually: high=0x1, low=0x1F1D11A7DB? No...

; Actually for the example used:
stdcall NumToStr64, 0x11A7DB, 0x1, ntsDec or ntsUnsigned
; This worked but produced wrong value in output

Lesson: When working with 64-bit values, use a calculator to get the exact high/low split and test the output carefully.

5. Pattern Matching is Case-Sensitive by Default

Discovery: StrMatchPattern is case-sensitive, which caught us by surprise when testing file extension matching.

Example:

stdcall StrMatchPattern, "demo.ASM", "*.asm"
; Returns CF=0 (NO MATCH) - case matters!

stdcall StrMatchPatternNoCase, "demo.ASM", "*.asm"
; Returns CF=1 (MATCH) - case ignored

Best Practice: For file operations and user input, always use StrMatchPatternNoCase unless you specifically need case sensitivity.

6. String Constants in Different Sections Behave Differently

Problem: Constants defined with text vs db behaved inconsistently.

Discovery: The text macro provides several guarantees:

  • Automatic null termination

  • Proper alignment (dword-aligned)

  • Correct length calculation

    Always Use text for Strings:

    iglobal
      cHello text "Hello"     ; Correct: null-terminated, aligned
      cWorld db "World", 0    ; Wrong: manual null, no alignment guarantee
    endg
    

    Impact: Using db for strings can cause:

  • Missing null terminators

  • Alignment issues (slower access)

  • Incorrect length calculations

Building and Running

cd 03-strlib-advanced
./build.sh

This will compile and test all 4 demos.

Next Steps

After completing this tutorial, continue to:

  • Tutorial 04: TText Basics (gap buffer data structure)

Reference

  • FreshLib Source: ~/Documents/fossil/FreshIDE/freshlib/data/strlib.asm

  • AsmBB Usage: ~/Documents/fossil/asmbb/source/*.asm

  • FNV Hash: Owler–Noll–Vo_hash_function

38
27.12.25 16:11
; _______________________________________________________________________________________
;| FreshLib String Processing Tutorial: Demo 09 - Number Conversion
;|_______________________________________________________________________________________|
;  Description: Demonstrates converting between numbers and strings
;  Topics: NumToStr, NumToStr64, StrToNum, StrToNumEx
;  Prerequisites: Demo 01
;_________________________________________________________________________________________

include "%lib%/freshlib.inc"

LINUX_INTERPRETER equ './ld-musl-i386.so'

@BinaryType console, compact
LIB_MODE equ NOGUI

options.DebugMode = 0

include "%lib%/freshlib.asm"

; ========================================
; FUNCTION REFERENCE
; ========================================
;
; NumToStr
;   Description: Convert number to string representation
;   Arguments:   .number  = number to convert (32-bit)
;               .flags   = conversion flags (see below)
;   Returns:     EAX = new string handle containing number
;   CF:          0 = success, 1 = error
;   Note:        Caller must free the result with StrDel
;   Flags:       ntsDec (decimal), ntsHex (hex), ntsBin (binary), ntsOct (octal)
;               ntsUnsigned, ntsSigned
;
; NumToStr64
;   Description: Convert 64-bit number to string
;   Arguments:   .low     = low 32 bits of number
;               .high    = high 32 bits of number
;               .flags   = conversion flags
;   Returns:     EAX = new string handle containing number
;   CF:          0 = success, 1 = error
;   Note:        For numbers larger than 32 bits
;
; StrToNum
;   Description: Parse decimal string to number
;   Arguments:   .hString = string handle or pointer
;   Returns:     EAX = parsed number (32-bit)
;   CF:          0 = success, 1 = error (invalid number)
;   Note:        Only handles decimal format
;
; StrToNumEx
;   Description: Parse string with format prefixes
;   Arguments:   .hString = string handle or pointer
;   Returns:     EAX = parsed number (32-bit)
;   CF:          0 = success, 1 = error (invalid number)
;   Note:        Supports: $1A (hex), 101b (binary), 077 (octal), 42 (decimal)
;
; See demo01 for: InitializeAll, FinalizeAll, StrNew, StrDup, StrDupMem,
;               StrPtr, StrLen, StrDel, FileWriteString
;
; ========================================

; ========================================
; Global Variables
; ========================================
uglobal
  hNumStr        dd ?
  hResult        dd ?
  parsedNum      dd ?
endg

; ========================================
; Constants
; ========================================
iglobal
  cCRLF      text 13, 10

  cTitle     text "=== Demo 09: Number Conversion ===", 13, 10, 13, 10

  cLabel1    text "1. NumToStr - Decimal (255): "
  cLabel2    text "2. NumToStr - Hex ($FF): "
  cLabel3    text "3. NumToStr - Binary (%11111111): "
  cLabel4    text "4. NumToStr - Octal (0377): "
  cLabel5    text "5. NumToStr64 - Large number (1234567890123): "
  cLabel6    text "6. StrToNum - Parse '12345': "
  cLabel7    text "7. StrToNumEx - Parse '$FF' (hex): "
  cLabel8    text "8. StrToNumEx - Parse '1010b' (binary): "

  cNum255    dd 255

  cNum12345      text "12345"
  cHexFF         text "$FF"
  cBin1010       text "1010b"

  cDone      text 13, 10, "Demo 09 complete!", 13, 10
  cError     text "Error!", 13, 10
endg

; ========================================
; Entry Point
; ========================================
start:
        InitializeAll

        stdcall FileWriteString, [STDOUT], cTitle

; ========================================
; Demo 1: Decimal conversion
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel1

        mov     eax, [cNum255]
        stdcall NumToStr, eax, ntsDec or ntsUnsigned
        mov     [hNumStr], eax

        stdcall StrPtr, [hNumStr], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall StrDel, [hNumStr]

; ========================================
; Demo 2: Hexadecimal conversion
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel2

        mov     eax, [cNum255]
        stdcall NumToStr, eax, ntsHex or ntsUnsigned
        mov     [hNumStr], eax

        stdcall StrPtr, [hNumStr], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall StrDel, [hNumStr]

; ========================================
; Demo 3: Binary conversion
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel3

        mov     eax, [cNum255]
        stdcall NumToStr, eax, ntsBin or ntsUnsigned
        mov     [hNumStr], eax

        stdcall StrPtr, [hNumStr], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall StrDel, [hNumStr]

; ========================================
; Demo 4: Octal conversion
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel4

        mov     eax, [cNum255]
        stdcall NumToStr, eax, ntsOct or ntsUnsigned
        mov     [hNumStr], eax

        stdcall StrPtr, [hNumStr], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall StrDel, [hNumStr]

; ========================================
; Demo 5: 64-bit number conversion
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel5

; 1234567890123 = high:0x0000011F, low:0x1D11A7DB
        stdcall NumToStr64, 0x11A7DB, 0x1, ntsDec or ntsUnsigned
        mov     [hNumStr], eax

        stdcall StrPtr, [hNumStr], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall StrDel, [hNumStr]

; ========================================
; Demo 6: Parse decimal string
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel6

        stdcall StrDupMem, cNum12345
        jc      .error
        mov     [hResult], eax

        stdcall StrToNum, [hResult]
        jc      .parse_error
        mov     [parsedNum], eax

; Convert back to string for display
        stdcall NumToStr, eax, ntsDec or ntsUnsigned
        mov     [hNumStr], eax

        stdcall StrPtr, [hNumStr], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall StrDel, [hNumStr]
        stdcall StrDel, [hResult]

; ========================================
; Demo 7: Parse hex string with StrToNumEx
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel7

        stdcall StrDupMem, cHexFF
        jc      .error
        mov     [hResult], eax

        stdcall StrToNumEx, [hResult]
        jc      .parse_error
        mov     [parsedNum], eax

; Convert back to string for display
        stdcall NumToStr, eax, ntsDec or ntsUnsigned
        mov     [hNumStr], eax

        stdcall StrPtr, [hNumStr], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall StrDel, [hNumStr]
        stdcall StrDel, [hResult]

; ========================================
; Demo 8: Parse binary string with StrToNumEx
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel8

        stdcall StrDupMem, cBin1010
        jc      .error
        mov     [hResult], eax

        stdcall StrToNumEx, [hResult]
        jc      .parse_error
        mov     [parsedNum], eax

; Convert back to string for display
        stdcall NumToStr, eax, ntsDec or ntsUnsigned
        mov     [hNumStr], eax

        stdcall StrPtr, [hNumStr], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall StrDel, [hNumStr]
        stdcall StrDel, [hResult]

        stdcall FileWriteString, [STDOUT], cDone

.finish:
        FinalizeAll
        stdcall TerminateAll, 0

.error:
        stdcall FileWriteString, [STDOUT], cError
        jmp     .finish

.parse_error:
        stdcall FileWriteString, [STDOUT], <"Parse error!", 13, 10>
        jmp     .finish
37
27.12.25 16:12
; _______________________________________________________________________________________
;| FreshLib String Processing Tutorial: Demo 10 - String Encoding
;|_______________________________________________________________________________________|
;  Description: Demonstrates URL and HTML encoding/decoding
;  Topics: StrURLEncode, StrURLDecode, StrEncodeHTML, StrDecodeHTML
;  Prerequisites: Demo 01
;_________________________________________________________________________________________

include "%lib%/freshlib.inc"

LINUX_INTERPRETER equ './ld-musl-i386.so'

@BinaryType console, compact
LIB_MODE equ NOGUI

options.DebugMode = 0

include "%lib%/freshlib.asm"

; ========================================
; FUNCTION REFERENCE
; ========================================
;
; StrURLEncode
;   Description: Encode string for use in URLs
;   Arguments:   .hString = source string handle
;   Returns:     EAX = new string handle with encoded content
;   CF:          0 = success, 1 = error
;   Note:        Replaces special chars with %XX format
;               Caller must free result with StrDel
;
; StrURLDecode
;   Description: Decode URL-encoded string
;   Arguments:   .hString = URL-encoded string handle
;   Returns:     None (modifies string in place)
;   CF:          0 = success, 1 = error
;   Note:        Converts %XX back to original characters
;               Modifies the string in place
;
; StrEncodeHTML
;   Description: Encode HTML special characters
;   Arguments:   .hString = source string handle
;   Returns:     EAX = new string handle with encoded content
;   CF:          0 = success, 1 = error
;   Note:        Replaces: < &lt; > &gt; & &amp; " &quot; ' &apos;
;               Caller must free result with StrDel
;
; StrDecodeHTML
;   Description: Decode HTML entities
;   Arguments:   .hString = string with HTML entities
;   Returns:     None (modifies string in place)
;   CF:          0 = success, 1 = error
;   Note:        Converts HTML entities back to characters
;               Modifies the string in place
;
; See demo01 for: InitializeAll, FinalizeAll, StrNew, StrDup, StrDupMem,
;               StrPtr, StrLen, StrDel, FileWriteString
;
; ========================================

; ========================================
; Global Variables
; ========================================
uglobal
  hSource        dd ?
  hEncoded       dd ?
endg

; ========================================
; Constants
; ========================================
iglobal
  cCRLF      text 13, 10

  cTitle     text "=== Demo 10: String Encoding ===", 13, 10, 13, 10

  cLabel1    text "1. URL Encoding: 'hello world?query=1&sort=asc'"
  cLabel2    text "   Encoded: '"
  cLabel3    text "   Decoded: '"

  cLabel4    text "2. HTML Encoding: '<script>alert(', 34, 'XSS', 34, ')</script>'"
  cLabel5    text "   Encoded: '"
  cLabel6    text "   Decoded: '"

  cDone      text 13, 10, "Demo 10 complete!", 13, 10
  cError     text "Error!", 13, 10
endg

; ========================================
; Entry Point
; ========================================
start:
        InitializeAll

        stdcall FileWriteString, [STDOUT], cTitle

; ========================================
; Demo 1: URL Encoding and Decoding
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel1
        stdcall FileWriteString, [STDOUT], cCRLF

; Create source string
        stdcall StrDupMem, <"hello world?query=1&sort=asc">
        jc      .error
        mov     [hSource], eax

; URL encode
        stdcall StrURLEncode, [hSource]
        jc      .error
        mov     [hEncoded], eax

        stdcall FileWriteString, [STDOUT], cLabel2
        stdcall StrPtr, [hEncoded], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], <"'", 13, 10>

; URL decode (modifies hEncoded in place)
        stdcall StrURLDecode, [hEncoded]
        jc      .error

        stdcall FileWriteString, [STDOUT], cLabel3
        stdcall StrPtr, [hEncoded], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], <"'", 13, 10>

; Clean up
        stdcall StrDel, [hSource]
        stdcall StrDel, [hEncoded]

        stdcall FileWriteString, [STDOUT], cCRLF

; ========================================
; Demo 2: HTML Encoding and Decoding
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel4
        stdcall FileWriteString, [STDOUT], cCRLF

; Create source string with HTML special chars
        stdcall StrDupMem, <'<script>alert(', 34, 'XSS', 34, ')</script>'>
        jc      .error
        mov     [hSource], eax

; HTML encode
        stdcall StrEncodeHTML, [hSource]
        jc      .error
        mov     [hEncoded], eax

        stdcall FileWriteString, [STDOUT], cLabel5
        stdcall StrPtr, [hEncoded], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], <"'", 13, 10>

; HTML decode (modifies hEncoded in place)
        stdcall StrDecodeHTML, [hEncoded]
        jc      .error

        stdcall FileWriteString, [STDOUT], cLabel6
        stdcall StrPtr, [hEncoded], eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall FileWriteString, [STDOUT], <"'", 13, 10>

; Clean up
        stdcall StrDel, [hSource]
        stdcall StrDel, [hEncoded]

        stdcall FileWriteString, [STDOUT], cDone

.finish:
        FinalizeAll
        stdcall TerminateAll, 0

.error:
        stdcall FileWriteString, [STDOUT], cError
        jmp     .finish
36
27.12.25 16:12
; _______________________________________________________________________________________
;| FreshLib String Processing Tutorial: Demo 11 - Pattern Matching
;|_______________________________________________________________________________________|
;  Description: Demonstrates wildcard string matching
;  Topics: StrMatchPattern, StrMatchPatternNoCase
;  Prerequisites: Demo 01
;_________________________________________________________________________________________

include "%lib%/freshlib.inc"

LINUX_INTERPRETER equ './ld-musl-i386.so'

@BinaryType console, compact
LIB_MODE equ NOGUI

options.DebugMode = 0

include "%lib%/freshlib.asm"

; ========================================
; FUNCTION REFERENCE
; ========================================
;
; StrMatchPattern
;   Description: Match string against wildcard pattern (case-sensitive)
;   Arguments:   .string  = string to test
;               .pattern = wildcard pattern
;   Returns:     None (uses Carry Flag)
;   CF:          1 = pattern matches, 0 = no match
;   Note:        * matches any characters, ? matches one character
;
; StrMatchPatternNoCase
;   Description: Match string against wildcard pattern (case-insensitive)
;   Arguments:   .string  = string to test
;               .pattern = wildcard pattern
;   Returns:     None (uses Carry Flag)
;   CF:          1 = pattern matches, 0 = no match
;   Note:        * matches any characters, ? matches one character
;
; See demo01 for: InitializeAll, FinalizeAll, StrNew, StrDup, StrDupMem,
;               StrPtr, StrLen, StrDel, FileWriteString
;
; ========================================

; ========================================
; Global Variables
; ========================================
uglobal
  hString        dd ?
  hPattern       dd ?
endg

; ========================================
; Constants
; ========================================
iglobal
  cCRLF      text 13, 10

  cTitle     text "=== Demo 11: Pattern Matching ===", 13, 10, 13, 10

  cLabel1    text "1. '*.txt' matches 'document.txt': "
  cLabel2    text "2. '*.txt' matches 'document.pdf': "
  cLabel3    text "3. 'file?.txt' matches 'file1.txt': "
  cLabel4    text "4. 'file?.txt' matches 'file10.txt': "
  cLabel5    text "5. '*.asm' matches 'demo.ASM' (case-sensitive): "
  cLabel6    text "6. '*.asm' matches 'demo.ASM' (case-insensitive): "
  cLabel7    text "7. 'test*' matches 'test_data_123.bin': "

  cMatch     text "MATCH", 13, 10
  cNoMatch   text "NO MATCH", 13, 10

  cDone      text 13, 10, "Demo 11 complete!", 13, 10
  cError     text "Error!", 13, 10
endg

; ========================================
; Entry Point
; ========================================
start:
        InitializeAll

        stdcall FileWriteString, [STDOUT], cTitle

; ========================================
; Demo 1: *.txt matches document.txt
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel1

        stdcall StrDupMem, <"document.txt">
        jc      .error
        mov     [hString], eax

        stdcall StrMatchPattern, [hString], "*.txt"
        jc      .match1

        stdcall FileWriteString, [STDOUT], cNoMatch
        jmp     .cleanup1

.match1:
        stdcall FileWriteString, [STDOUT], cMatch

.cleanup1:
        stdcall StrDel, [hString]

; ========================================
; Demo 2: *.txt does NOT match document.pdf
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel2

        stdcall StrDupMem, <"document.pdf">
        jc      .error
        mov     [hString], eax

        stdcall StrMatchPattern, [hString], "*.txt"
        jc      .match2

        stdcall FileWriteString, [STDOUT], cNoMatch
        jmp     .cleanup2

.match2:
        stdcall FileWriteString, [STDOUT], cMatch

.cleanup2:
        stdcall StrDel, [hString]

; ========================================
; Demo 3: file?.txt matches file1.txt
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel3

        stdcall StrDupMem, <"file1.txt">
        jc      .error
        mov     [hString], eax

        stdcall StrMatchPattern, [hString], "file?.txt"
        jc      .match3

        stdcall FileWriteString, [STDOUT], cNoMatch
        jmp     .cleanup3

.match3:
        stdcall FileWriteString, [STDOUT], cMatch

.cleanup3:
        stdcall StrDel, [hString]

; ========================================
; Demo 4: file?.txt does NOT match file10.txt
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel4

        stdcall StrDupMem, <"file10.txt">
        jc      .error
        mov     [hString], eax

        stdcall StrMatchPattern, [hString], "file?.txt"
        jc      .match4

        stdcall FileWriteString, [STDOUT], cNoMatch
        jmp     .cleanup4

.match4:
        stdcall FileWriteString, [STDOUT], cMatch

.cleanup4:
        stdcall StrDel, [hString]

; ========================================
; Demo 5: Case-sensitive matching
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel5

        stdcall StrDupMem, <"demo.ASM">
        jc      .error
        mov     [hString], eax

        stdcall StrMatchPattern, [hString], "*.asm"
        jc      .match5

        stdcall FileWriteString, [STDOUT], cNoMatch
        jmp     .cleanup5

.match5:
        stdcall FileWriteString, [STDOUT], cMatch

.cleanup5:
        stdcall StrDel, [hString]

; ========================================
; Demo 6: Case-insensitive matching
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel6

        stdcall StrDupMem, <"demo.ASM">
        jc      .error
        mov     [hString], eax

        stdcall StrMatchPatternNoCase, [hString], "*.asm"
        jc      .match6

        stdcall FileWriteString, [STDOUT], cNoMatch
        jmp     .cleanup6

.match6:
        stdcall FileWriteString, [STDOUT], cMatch

.cleanup6:
        stdcall StrDel, [hString]

; ========================================
; Demo 7: test* matches test_data_123.bin
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel7

        stdcall StrDupMem, <"test_data_123.bin">
        jc      .error
        mov     [hString], eax

        stdcall StrMatchPattern, [hString], "test*"
        jc      .match7

        stdcall FileWriteString, [STDOUT], cNoMatch
        jmp     .cleanup7

.match7:
        stdcall FileWriteString, [STDOUT], cMatch

.cleanup7:
        stdcall StrDel, [hString]

        stdcall FileWriteString, [STDOUT], cDone

.finish:
        FinalizeAll
        stdcall TerminateAll, 0

.error:
        stdcall FileWriteString, [STDOUT], cError
        jmp     .finish
35
27.12.25 16:13
; _______________________________________________________________________________________
;| FreshLib String Processing Tutorial: Demo 12 - Hash and Sort
;|_______________________________________________________________________________________|
;  Description: Demonstrates string hashing and sort comparison
;  Topics: StrHash, StrCompSort2, SetString
;  Prerequisites: Demo 01
;_________________________________________________________________________________________

include "%lib%/freshlib.inc"

LINUX_INTERPRETER equ './ld-musl-i386.so'

@BinaryType console, compact
LIB_MODE equ NOGUI

options.DebugMode = 0

include "%lib%/freshlib.asm"

; ========================================
; FUNCTION REFERENCE
; ========================================
;
; StrHash
;   Description: Compute FNV-1b hash of string
;   Arguments:   .hString = string handle
;   Returns:     EAX = 32-bit hash value
;   CF:          0 = success
;   Note:        Deterministic: same string always produces same hash
;               Fast, non-cryptographic hash for hash tables
;
; StrCompSort2
;   Description: Compare two strings for sorting
;   Arguments:   .str1    = first string handle or pointer
;               .str2    = second string handle or pointer
;   Returns:     EAX = comparison result
;               -1 if str1 < str2
;                0 if str1 = str2
;                1 if str1 > str2
;   CF:          0 = success
;   Note:        Perfect for sorting algorithms (qsort, binary search)
;
; SetString
;   Description: Create or set a string variable
;   Arguments:   .ptrVar  = pointer to string variable
;               .hString  = string handle to assign
;   Returns:     None
;   Note:        Handles memory management automatically
;
; See demo01 for: InitializeAll, FinalizeAll, StrNew, StrDup, StrDupMem,
;               StrPtr, StrLen, StrDel, NumToStr, FileWriteString
;
; ========================================

; ========================================
; Global Variables
; ========================================
uglobal
  hString1       dd ?
  hString2       dd ?
  hString3       dd ?
  hashValue1     dd ?
  hashValue2     dd ?
  hashValue3     dd ?
  sortResult     dd ?
  stringVar      dd ?
endg

; ========================================
; Constants
; ========================================
iglobal
  cCRLF      text 13, 10

  cTitle     text "=== Demo 12: Hash and Sort ===", 13, 10, 13, 10

  cLabel1    text "1. StrHash - Computing hash values:", 13, 10
  cLabel2    text "2. StrCompSort2 - Comparing strings:", 13, 10

  cLabel3    text "   Compare 'apple' vs 'banana': "
  cLabel4    text "   Compare 'banana' vs 'apple': "
  cLabel5    text "   Compare 'apple' vs 'apple': "

  cLess      text "-1 (less than)", 13, 10
  cEqual     text "0 (equal)", 13, 10
  cGreater   text "1 (greater than)", 13, 10

  cDone      text 13, 10, "Demo 12 complete!", 13, 10
  cError     text "Error!", 13, 10
endg

; ========================================
; Entry Point
; ========================================
start:
        InitializeAll

        stdcall FileWriteString, [STDOUT], cTitle

; ========================================
; Demo 1: Computing hash values
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel1

        stdcall StrDupMem, <"Hello">
        jc      .error
        mov     [hString1], eax

        stdcall StrDupMem, <"World">
        jc      .error
        mov     [hString2], eax

        stdcall StrDupMem, <"Hello">
        jc      .error
        mov     [hString3], eax

; Compute hash of "Hello"
        stdcall StrHash, [hString1]
        mov     [hashValue1], eax
        push    eax

        stdcall FileWriteString, [STDOUT], <"   Hash('Hello') = ">
        pop     eax
        stdcall NumToStr, eax, ntsHex or ntsUnsigned
        push    eax
        stdcall FileWriteString, [STDOUT], eax
        pop     eax
        stdcall StrDel, eax
        stdcall FileWriteString, [STDOUT], cCRLF

; Compute hash of "World"
        stdcall StrHash, [hString2]
        mov     [hashValue2], eax
        push    eax

        stdcall FileWriteString, [STDOUT], <"   Hash('World') = ">
        pop     eax
        stdcall NumToStr, eax, ntsHex or ntsUnsigned
        push    eax
        stdcall FileWriteString, [STDOUT], eax
        pop     eax
        stdcall StrDel, eax
        stdcall FileWriteString, [STDOUT], cCRLF

; Compute hash of second "Hello"
        stdcall StrHash, [hString3]
        mov     [hashValue3], eax
        push    eax

        stdcall FileWriteString, [STDOUT], <"   Hash('Hello') = ">
        pop     eax
        stdcall NumToStr, eax, ntsHex or ntsUnsigned
        push    eax
        stdcall FileWriteString, [STDOUT], eax
        pop     eax
        stdcall StrDel, eax
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall FileWriteString, [STDOUT], <"   Note: Same strings have same hash!", 13, 10>

; Clean up
        stdcall StrDel, [hString1]
        stdcall StrDel, [hString2]
        stdcall StrDel, [hString3]

        stdcall FileWriteString, [STDOUT], cCRLF

; ========================================
; Demo 2: Sort comparison
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel2

; Create strings for comparison
        stdcall StrDupMem, <"apple">
        jc      .error
        mov     [hString1], eax

        stdcall StrDupMem, <"banana">
        jc      .error
        mov     [hString2], eax

; Compare "apple" vs "banana"
        stdcall FileWriteString, [STDOUT], cLabel3
        stdcall StrCompSort2, [hString1], [hString2]
        mov     [sortResult], eax

        cmp     eax, -1
        je      .less1
        cmp     eax, 0
        je      .equal1

        stdcall FileWriteString, [STDOUT], cGreater
        jmp     .compare2

.less1:
        stdcall FileWriteString, [STDOUT], cLess
        jmp     .compare2

.equal1:
        stdcall FileWriteString, [STDOUT], cEqual

.compare2:
; Compare "banana" vs "apple"
        stdcall FileWriteString, [STDOUT], cLabel4
        stdcall StrCompSort2, [hString2], [hString1]
        mov     [sortResult], eax

        cmp     eax, -1
        je      .less2
        cmp     eax, 0
        je      .equal2

        stdcall FileWriteString, [STDOUT], cGreater
        jmp     .compare3

.less2:
        stdcall FileWriteString, [STDOUT], cLess
        jmp     .compare3

.equal2:
        stdcall FileWriteString, [STDOUT], cEqual

.compare3:
; Compare "apple" vs "apple"
        stdcall FileWriteString, [STDOUT], cLabel5
        stdcall StrCompSort2, [hString1], [hString1]
        mov     [sortResult], eax

        cmp     eax, -1
        je      .less3
        cmp     eax, 0
        je      .equal3

        stdcall FileWriteString, [STDOUT], cGreater
        jmp     .cleanup

.less3:
        stdcall FileWriteString, [STDOUT], cLess
        jmp     .cleanup

.equal3:
        stdcall FileWriteString, [STDOUT], cEqual

.cleanup:
; Clean up
        stdcall StrDel, [hString1]
        stdcall StrDel, [hString2]

        stdcall FileWriteString, [STDOUT], cDone

.finish:
        FinalizeAll
        stdcall TerminateAll, 0

.error:
        stdcall FileWriteString, [STDOUT], cError
        jmp     .finish

Tutorial 03: StrLib - Advanced Features

0
#