1 /* $XConsortium: OffsetOrderedList.C /main/1 1996/07/29 16:59:05 cde-hp $ */
2 // Copyright (c) 1994 James Clark
3 // See the file COPYING for copying permission.
6 #include "OffsetOrderedList.h"
10 namespace SP_NAMESPACE {
13 OffsetOrderedList::OffsetOrderedList()
14 : blockUsed_(OffsetOrderedListBlock::size)
18 void OffsetOrderedList::append(Offset offset)
20 // At any position in the list there's a current offset.
21 // The offset is initially zero.
22 // A byte of 255 says add 255 to the current offset.
23 // A byte B < 255, says that there's an item in the list whose
24 // offset is the current offset + B, and that B + 1 should be
25 // added to the current offset.
26 Offset curOffset = blocks_.size() > 0 ? blocks_.back()->offset : 0;
27 ASSERT(offset >= curOffset);
28 Offset count = offset - curOffset;
29 while (count >= 255) {
36 void OffsetOrderedList::addByte(unsigned char b)
38 if (blockUsed_ >= OffsetOrderedListBlock::size) {
39 blocks_.resize(blocks_.size() + 1);
40 Owner<OffsetOrderedListBlock> &last = blocks_.back();
41 last = new OffsetOrderedListBlock;
42 if (blocks_.size() == 1) {
47 OffsetOrderedListBlock &lastButOne = *blocks_[blocks_.size() - 2];
48 last->nextIndex = lastButOne.nextIndex;
49 last->offset = lastButOne.offset;
53 blocks_.back()->bytes[blockUsed_++] = b;
55 blocks_.back()->offset += 255;
57 blocks_.back()->offset += b + 1;
58 blocks_.back()->nextIndex += 1;
62 // Find the last offset <= off.
64 Boolean OffsetOrderedList::findPreceding(Offset off,
66 Offset &foundOffset) const
69 // blocks with index < i have offset <= off
70 // blocks with index >= lim have offset > off
72 size_t lim = blocks_.size();
73 // Most commonly we'll want to know the about positions near the end,
74 // so optimize this case.
75 if (lim > 0 && blocks_[lim - 1]->offset <= off)
77 else if (lim > 1 && blocks_[lim - 2]->offset <= off)
80 // Do a binary search.
82 size_t mid = i + (lim - i)/2;
83 if (blocks_[mid]->offset > off)
89 if (i == blocks_.size()) {
92 foundIndex = blocks_.back()->nextIndex - 1;
93 foundOffset = blocks_.back()->offset - 1;
96 // Note that an item with offset X can only occur in a block with offset > X
97 // i is now the first block with offset > off
98 Offset curOff = blocks_[i]->offset;
99 size_t curIndex = blocks_[i]->nextIndex;
100 const unsigned char *bytes = blocks_[i]->bytes;
101 int j = (i == blocks_.size() - 1
103 : int(OffsetOrderedListBlock::size));
106 if (bytes[j] != 255) {
117 j = OffsetOrderedListBlock::size;
118 curOff = blocks_[i]->offset;
119 curIndex = blocks_[i]->nextIndex;
120 bytes = blocks_[i]->bytes;
123 foundIndex = curIndex;
124 foundOffset = curOff;