source: trunk/NewView/SearchTable.pas@ 18

Last change on this file since 18 was 18, checked in by RBRi, 19 years ago

+ newview source

  • Property svn:eol-style set to native
File size: 7.3 KB
Line 
1Unit SearchTable;
2
3// NewView - a new OS/2 Help Viewer
4// Copyright 2003 Aaron Lawrence (aaronl at consultant dot com)
5// This software is released under the Gnu Public License - see readme.txt
6
7Interface
8
9uses
10 Classes, IPFFileFormatUnit, OS2Def;
11
12// Code to read and use IPF search tables
13// NB The RLE decompression was arrived at by trial and error
14// it seems to be correct but it's difficult to test.
15
16type
17 TSearchTable = class
18 protected
19 _Data: pointer;
20 _Entries: TList; // pointers to panel flag records
21 _RecordLengthIs16Bit: boolean;
22 _DictionaryCount: longint;
23 _TopicCount: longint;
24
25 procedure ReadEntries;
26
27 Procedure Check1ByteOfFlags( b: byte;
28 StartingIndex: longint;
29 Results: UInt32ArrayPointer );
30
31 procedure DoRLESearch( p: pbyte;
32 pDataEnd: pointer;
33 Results: UInt32ArrayPointer );
34
35 public
36 constructor Create( Data: pointer;
37 RecordLengthIs16Bit: boolean;
38 DictionaryCount: longint;
39 TopicCount: longint );
40 destructor Destroy; override;
41
42 // Sets Results to 1 for occurrences of DictIndex
43 procedure Search( DictIndex: uint16;
44 Results: UInt32ArrayPointer );
45
46 end;
47
48Implementation
49
50constructor TSearchTable.Create( Data: pointer;
51 RecordLengthIs16Bit: boolean;
52 DictionaryCount: longint;
53 TopicCount: longint );
54begin
55 _Data := Data;
56 _RecordLengthIs16Bit :=
57 RecordLengthIs16Bit;
58 _Entries := TList.Create;
59 _DictionaryCount := DictionaryCount;
60 _TopicCount := TopicCount;
61 ReadEntries;
62end;
63
64destructor TSearchTable.Destroy;
65begin
66 _Entries.Destroy;
67end;
68
69procedure TSearchTable.ReadEntries;
70var
71 pWordRecord: pointer;
72 RecordLen: uint16;
73 WordIndex: uint16;
74begin
75 pWordRecord:= _Data;
76
77 for WordIndex:= 0 to _DictionaryCount - 1 do
78 begin
79 _Entries.Add( pWordRecord );
80
81 if _RecordLengthIs16Bit then
82 RecordLen:= pUInt16( pWordRecord )^
83 else // 8 bit
84 RecordLen:= pUInt8( pWordRecord )^;
85 inc( pWordRecord, RecordLen );
86 end;
87end;
88
89
90// Search table decompression
91
92// Looks through a single byte of 8 flags, given by b,
93// and updates topic entries within results for any flags
94// that are set.
95Procedure TSearchTable.Check1ByteOfFlags( b: byte;
96 StartingIndex: longint;
97 Results: UInt32ArrayPointer );
98var
99 TopicIndex: longint;
100begin
101 TopicIndex:= StartingIndex;
102 while b > 0 do
103 begin
104 if b and $80 > 0 then
105 Results[ TopicIndex ] := 1;
106 inc( TopicIndex );
107 b:= b shl 1;
108 end;
109end;
110
111// Decompress RLE compressed data starting at p,
112// running til pDataEnd. Update topic entries in Results.
113procedure TSearchTable.DoRLESearch( p: pbyte;
114 pDataEnd: pointer;
115 Results: UInt32ArrayPointer );
116var
117 TopicIndex: integer;
118
119 N: integer;
120 thebyte: byte;
121 byte1, byte2: byte;
122begin
123 assert( pbyte( p )^ = 1, 'Unexpected RLE type' );
124 inc( p ); // skip header, always 1?
125
126 TopicIndex:= 0;
127
128 while p < pDataEnd do
129 begin
130 thebyte:= p^;
131 inc( p );
132
133 if thebyte = $80 then
134 begin
135 // escape
136 thebyte := p^;
137 inc( p );
138
139 if thebyte = 0 then
140 begin
141 // 16 bit repeat of zeroes??
142 N := pUInt16( p )^ + 1;
143 inc( p, 2 );
144 inc( TopicIndex, N );
145 end
146 else
147 begin
148 // n+1 repeats of next 2 bytes???
149 N := thebyte + 1;
150 byte1 := p^;
151 inc( p );
152 byte2 := p^;
153 inc( p );
154 while N > 0 do
155 begin
156 Check1ByteOfFlags( byte1,
157 TopicIndex,
158 Results );
159 inc( TopicIndex, 8 );
160 Check1ByteOfFlags( byte2,
161 TopicIndex,
162 Results );
163 inc( TopicIndex, 8 );
164 dec( N );
165 end;
166 end;
167 end
168 else
169 begin
170 N:= thebyte and $7f + 1;
171
172 if thebyte and $80 > 0 then
173 begin
174 // literal data
175 while N > 0 do
176 begin
177 Check1ByteOfFlags( p^,
178 TopicIndex,
179 Results );
180 inc( TopicIndex, 8 );
181 inc( p );
182 dec( N );
183 end;
184 end
185 else
186 begin
187 // repeat of next byte
188 thebyte := p^;
189 inc( p );
190 while N > 0 do
191 begin
192 Check1ByteOfFlags( thebyte,
193 TopicIndex,
194 Results );
195 inc( TopicIndex, 8 );
196 dec( N );
197 end;
198 end;
199 end;
200 end;
201end;
202
203// This function finds uses of the given word (DictIndex)
204// using the search table. Results[ topic ] is set to
205// non-zero for topics which contain the word.
206procedure TSearchTable.Search( DictIndex: uint16;
207 Results: UInt32ArrayPointer );
208var
209 TopicIndex: integer;
210 pWordRecord: pointer;
211 RecordLen: uint16;
212 CompressionCode: uint8;
213 pData: pointer;
214 pDataEnd: pointer;
215 Flags: uint8;
216begin
217 pWordRecord:= _Entries[ DictIndex ];
218
219 // Check search table format
220 if _RecordLengthIs16Bit then
221 begin
222 RecordLen:= pUInt16( pWordRecord )^;
223 CompressionCode:= pUInt8( pWordRecord + 2 )^;
224 pData:= pWordRecord + 3;
225 end
226 else // 8 bit
227 begin
228 RecordLen:= pUInt8( pWordRecord )^;
229 CompressionCode:= pUInt8( pWordRecord + 1 )^;
230 pData:= pWordRecord + 2;
231 end;
232
233 // Decompress the search table for this word
234 pDataEnd:= pWordRecord + RecordLen;
235 case CompressionCode of
236 0: // word not used anywhere.
237 ClearUInt32Array( Results, _TopicCount );
238
239 1: // used in all panels
240 FillUInt32Array( Results, _TopicCount, 1 );
241
242 2: // RLE
243 begin
244 ClearUInt32Array( Results, _TopicCount );
245 DoRLESearch( pData,
246 pDataEnd,
247 Results );
248 end;
249
250 3: // list of topics containing word
251 begin
252 ClearUInt32Array( Results, _TopicCount );
253 while pData < pDataEnd do
254 begin
255 TopicIndex:= pUInt16( pData )^;
256 Results^[ TopicIndex ] := 1;
257 inc( pData, 2 );
258 end;
259 end;
260
261 4: // list of topics NOT containing word
262 begin
263 FillUInt32Array( Results, _TopicCount, 1 );
264
265 while pData < pDataEnd do
266 begin
267 TopicIndex:= pUInt16( pData )^;
268 Results^[ TopicIndex ] := 0;
269 inc( pData, 2 );
270 end;
271 end;
272
273 5, // compressed by truncating bit stream at last byte containing a set bit.
274 6: // same as above but starting at non-zero byte (first word contains start topic)
275 begin
276 ClearUInt32Array( Results, _TopicCount );
277 if CompressionCode = 5 then
278 begin
279 TopicIndex:= 0
280 end
281 else
282 begin
283 TopicIndex:= pUInt16( pData )^ * 8;
284 inc( pData, 2 );
285 end;
286
287 while pData < pDataEnd do
288 begin
289 Flags:= pUInt8( pData )^;
290 Check1ByteOfFlags( Flags,
291 TopicIndex,
292 Results );
293 inc( TopicIndex, 8 );
294 inc( pData );
295 end;
296 end;
297
298 else
299 // unknown method
300 ClearUInt32Array( Results, _TopicCount );
301 end;
302end;
303
304Initialization
305End.
Note: See TracBrowser for help on using the repository browser.