Tutorial 06: TText - Real-World Patterns

0
#
12
27.12.25 16:21

Tutorial 06: TText - Real-World Patterns

Overview

This tutorial demonstrates how TText is used in real-world applications, showing patterns from the AsmBB forum engine. You'll learn to build HTTP responses, integrate with StrLib, and apply practical text editing techniques.

Topics Covered

1. HTTP Response Building

  • Creating dynamic HTTP headers

  • Building HTML content incrementally

  • Managing text buffers efficiently

2. TText + StrLib Integration

  • Converting between TText and StrLib strings

  • When to use each text representation

  • Memory management best practices

3. Common Real-World Patterns

  • Pattern: Keep TText pointer in register (EDX)

  • Pattern: Update pointer after each modifying call

  • Pattern: Use position -1 for appending

  • Pattern: Compact only at the end

Prerequisites

Before starting this tutorial, you should have completed:

  • Tutorial 04: TText - Gap Buffer Basics

  • Tutorial 05: TText - Advanced Operations

  • Understanding of HTTP protocol basics

Demos

Demo Filename Description
19 demo19_ttext_advanced.asm Complete HTTP response builder

Building and Running

cd 06-ttext-manipulation
./build.sh

This will compile and test all demos.

Real-World Patterns from AsmBB

Pattern 1: Keep Pointer in Register

AsmBB frequently keeps the TText pointer in EDX throughout operations:

stdcall TextCreate, sizeof.TText
mov     edx, eax              ; Keep in EDX

; All operations use EDX
stdcall TextAddString, edx, -1, cHeader
mov     edx, eax              ; Update after reallocation
stdcall TextAddString, edx, -1, cContent
mov     edx, eax

Why: Avoids memory load/store and follows AsmBB conventions.

Pattern 2: Build HTTP Responses Incrementally

; Start with status line
stdcall TextAddString, edx, -1, cHTTP200
mov     edx, eax

; Add headers
stdcall TextAddString, edx, -1, cContentType
mov     edx, eax

; Add blank line (end of headers)
stdcall TextAddString, edx, -1, cCRLF
mov     edx, eax

; Add body
stdcall TextAddString, edx, -1, cBody
mov     edx, eax

; Compact only when ready to send
stdcall TextCompact, edx
stdcall FileWrite, [hSocket], edx, [...]

Pattern 3: Use GapBegin for Current Position

When appending at current position, use GapBegin directly:

stdcall TextAddString, edx, [edx+TText.GapBegin], cString
mov     edx, eax

This is equivalent to position -1 but explicitly uses the gap position.

Pattern 4: Update After Every Modifying Call

CRITICAL: Always capture EDX after calls that modify content:

  • TextAddString → mov edx, eax

  • TextSetGapSize → mov edx, eax

  • TextDelChar → (no pointer change)

  • TextMoveGap → (no pointer change)

  • TextCompact → (may change pointer!)

Function Reference Summary

All TText functions covered in Tutorials 04-06:

Creation (Tutorial 04)

  • TextCreate - Allocate new TText buffer

  • TextDup - Duplicate TText

  • TextFree - Free TText buffer

Insertion (Tutorial 04)

  • TextAddString - Add string at position

  • TextAddBytes - Add raw bytes at position

  • TextAddChar - Add character at gap

  • TextAddText - Add TText content

Deletion (Tutorial 04)

  • TextDelChar - Delete character at gap

  • TextCompact - Collapse gap to end

  • TextSetGapSize - Adjust gap size

Movement (Tutorial 04)

  • TextMoveGap - Move gap to position

Search (Tutorial 05)

  • TextPrepareSearch - Build KMP table

  • TextSearch - Search for substring

Coordinates (Tutorial 05)

  • TextIndexToPos - Character index to byte position

  • TextPosToIndex - Byte position to character index

  • TextPosToOffset - Position to memory offset

  • TextOffsetToPos - Memory offset to position

Utility (Tutorial 04)

  • TextGetChar - Get character at gap

  • TextDebugInfo - Display structure info

Next Steps

After completing this tutorial series, you should be able to:

  • Build text editors using gap buffers

  • Create dynamic HTTP responses

  • Integrate TText with StrLib

  • Apply real-world patterns from AsmBB

For further study:

  • Read ~/Documents/fossil/asmbb/source/render2.asm - AsmBB's template engine

  • Study ~/Documents/fossil/FreshIDE/freshlib/data/buffergap.asm - TText implementation

11
27.12.25 16:21
; Demo 19: TText Real-World Patterns
; Demonstrates building HTTP responses and practical TText usage patterns

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"

