Files
five/examples/cross_cdx_test.prg
Charles KWON OhJun 7e2a159b88 feat: CDX support + ORDSCOPE + cross-read Harbour compatibility
CDX Integration:
- IndexEngine interface: common for NTX Index and CDX Tag
- OrderListAdd: auto-detects .cdx/.ntx extension, opens CDX tags
- decodeCompoundLeaf: proper bit-packed tag directory decoding
  (was stub falling through to scanCompoundLeaves with wrong names)
- CDX Tag: added KeyLen(), KeyExpr(), ForExpr(), IsDescending(), Close()
- CDX compound recNo = direct byte offset (not page number)

ORDSCOPE:
- SetScope/ClearScope/SetScopeTop/SetScopeBottom on DBFArea
- GoTopIndexed: seeks to scopeTop, validates within scopeBottom
- GoBottomIndexed: seeks to scopeBottom boundary
- SkipIndexed: stops at scope boundaries (top and bottom)
- OrdScope RTL function registered (nScope: 0=TOP, 1=BOTTOM)
- scopeKeyFromValue: converts Value to padded key bytes

Index Order Management:
- OrderListFocus: handles numeric order ("2" → order 2)
- SET ORDER TO n: gengo emits hbrt.NtoS for int-to-string conversion
- IndexOrd/OrdCount/OrdName/OrdKey: real implementations (were stubs)
- OrderCount/CurrentOrder/OrderName/OrderKeyExpr accessors on DBFArea
- ClearScope on order switch (prevents stale scope)

Cross-read test: Harbour-created CDX → Five reads, 20/20 items match:
  NAME/CITY/ID seek, ORDSCOPE count, GoTop/GoBottom all identical

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:21:26 +09:00

88 lines
2.2 KiB
Plaintext

// Five reads Harbour-created CDX — binary compatibility + ORDSCOPE test
PROCEDURE Main()
LOCAL nCount
// Open Harbour-created DBF + CDX
USE "/tmp/cdx_test" NEW
SET INDEX TO "/tmp/cdx_test.cdx"
? "RECORDS=" + LTrim(Str(RecCount()))
? "ORDCOUNT=" + LTrim(Str(OrdCount()))
// NAME tag
OrdSetFocus("BYNAME")
GO TOP
? "N_TOP=" + RTrim(FieldGet(2)) + " " + LTrim(Str(FieldGet(1)))
SEEK PadR("Name_001", 20)
? "N_S001=" + IIF(Found(),".T.",".F.") + " " + LTrim(Str(RecNo()))
SEEK PadR("Name_025", 20)
? "N_S025=" + IIF(Found(),".T.",".F.") + " " + LTrim(Str(RecNo()))
SEEK PadR("Name_050", 20)
? "N_S050=" + IIF(Found(),".T.",".F.") + " " + LTrim(Str(RecNo()))
SEEK "Name_01"
? "N_P01=" + IIF(Found(),".T.",".F.") + " " + LTrim(Str(RecNo()))
GO BOTTOM
? "N_BOTTOM=" + RTrim(FieldGet(2)) + " " + LTrim(Str(RecNo()))
// CITY tag
OrdSetFocus("BYCITY")
GO TOP
? "C_TOP=" + RTrim(FieldGet(3)) + " " + LTrim(Str(FieldGet(1)))
SEEK PadR("Seoul", 15)
? "C_SEOUL=" + IIF(Found(),".T.",".F.") + " " + LTrim(Str(RecNo()))
SEEK PadR("Tokyo", 15)
? "C_TOKYO=" + IIF(Found(),".T.",".F.") + " " + LTrim(Str(RecNo()))
// ORDSCOPE on CITY: London..Seoul
OrdScope(0, PadR("London", 15))
OrdScope(1, PadR("Seoul", 15))
GO TOP
? "SCOPE_TOP=" + RTrim(FieldGet(3)) + " " + LTrim(Str(RecNo()))
GO BOTTOM
? "SCOPE_BOT=" + RTrim(FieldGet(3)) + " " + LTrim(Str(RecNo()))
GO TOP
nCount := 0
DO WHILE !EOF()
nCount++
SKIP
ENDDO
? "SCOPE_CNT=" + LTrim(Str(nCount))
// Clear scope
OrdScope(0, NIL)
OrdScope(1, NIL)
GO TOP
nCount := 0
DO WHILE !EOF()
nCount++
SKIP
ENDDO
? "NOSCOPE_CNT=" + LTrim(Str(nCount))
// ID tag
OrdSetFocus("BYID")
SEEK Str(10, 6)
? "I_S10=" + IIF(Found(),".T.",".F.") + " " + LTrim(Str(RecNo()))
SEEK Str(40, 6)
? "I_S40=" + IIF(Found(),".T.",".F.") + " " + LTrim(Str(RecNo()))
// ORDSCOPE on ID: 20..30
OrdScope(0, Str(20, 6))
OrdScope(1, Str(30, 6))
GO TOP
nCount := 0
DO WHILE !EOF()
nCount++
SKIP
ENDDO
? "ID_SCOPE_CNT=" + LTrim(Str(nCount))
OrdScope(0, NIL)
OrdScope(1, NIL)
CLOSE ALL
RETURN