From 6c9bd169bdcab488387518eb071532f1e62c564a Mon Sep 17 00:00:00 2001 From: Graeme Geldenhuys Date: Tue, 29 Sep 2009 16:38:12 +0200 Subject: Add more INF required units. Converted them all to be FPC compatible. Signed-off-by: Graeme Geldenhuys --- src/SearchTable.pas | 297 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 src/SearchTable.pas (limited to 'src/SearchTable.pas') diff --git a/src/SearchTable.pas b/src/SearchTable.pas new file mode 100644 index 00000000..ffbd3ee9 --- /dev/null +++ b/src/SearchTable.pas @@ -0,0 +1,297 @@ +Unit SearchTable; + +{$mode objfpc}{$H+} + +// NewView - a new OS/2 Help Viewer +// Copyright 2001 Aaron Lawrence (aaronl at consultant dot com) +// This software is released under the Gnu Public License - see readme.txt + +Interface + +uses + Classes, DataTypes; + +// Code to read and use IPF search tables +// NB The RLE decompression was arrived at by trial and error +// it seems to be correct but it's difficult to test. + +type + TSearchTable = class + protected + _Data: pointer; + _Entries: TList; // pointers to panel flag records + _RecordLengthIs16Bit: boolean; + _DictionaryCount: longint; + _TopicCount: longint; + + procedure ReadEntries; + + Procedure Check1ByteOfFlags( b: byte; + StartingIndex: longint; + Results: Int32ArrayPointer ); + + procedure DoRLESearch( p: pbyte; + pDataEnd: pointer; + Results: Int32ArrayPointer ); + + public + constructor Create( Data: pointer; + RecordLengthIs16Bit: boolean; + DictionaryCount: longint; + TopicCount: longint ); + destructor Destroy; override; + + procedure Search( DictIndex: int16; + Results: Int32ArrayPointer ); + + end; + +Implementation + +constructor TSearchTable.Create( Data: pointer; + RecordLengthIs16Bit: boolean; + DictionaryCount: longint; + TopicCount: longint ); +begin + _Data := Data; + _RecordLengthIs16Bit := + RecordLengthIs16Bit; + _Entries := TList.Create; + _DictionaryCount := DictionaryCount; + _TopicCount := TopicCount; + ReadEntries; +end; + +destructor TSearchTable.Destroy; +begin + _Entries.Destroy; +end; + +procedure TSearchTable.ReadEntries; +var + pWordRecord: pointer; + RecordLen: int16; + WordIndex: int16; +begin + pWordRecord:= _Data; + + for WordIndex:= 0 to _DictionaryCount - 1 do + begin + _Entries.Add( pWordRecord ); + + if _RecordLengthIs16Bit then + RecordLen:= pint16( pWordRecord )^ + else // 8 bit + RecordLen:= pint8( pWordRecord )^; + inc( pWordRecord, RecordLen ); + end; +end; + + +// Search table decompression + +// Looks through a single byte of 8 flags, given by b, +// and updates topic entries within results for any flags +// that are set. +Procedure TSearchTable.Check1ByteOfFlags( b: byte; + StartingIndex: longint; + Results: Int32ArrayPointer ); +var + TopicIndex: longint; +begin + TopicIndex:= StartingIndex; + while b > 0 do + begin + if b and $80 > 0 then + Results^[ TopicIndex ] := 1; + inc( TopicIndex ); + b:= b shl 1; + end; +end; + +// Decompress RLE compressed data starting at p, +// running til pDataEnd. Update topic entries in Results. +procedure TSearchTable.DoRLESearch( p: pbyte; + pDataEnd: pointer; + Results: Int32ArrayPointer ); +var + TopicIndex: integer; + + N: integer; + thebyte: byte; + byte1, byte2: byte; +begin + assert( pbyte( p )^ = 1, 'Unexpected RLE type' ); + inc( p ); // skip header, always 1? + + TopicIndex:= 0; + + while p < pDataEnd do + begin + thebyte:= p^; + inc( p ); + + if thebyte = $80 then + begin + // escape + thebyte := p^; + inc( p ); + + if thebyte = 0 then + begin + // 16 bit repeat of zeroes?? + N := pint16( p )^ + 1; + inc( p, 2 ); + inc( TopicIndex, N ); + end + else + begin + // n+1 repeats of next 2 bytes??? + N := thebyte + 1; + byte1 := p^; + inc( p ); + byte2 := p^; + inc( p ); + while N > 0 do + begin + Check1ByteOfFlags( byte1, + TopicIndex, + Results ); + inc( TopicIndex, 8 ); + Check1ByteOfFlags( byte2, + TopicIndex, + Results ); + inc( TopicIndex, 8 ); + dec( N ); + end; + end; + end + else + begin + N:= thebyte and $7f + 1; + + if thebyte and $80 > 0 then + begin + // literal data + while N > 0 do + begin + Check1ByteOfFlags( p^, + TopicIndex, + Results ); + inc( TopicIndex, 8 ); + inc( p ); + dec( N ); + end; + end + else + begin + // repeat of next byte + thebyte := p^; + inc( p ); + while N > 0 do + begin + Check1ByteOfFlags( thebyte, + TopicIndex, + Results ); + inc( TopicIndex, 8 ); + dec( N ); + end; + end; + end; + end; +end; + +// This function finds uses of the given word (DictIndex) +// using the search table. Results[ topic ] is set to +// non-zero for topics which contain the word. +procedure TSearchTable.Search( DictIndex: int16; + Results: Int32ArrayPointer ); +var + TopicIndex: integer; + pWordRecord: pointer; + RecordLen: int16; + CompressionCode: int8; + pData: pointer; + pDataEnd: pointer; + Flags: int8; +begin + FillInt32Array( Results, _TopicCount, 0 ); + + pWordRecord:= _Entries[ DictIndex ]; + + // Check search table format + if _RecordLengthIs16Bit then + begin + RecordLen:= pint16( pWordRecord )^; + CompressionCode:= pint8( pWordRecord + 2 )^; + pData:= pWordRecord + 3; + end + else // 8 bit + begin + RecordLen:= pint8( pWordRecord )^; + CompressionCode:= pint8( pWordRecord + 1 )^; + pData:= pWordRecord + 2; + end; + + // Decompress the search table for this word + pDataEnd:= pWordRecord + RecordLen; + case CompressionCode of + 0: // word not used anywhere. + ; + + 1: // used in all panels + FillInt32Array( Results, _TopicCount, 1 ); + + 2: // RLE + begin + DoRLESearch( pData, + pDataEnd, + Results ); + end; + + 3: // list of topics containing word + while pData < pDataEnd do + begin + TopicIndex:= pint16( pData )^; + Results^[ TopicIndex ] := 1; + inc( pData, 2 ); + end; + + 4: // list of topics NOT containing word + begin + FillInt32Array( Results, _TopicCount, 1 ); + + while pData < pDataEnd do + begin + TopicIndex:= pint16( pData )^; + Results^[ TopicIndex ] := 0; + inc( pData, 2 ); + end; + end; + + 5, // compressed by truncating bit stream at last byte containing a set bit. + 6: // same as above but starting at non-zero byte + begin + if CompressionCode = 5 then + TopicIndex:= 0 + else + begin + TopicIndex:= pInt16( pData )^ * 8; + inc( pData, 2 ); + end; + + while pData < pDataEnd do + begin + Flags:= pInt8( pData )^; + Check1ByteOfFlags( Flags, + TopicIndex, + Results ); + inc( TopicIndex, 8 ); + inc( pData ); + end; + end; + end; +end; + +Initialization +End. -- cgit v1.2.3-70-g09d2