; ========================================
; Data Section
; ========================================
uglobal
  pResponse      dd ?
  hOutput        dd ?
endg

iglobal
  cCRLF          text 13, 10

  cTitle         text "=== Demo 19: TText Real-World Patterns ===", 13, 10, 13, 10

  cLabel1        text "1. Building HTTP Response:", 13, 10
  cLabel2        text "2. Using GapBegin for Current Position:", 13, 10
  cLabel3        text "3. Pattern Comparison:", 13, 10
  cLabel4        text "4. Integration with StrLib:", 13, 10

; HTTP Response components
  cHTTPStatus    text "HTTP/1.1 200 OK"
  cServer        text "Server: AsmBB/1.0"
  cContentType  text "Content-Type: text/html; charset=utf-8"
  cContentLen    text "Content-Length: "

; HTML content
  cHTMLStart     text "<!DOCTYPE html><html><head><title>"
  cHTMLTitle     text "TText Demo"
  cHTMLMid       text "</title></head><body><h1>"
  cHTMLHeading   text "Hello from TText!"
  cHTMLBody      text "</h1><p>This page was generated using FreshLib TText.</p></body></html>"

  cDoubleCRLF    text 13, 10, 13, 10

; Pattern demonstration
  cPattern1      text "First"
  cPattern2      text " Second"
  cPattern3      text " Third"

; StrLib integration test
  cStrLibText    text "Dynamic content"

  cArrow         text " -> "
  cColon         text ": "
  cResult        text "  Result: '"

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

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

        stdcall FileWriteString, [STDOUT], cTitle

; ========================================
; Demo 1: Building HTTP Response
; Shows real-world pattern from AsmBB
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel1

        stdcall TextCreate, sizeof.TText
        test    eax, eax
        jz      .error
        mov     [pResponse], eax

; Build HTTP response incrementally
        stdcall TextAddString, [pResponse], -1, cHTTPStatus
        mov     [pResponse], edx
        stdcall TextAddString, [pResponse], -1, cCRLF
        mov     [pResponse], edx
        stdcall TextAddString, [pResponse], -1, cServer
        mov     [pResponse], edx
        stdcall TextAddString, [pResponse], -1, cCRLF
        mov     [pResponse], edx
        stdcall TextAddString, [pResponse], -1, cDoubleCRLF
        mov     [pResponse], edx

; Display result
        stdcall FileWriteString, [STDOUT], <"  HTTP Response:", 13, 10>
        stdcall TextCompact, [pResponse]
        stdcall FileWriteString, [STDOUT], [pResponse]
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall TextFree, [pResponse]
        stdcall FileWriteString, [STDOUT], cCRLF

; ========================================
; Demo 2: Using GapBegin for Current Position
; Shows alternative to position -1
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel2

        stdcall TextCreate, sizeof.TText
        test    eax, eax
        jz      .error
        mov     [pResponse], eax

; Pattern: Use GapBegin instead of -1
        mov     esi, [pResponse]
        stdcall TextAddString, [pResponse], [esi+TText.GapBegin], cPattern1
        mov     [pResponse], edx
        mov     esi, [pResponse]
        stdcall TextAddString, [pResponse], [esi+TText.GapBegin], cPattern2
        mov     [pResponse], edx
        mov     esi, [pResponse]
        stdcall TextAddString, [pResponse], [esi+TText.GapBegin], cPattern3
        mov     [pResponse], edx

; Display result
        stdcall TextCompact, [pResponse]
        stdcall FileWriteString, [STDOUT], cResult
        stdcall FileWriteString, [STDOUT], [pResponse]
        stdcall FileWriteString, [STDOUT], <"'", 13, 10>

        stdcall TextFree, [pResponse]
        stdcall FileWriteString, [STDOUT], cCRLF

