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>
88 lines
2.2 KiB
Plaintext
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
|