sein. Zuerst sucht man also im Stamm nach einen Eintrag. Dieser führt
aber noch nicht zum Ergebniss sondern verweist nur auf die "Page" (Ast).
zum Ergebniss (Blatt).
bei CDX komplizierter weil ja "comprimiert" d.h. gleiche Werte kommen
nur 1x vor.
Code: Alles auswählen
#include "Fileio.ch"
#define PAGE_SIZE 1024
#define UNSIGNED 2
#define SIGNED 2
#define LONG 4
#define LONG2 4
#define STACK_SIZE 4096
/* Programm-Name: CDXDUMP.PRG
* Autor: original NTXdump by Isaac Said-Nejad
* Aufruf: CDXDUMP <Dateiname>
* Copyright (c): Nantucket Corp.
* Compilieren mit: /n/w/p
Byte offset Description
*** File header (page 0) ***
00 – 03 Pointer to root node
04 – 07 Pointer to free node list ( -1 if not present/empty)
07 -1 if none (FoxPro)
0 if none (FoxBase)
08 – 11 Version no. ,Reserved for internal use
08 (Foxbase, FoxPro 1.x) No. of pages in file. (FoxPro 2.x) Reserved.
12 – 13 Length of key
13 Number and date keys are 8 bits long . Character keys are <= 100
bytes long. Note! Character keys are NOT terminated with 00h
-1 if none (FoxPro)
0 if none (FoxBase)
14 Index options (any of the following numeric values or their sums):
14 Index options represented as the sum of the following values:
01 a Unique index
08 Index has FOR clause
16 (10h) Bit vector (SoftC)
32 (20h) Compact index format (FoxPro)
64 (40h) Compounding index header (FoxPro)
128 (80h) Structure index (FoxPro)
15 Index signature
16 – 19 Reserved for internal use
16 Reserved
20 – 23 Reserved for internal use
24 – 27 Reserved for internal use
28 – 31 Reserved for internal use
32 – 35 Reserved for internal use
36 – 501 Reserved for internal use
(Currently all NULL's)
502 – 503 Ascending or descending:
502 0 Ascending
1 Descending
504 – 505 Total expression length (FoxPro 2), Reserved for internal use
506 – 507 FOR expression pool length1 (binary)
508 – 509 Reserved for internal use
510 – 511 Key expression pool length1 (binary)
512 – 1023 Key expression pool (uncompiled)
Key first with null terminator, then FOR expression.
1 This information tracks the space used in the key expression pool.
*** Compact Index Interior Node Record ( Non leaf page ) ***
Byte offset Description
00 – 01 Node attributes (any of the following numeric values or their sums):
Node attributes represented as the sum of the following values:
0 Index Interior node (branch)
1 Root page
2 Leaf page
02 – 03 Number of keys present
(0, 1 or many)
04 – 07 Pointer to node directly to left of current node
(on same level, -1 if not present)
08 – 11 Pointer to node directly to right of current node
(on same level; -1 if not present)
12 – 511 Up to 500 characters containing the key value for the length of
the key with a four-byte hexadecimal number (stored in normal left-to-
right format):
Key data
Record number in data file (high order byte first)
Pointer to child page
This node always contains the index key, record number and intra-index
pointer.2
The key/four-byte hexadecimal number combinations will occur the number of
times indicated in bytes 02 – 03.
*** Compact Index Exterior Node Record ( Leaf page ) ***
00 – 01 Node attributes (any of the following numeric values or their sums):
Node attributes represented as the sum of the following values:
0 Index Interior node (branch)
1 Root page
2 Leaf page
02 – 03 Number of keys present
(0, 1 or many)
04 – 07 Pointer to the node directly to the left of current node
(on same level; -1 if not present)
08 – 11 Pointer to the node directly to right of the current node
(on same level; -1 if not present)
12 – 13 Available free space in node
14 – 17 Record number mask
18 Duplicate byte count mask
The individual list must be ANDed with these masks in order
to calculatethe original index.
19 Trailing byte count mask
The individual list must be ANDed with these masks in order
to calculatethe original index.
20 Number of bits used for record number
Byte 020 Number of bits for record number
21 Number of bits used for duplicate count
Byte 021 Number of bits for duplicate count
22 Number of bits used for trail count
Byte 022 Number of bits for trailing count
23 Number of bytes holding record number,
duplicate count and trailing count Byte 023: Number of bytes holding
record number, duplicate count & trailing count (i.e. the total size
of values in byte 20 - 22).
24 – 511 Index keys and information2
0 Recno/supCount/TrailCount
At the start of this area, the recno/dupCount/trailCount is stored
(bit compressed). Each entry requires the number of bytes as indicated
by byte 023.
The key values are placed at the end of this area (working backwards)
and are stored by eliminating any duplicates with the previous key and
any trailing blanks.
1
2
3
4 Record number in data file
5
6
7
8 Key data
2 Each entry consists of the record number, duplicate byte count and
trailing byte count, all compacted. The key text is placed at the logical
end of the node, working backwards, allowing for previous key entries.
Dates are stored as Julian dates and converted to numbers
Numbers are stored as IEEE doubles (binary values) with the following
conversion:
Convert to an IEEE double (8 bytes)
Swap the order of the bytes
IF the number was negative:
Invert all the bits
ELSE
Invert only the highest order bit
ENDIF
*/
FUNCTION MAIN(Cdx_file)
LOCAL handle, stack_pointer, read, root, key_size
LOCAL item_number, down, buffer, items, item_pointer
LOCAL child_page, item_at
LOCAL stack[STACK_SIZE]
LOCAL nZahl := 0
LOCAL hByte
CLEAR SCREEN
IF PCOUNT() == 0
? "Syntax: CDXDUMP <Dateiname>"
QUIT
ENDIF
handle := FOPEN(Cdx_file, 0)
IF FERROR() != 0
? "Fehler beim ™ffnen der Datei ", FERROR()
QUIT
ENDIF
stack_pointer := 1
buffer := SPACE(PAGE_SIZE)
read := FREAD(handle, @buffer, PAGE_SIZE)
IF read <> PAGE_SIZE
? "Fehler beim Lesen des Headers"
QUIT
ENDIF
SET ALTERNATE TO CDXDUMP.TXT
SET ALTERNATE ON
*** File header (page 0) ***
? " 00 – 03 Pointer to root node : ", BIN2L(SUBSTR(buffer, 1, LONG))
root := BIN2L(SUBSTR(buffer, 1, LONG))
? " 04 – 07 Pointer to free node list : ", BIN2L(SUBSTR(buffer, 5, LONG))
// ( -1 if not present)
//
// 07 -1 if none (FoxPro)
// 0 if none (FoxBase)
? " 07 Header type is : ", IF(BIN2I(SUBSTR(buffer, 8, 1))=0,"FoxBase","FoxPro")
? " 08 – 11 Reserved for internal use : ", BIN2L(SUBSTR(buffer, 9, LONG))
key_size := BIN2W(SUBSTR(buffer, 13, UNSIGNED))
? " 12 – 13 Length of key : ", BIN2W(SUBSTR(buffer, 13, UNSIGNED))
? " 14 Index options : ", BIN2I(SUBSTR(buffer, 15, 1))
// (any of the following numeric values or their sums):
// 1 – a unique index
// 8 – index has FOR clause
// 32 – compact index format
// 64 – compound index header
? " 15 Index signature : ", BIN2I(SUBSTR(buffer, 16, 1))
? " 16 – 19 Reserved for internal use : ", BIN2L(SUBSTR(buffer, 17, LONG))
? " 20 – 23 Reserved for internal use : ", BIN2L(SUBSTR(buffer, 21, LONG))
? " 24 – 27 Reserved for internal use : ", BIN2L(SUBSTR(buffer, 25, LONG))
? " 28 – 31 Reserved for internal use : ", BIN2L(SUBSTR(buffer, 29, LONG))
? " 32 – 35 Reserved for internal use : ", BIN2L(SUBSTR(buffer, 33, LONG))
? " 36 – 501 Reserved for internal use : ", SUBSTR(buffer, 37, 465)
? "502 – 503 Ascending or descending : ", BIN2W(SUBSTR(buffer,503, UNSIGNED))
// 0 = ascending
// 1 = descending
? "504 – 505 Reserved for internal use : ", BIN2W(SUBSTR(buffer,505, UNSIGNED))
? "506 – 507 FOR expression pool length1 : ", BIN2W(SUBSTR(buffer,507, UNSIGNED))
? "508 – 509 Reserved for internal use : ", BIN2W(SUBSTR(buffer,509, UNSIGNED))
? "510 – 511 Key expression pool length1 : ", BIN2W(SUBSTR(buffer,511, UNSIGNED))
? "512 – 1023 Key expression pool : ", SUBSTR(buffer,513, 512)
// (uncompiled)
ALTD()
item_number := 1
down := .T.
DO WHILE .T.
IF down .AND. root <> 0
FSEEK(handle, root)
read := FREAD(handle, @buffer, PAGE_SIZE)
IF read <> PAGE_SIZE
? "Fehler beim Lesen der Page"+STR(read)
?? STR( FSEEK(handle, 0 , FS_RELATIVE) )
QUIT
ENDIF
? ""
? "1.) Position"
?? STR( FSEEK(handle, 0 , FS_RELATIVE) )
? "***********************"
? "00 – 01 Node attributes : ", BIN2W(SUBSTR(buffer, 1, UNSIGNED))
// (any of the following numeric values or their sums):
? "02 – 03 Number of keys present : ", BIN2W(SUBSTR(buffer, 3, UNSIGNED))
// (0, 1 or many)
? "04 – 07 Pointer to the node left : ", BIN2L(SUBSTR(buffer, 5, LONG))
// directly to the left of current node (on same level; -1 if not present)
? "08 – 11 Pointer to the node right : ", BIN2L(SUBSTR(buffer, 9, LONG))
// directly to right of the current node (on same level; -1 if not present)
? "12 – 511 Index key value for the length : ", BIN2L(SUBSTR(buffer, 13, 500))
// Up to 500 characters containing the key value for the length of
// the key with a four-byte hexadecimal number (stored in normal
// left-to-right format):
hByte := SUBSTR(buffer, 13, LONG)
? "12 hByte : ", hByte
? " BIN2L( hByte ) : ", BIN2L( hByte )
hByte := SUBSTR(buffer, 13, LONG*2)
? "12 hByte*2 : ", hByte
? " BIN2L( hByte*2 ) : ", BIN2L( hByte )
? "12 Key data : ", BIN2I(SUBSTR(hByte, 1, 1))
? "16 Record number in data file : ", BIN2I(SUBSTR(hByte, 5, 1))
? "20 Pointer to child page : ", BIN2I(SUBSTR(hByte, 8, 1))
? " Index key value : ", SUBSTR(buffer, 13, 500)
hByte := SUBSTR(buffer, 508+18, LONG)
? " – 511 hByte : ", hByte
? " BIN2L( hByte ) : ", BIN2L( hByte )
hByte := SUBSTR(buffer, 504+18, LONG*2)
? " – 511 hByte*2 : ", hByte
? " BIN2L( hByte*2 ) : ", BIN2L( hByte )
? " 504 Key data : ", BIN2I(SUBSTR(hByte, 1, 1))
? " 508 Record number in data file : ", BIN2I(SUBSTR(hByte, 5, 1))
? " 511 Pointer to child page : ", BIN2I(SUBSTR(hByte, 8, 1))
// 00 – 01 Node attributes
items := BIN2W(SUBSTR(buffer, 1, UNSIGNED))
item_number := 1
item_pointer := UNSIGNED + 1
? ""
? "* items : "+STR(items )
? "* item_number : "+STR(item_number )
? "* item_pointer : "+STR(item_pointer)
// 02 – 03 Number of keys present
item_at := BIN2W(SUBSTR(buffer, item_pointer, LONG ))
? "* item_at : "+STR(item_at )
// 04 – 07 Pointer to the node directly to the left
child_page := BIN2W(SUBSTR(buffer, item_at+1, LONG))
? "* child_page is : "+STR(child_page)
stack_pointer := stack_pointer+LONG
IF stack_pointer > STACK_SIZE
? "Programm-Stack-Overflow"+STR(stack_pointer)
QUIT
ENDIF
stack[stack_pointer-4] := root
stack[stack_pointer-3] := items
stack[stack_pointer-2] := item_number
stack[stack_pointer-1] := item_at
root := child_page
? "* root : "+STR(root )
ELSEIF item_number <= items
? ""
? "2.) Position"
?? STR( FSEEK(handle, 0 , FS_RELATIVE) )
? "***********************"
? "00 – 01 Node attributes : ", BIN2W(SUBSTR(buffer, 1, UNSIGNED))
// (any of the following numeric values or their sums):
? "02 – 03 Number of keys present : ", BIN2W(SUBSTR(buffer, 3, UNSIGNED))
// (0, 1 or many)
? "04 – 07 Pointer to the node directly to the left: ", BIN2L(SUBSTR(buffer, 5, LONG))
// directly to the left of current node (on same level; -1 if not present)
? "08 – 11 Pointer to the node directly to right of: ", BIN2L(SUBSTR(buffer, 9, LONG))
// directly to right of the current node (on same level; -1 if not present)
? "12 – 13 Available free space in node : ", BIN2W(SUBSTR(buffer, 13, UNSIGNED))
? "14 – 17 Record number mask : ", BIN2L(SUBSTR(buffer, 15, LONG))
? "18 Duplicate byte count mask : ", BIN2I(SUBSTR(buffer, 19, 1))
? "19 Trailing byte count mask : ", BIN2I(SUBSTR(buffer, 20, 1))
? "20 Number of bits used for record number : ", BIN2I(SUBSTR(buffer, 21, 1))
? "21 Number of bits used for duplicate count : ", BIN2I(SUBSTR(buffer, 22, 1))
? "22 Number of bits used for trail count : ", BIN2I(SUBSTR(buffer, 23, 1))
? "23 Number of bytes holding record number : ", BIN2I(SUBSTR(buffer, 24, 1))
// duplicate count and trailing count
? "24 Recno/supCount/TrailCount : ", BIN2I(SUBSTR(buffer, 25, 1))
? "28 Record number in data file : ", BIN2I(SUBSTR(buffer, 29, 1))
? "31 Key data : ", BIN2I(SUBSTR(buffer, 32, 1))
hByte := SUBSTR(buffer, 25, LONG)
? " hByte : ", hByte
? " BIN2L( hByte ) : ", BIN2L( hByte )
? "24 – 511 Index keys and information2 : ", BIN2L(SUBSTR(buffer, 25, (511-24) ))
? " LEN() : ", STR(LEN(SUBSTR(buffer, 25, (511-24) )))
? " Index keys and information2 : ", SUBSTR(buffer, 25, (511-24) )
LEN(SUBSTR(buffer, 25, (511-24) ))
? " 504 Recno/supCount/TrailCount : ", BIN2I(SUBSTR(buffer,505, 1))
? " 508 Record number in data file : ", BIN2I(SUBSTR(buffer,508, 1))
? " 511 Key data : ", BIN2I(SUBSTR(buffer,512, 1))
hByte := SUBSTR(buffer,504, LONG)
? " hByte : ", hByte
? " BIN2L( hByte ) : ", BIN2L( hByte )
* ? "2a.) Position"
* ?? STR( FSEEK(handle, (25+511-24) , FS_RELATIVE) )
* ? "***********************"
* ? "2c.) Position"
* ?? STR( FSEEK(handle, -512 , FS_RELATIVE) )
* ? "***********************"
//
// dump out Element
//
? BIN2L(SUBSTR(buffer, item_at+1+LONG, LONG)),;
SUBSTR(buffer, item_at+ LONG2+5, key_size)
item_number := item_number + 1
stack[stack_pointer-2] := item_number
item_pointer := (item_number-1) * 2 + 2 + 1
? ""
? "* item_number : "+STR(item_number )
? "* item_pointer : "+STR(item_pointer)
// 02 – 03 Number of keys present (0, 1 or many)
item_at := BIN2W(SUBSTR(buffer, item_pointer, LONG))
? "* item_at : "+STR(item_at)
// 04 – 07 Pointer to the node directly to the left of current
// node (on same level; -1 if not present)
child_page := BIN2W(SUBSTR(buffer, item_at+1, LONG))
? "* child_page is : "+STR(child_page)
stack[stack_pointer-1] := item_at
stack[stack_pointer-3] := items
root := child_page
down := .T.
? "* root : "+STR(root )
nZahl++
ELSE
stack_pointer := stack_pointer-LONG
IF stack_pointer < 5
EXIT
ENDIF
? ""
? "3.) Position"
?? STR( FSEEK(handle, 0 , FS_RELATIVE) )
? "***********************"
root := stack[stack_pointer-4]
items := stack[stack_pointer-3]
item_number := stack[stack_pointer-2]
item_at := stack[stack_pointer-1]
down := .F.
FSEEK(handle, root)
read := FREAD(handle, @buffer, PAGE_SIZE)
IF read <> PAGE_SIZE
? "Fehler beim Lesen der Page"+STR(read)
?? STR( FSEEK(handle, 0 , FS_RELATIVE) )
QUIT
ENDIF
? "* root : "+STR(root )
? "* items : "+STR(items )
? "* item_number : "+STR(item_number )
? "* item_at : "+STR(item_at )
ENDIF
ENDDO
?
?
? "Anzahl",nZahl
?
SET ALTERNATE TO
SET ALTERNATE OFF
RETURN NIL
habe.