; ========================================
; Demo 3: Pattern Comparison
; Shows difference between approaches
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel3

        stdcall FileWriteString, [STDOUT], <"  Approach 1: Position -1 (append)", 13, 10>

        stdcall TextCreate, sizeof.TText
        test    eax, eax
        jz      .error
        mov     [pResponse], eax

        stdcall TextAddString, [pResponse], -1, cPattern1
        mov     [pResponse], edx
        stdcall TextAddString, [pResponse], -1, cPattern2
        mov     [pResponse], edx
        stdcall TextAddString, [pResponse], -1, cPattern3
        mov     [pResponse], edx

        stdcall TextCompact, [pResponse]
        stdcall FileWriteString, [STDOUT], cResult
        stdcall FileWriteString, [STDOUT], [pResponse]
        stdcall FileWriteString, [STDOUT], <"'", 13, 10>

        stdcall TextFree, [pResponse]

        stdcall FileWriteString, [STDOUT], <"  Approach 2: Use GapBegin", 13, 10>

        stdcall TextCreate, sizeof.TText
        test    eax, eax
        jz      .error
        mov     [pResponse], eax

        mov     esi, [pResponse]
        stdcall TextAddString, [pResponse], [esi+TText.GapBegin], cPattern1
        mov     [pResponse], edx
        mov     esi, [pResponse]
        stdcall TextAddString, [pResponse], [esi+TText.GapBegin], cPattern2
        mov     [pResponse], edx
        mov     esi, [pResponse]
        stdcall TextAddString, [pResponse], [esi+TText.GapBegin], cPattern3
        mov     [pResponse], edx

        stdcall TextCompact, [pResponse]
        stdcall FileWriteString, [STDOUT], cResult
        stdcall FileWriteString, [STDOUT], [pResponse]
        stdcall FileWriteString, [STDOUT], <"'", 13, 10, 13, 10>

        stdcall TextFree, [pResponse]

; ========================================
; Demo 4: Integration with StrLib
; Shows when to use each text type
; ========================================
        stdcall FileWriteString, [STDOUT], cLabel4

        stdcall FileWriteString, [STDOUT], <"  StrLib: Good for temporary text", 13, 10>
        stdcall FileWriteString, [STDOUT], <"  TText: Good for building content", 13, 10>
        stdcall FileWriteString, [STDOUT], <"  Pattern: Build with TText, convert for output", 13, 10>

; Create StrLib string for processing
        stdcall StrDupMem, cStrLibText
        test    eax, eax
        jz      .error
        mov     [hOutput], eax

; Process with StrLib (e.g., transform case)
        stdcall StrUCase, [hOutput]

; Convert to TText for final assembly
        stdcall TextCreate, sizeof.TText
        test    eax, eax
        jz      .error
        mov     [pResponse], eax

        stdcall TextAddString, [pResponse], -1, <"Processed: ">
        mov     [pResponse], edx
        stdcall TextAddString, [pResponse], -1, [hOutput]
        mov     [pResponse], edx
        stdcall TextAddString, [pResponse], -1, cCRLF
        mov     [pResponse], edx

; Display
        stdcall TextCompact, [pResponse]
        stdcall FileWriteString, [STDOUT], cResult
        stdcall FileWriteString, [STDOUT], [pResponse]
        stdcall FileWriteString, [STDOUT], <"'", 13, 10>

        stdcall TextFree, [pResponse]
        stdcall StrDel, [hOutput]

; ========================================
; Summary
; ========================================
        stdcall FileWriteString, [STDOUT], <"  Key Patterns:", 13, 10>
        stdcall FileWriteString, [STDOUT], <"  1. Keep TText in register (EDX)", 13, 10>
        stdcall FileWriteString, [STDOUT], <"  2. Update pointer after TextAddString", 13, 10>
        stdcall FileWriteString, [STDOUT], <"  3. Use -1 or GapBegin for append", 13, 10>
        stdcall FileWriteString, [STDOUT], <"  4. Compact only before output", 13, 10>
        stdcall FileWriteString, [STDOUT], cCRLF

        stdcall FileWriteString, [STDOUT], cDone

.finish:
        FinalizeAll
        stdcall TerminateAll, 0

.error:
        stdcall FileWriteString, [STDOUT], cError
        FinalizeAll
        stdcall TerminateAll, 1

; ========================================
; FUNCTION REFERENCE
; ========================================
; (See Tutorials 04-05 for detailed function reference)
;
; Key Real-World Patterns:
;
; Pattern 1: Keep pointer in EDX
;   stdcall TextCreate, sizeof.TText
;   mov     edx, eax              ; Keep in EDX
;   stdcall TextAddString, edx, -1, cText
;   mov     edx, eax              ; Update after realloc!
;
; Pattern 2: Use GapBegin for append
;   stdcall TextAddString, edx, [edx+TText.GapBegin], cText
;   mov     edx, eax
;
; Pattern 3: Build incrementally, compact at end
;   stdcall TextAddString, edx, -1, cPart1
;   mov     edx, eax
;   stdcall TextAddString, edx, -1, cPart2
;   mov     edx, eax
;   stdcall TextCompact, edx       ; Only before output
;
; Pattern 4: Integration with StrLib
;   ; Build/transform with StrLib
;   stdcall StrDupMem, cRaw
;   stdcall StrUpper, eax
;   ; Then add to TText for final assembly
;   stdcall TextAddString, edx, -1, eax
;   mov     edx, eax
;   stdcall StrDel, eax
;

Tutorial 06: TText - Real-World Patterns

0
#