6 Copyright (c) 1991-2001, Be Incorporated. All rights reserved.
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
29 BeMail(TM), Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
51 static int32 kCRCTable
= 0;
54 int32
cmp_i_entries(const WIndexEntry
*e1
, const WIndexEntry
*e2
);
56 unsigned long update_crc(unsigned long crc_accum
, const char *data_blk_ptr
,
60 FileEntry::FileEntry(void)
66 FileEntry::FileEntry(const char *entryString
)
75 WIndex::SetTo(const char *dataPath
, const char *indexPath
)
80 dataFile
= new BFile();
82 if (dataFile
->SetTo(dataPath
, B_READ_ONLY
) != B_OK
) {
85 bool buildIndex
= true;
91 dataFile
->GetModificationTime(&mtime
);
93 if (indexFile
.SetTo(indexPath
, B_READ_ONLY
) == B_OK
) {
95 if ((indexFile
.GetAttrInfo("WINDEX:version", &info
) == B_OK
)) {
97 indexFile
.ReadAttr("WINDEX:version", B_UINT32_TYPE
, 0,
99 if (IVERSION
== version
) {
100 if ((indexFile
.GetAttrInfo("WINDEX:modified", &info
)
102 indexFile
.ReadAttr("WINDEX:modified", B_UINT32_TYPE
, 0,
105 if (mtime
== modified
) {
106 if (UnflattenIndex(&indexFile
) == B_OK
)
117 if (indexFile
.SetTo(indexPath
,
118 B_WRITE_ONLY
| B_CREATE_FILE
| B_ERASE_FILE
) == B_OK
) {
119 FlattenIndex(&indexFile
);
120 indexFile
.WriteAttr("WINDEX:modified", B_UINT32_TYPE
, 0,
122 uint32 version
= IVERSION
;
123 indexFile
.WriteAttr("WINDEX:version", B_UINT32_TYPE
, 0,
132 FileEntry::~FileEntry(void)
138 WIndex::WIndex(int32 count
)
142 fEntriesPerBlock
= count
;
143 fEntrySize
= sizeof(WIndexEntry
);
144 if (!atomic_or(&kCRCTable
, 1))
149 WIndex::WIndex(BPositionIO
*dataFile
, int32 count
)
152 fDataFile
= dataFile
;
153 fEntriesPerBlock
= count
;
154 fEntrySize
= sizeof(WIndexEntry
);
155 if (!atomic_or(&kCRCTable
, 1))
160 WIndex::~WIndex(void)
169 WIndex::UnflattenIndex(BPositionIO
*io
)
175 io
->Seek(0, SEEK_SET
);
176 io
->Read(&head
, sizeof(head
));
177 io
->Seek(head
.offset
, SEEK_SET
);
179 fEntrySize
= head
.entrySize
;
180 fEntries
= head
.entries
;
181 fMaxEntries
= fEntriesPerBlock
;
182 fBlockSize
= fEntriesPerBlock
* fEntrySize
;
183 fBlocks
= fEntries
/ fEntriesPerBlock
+ 1;;
186 int32 size
= (head
.entries
+ 1) * head
.entrySize
;
187 if (!(fEntryList
= (uint8
*)malloc(size
)))
191 io
->Read(fEntryList
, size
);
198 WIndex::FlattenIndex(BPositionIO
*io
)
200 if (fEntries
&& !fIsSorted
)
204 head
.entries
= fEntries
;
205 head
.entrySize
= fEntrySize
;
206 head
.offset
= sizeof(WIndexHead
);
207 io
->Seek(0, SEEK_SET
);
208 io
->Write(&head
, sizeof(head
));
210 io
->Write(fEntryList
, head
.entries
* head
.entrySize
);
217 WIndex::Lookup(int32 key
)
230 if (key
< ((WIndexEntry
*)(fEntryList
+ (M
* fEntrySize
)))->key
)
232 else if (key
> ((WIndexEntry
*)(fEntryList
+ (M
* fEntrySize
)))->key
)
243 WIndex::AddItem(WIndexEntry
*entry
)
245 if (_BlockCheck() == B_ERROR
)
247 memcpy(((WIndexEntry
*)(fEntryList
+ (fEntries
* fEntrySize
))), entry
,
256 WIndex::SortItems(void)
258 qsort(fEntryList
, fEntries
, fEntrySize
,
259 (int(*)(const void *, const void *))cmp_i_entries
);
266 WIndex::_BlockCheck(void)
268 if (fEntries
< fMaxEntries
)
270 fBlocks
= fEntries
/ fEntriesPerBlock
+ 1;
271 fEntryList
= (uint8
*)realloc(fEntryList
, fBlockSize
* fBlocks
);
279 WIndex::InitIndex(void)
285 fMaxEntries
= fEntriesPerBlock
;
286 fBlockSize
= fEntriesPerBlock
* fEntrySize
;
288 fEntryList
= (uint8
*)malloc(fBlockSize
);
296 WIndex::GetKey(const char *s
)
307 key ^= (a * x + b) % m;
311 key
= update_crc(0, s
, strlen(s
));
313 if (key
< 0) // No negative values!
321 cmp_i_entries(const WIndexEntry
*e1
, const WIndexEntry
*e2
)
323 return e1
->key
- e2
->key
;
328 WIndex::SetTo(BPositionIO
*dataFile
)
330 fDataFile
= dataFile
;
343 WIndex::FindFirst(const char *word
)
352 NormalizeWord(word
, nword
);
355 if ((index
= Lookup(key
)) < 0)
357 // Find first instance of key
358 while ((ItemAt(index
- 1))->key
== key
)
365 WIndex::GetEntry(int32 index
)
367 if ((index
>= fEntries
)||(index
< 0))
373 dentry
= new FileEntry();
375 ientry
= ItemAt(index
);
379 fDataFile
->Seek(ientry
->offset
, SEEK_SET
);
380 buffer
= dentry
->LockBuffer(256);
381 fDataFile
->Read(buffer
, 256);
382 size
= _GetEntrySize(ientry
, buffer
);
384 //printf("Entry: = %s\n", buffer);
385 dentry
->UnlockBuffer(size
);
391 WIndex::_GetEntrySize(WIndexEntry
*entry
, const char *entryData
)
393 // eliminate unused parameter warning
396 return strcspn(entryData
, "\n\r");
401 WIndex::GetEntry(const char *word
)
403 return GetEntry(FindFirst(word
));
408 WIndex::NormalizeWord(const char *word
, char *dest
)
413 // remove dots and copy
423 // convert to lower-case
424 for (dst
= dest
; *dst
; dst
++)
425 *dst
= tolower(*dst
);
430 /* crc32h.c -- package to compute 32-bit CRC one byte at a time using */
431 /* the high-bit first (Big-Endian) bit ordering convention */
434 /* gen_crc_table() -- generates a 256-word table containing all CRC */
435 /* remainders for every possible 8-bit byte. It */
436 /* must be executed (once) before any CRC updates. */
438 /* unsigned update_crc(crc_accum, data_blk_ptr, data_blk_size) */
439 /* unsigned crc_accum; char *data_blk_ptr; int data_blk_size; */
440 /* Returns the updated value of the CRC accumulator after */
441 /* processing each byte in the addressed block of data. */
443 /* It is assumed that an unsigned long is at least 32 bits wide and */
444 /* that the predefined type char occupies one 8-bit byte of storage. */
446 /* The generator polynomial used for this version of the package is */
447 /* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 */
448 /* as specified in the Autodin/Ethernet/ADCCP protocol standards. */
449 /* Other degree 32 polynomials may be substituted by re-defining the */
450 /* symbol POLYNOMIAL below. Lower degree polynomials must first be */
451 /* multiplied by an appropriate power of x. The representation used */
452 /* is that the coefficient of x^0 is stored in the LSB of the 32-bit */
453 /* word and the coefficient of x^31 is stored in the most significant */
454 /* bit. The CRC is to be appended to the data most significant byte */
455 /* first. For those protocols in which bytes are transmitted MSB */
456 /* first and in the same order as they are encountered in the block */
457 /* this convention results in the CRC remainder being transmitted with */
458 /* the coefficient of x^31 first and with that of x^0 last (just as */
459 /* would be done by a hardware shift register mechanization). */
461 /* The table lookup technique was adapted from the algorithm described */
462 /* by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
465 #define POLYNOMIAL 0x04c11db7L
468 static unsigned long crc_table
[256];
474 // generate the table of CRC remainders for all possible bytes
477 register unsigned long crc_accum
;
479 for (i
= 0; i
< 256; i
++) {
480 crc_accum
= ((unsigned long) i
<< 24);
481 for (j
= 0; j
< 8; j
++) {
482 if (crc_accum
& 0x80000000L
)
483 crc_accum
= (crc_accum
<< 1) ^ POLYNOMIAL
;
485 crc_accum
= (crc_accum
<< 1);
487 crc_table
[i
] = crc_accum
;
495 update_crc(unsigned long crc_accum
, const char *data_blk_ptr
, int data_blk_size
)
497 // update the CRC on the data block one byte at a time
501 for (j
= 0; j
< data_blk_size
; j
++) {
502 i
= ((int) (crc_accum
>> 24) ^ *data_blk_ptr
++) & 0xff;
503 crc_accum
= (crc_accum
<< 8) ^ crc_table
[i
];