DIRECTORY Ascii USING [Lower], Basics USING [MoveWords], BTree USING [Compare, CompareEntries, DeleteKey, Entry, EntryFromRecord, EntrySize, EnumerateEntries, GetState, Key, New, NewPathStk, NewRecordFromEntry, Open, PageNumber, PagePtr, PageSize, PageStorage, PathStk, ReadEntry, ReferencePage, Relation, ReleasePage, SalvageEntries, SetState, SetUpdateInProgress, State, Tree, UpdateEntry, UpdateType, Validate], BTreeSimple, BTreeVM, IO USING [STREAM], Rope USING [Flatten, NewText]; BTreeSimpleImpl: CEDAR PROGRAM IMPORTS Ascii, Basics, BTree, BTreeVM, Rope EXPORTS BTreeSimple SHARES Rope = { OPEN BTreeSimple; KeyFromEntry: PUBLIC UNSAFE PROC [entryKey: EntryKey] RETURNS [key: InternalKey ¬ NIL] = UNCHECKED { IF entryKey # NIL THEN { key ¬ Rope.NewText[entryKey.length]; -- on Michael Plass's recommendation key.length ¬ entryKey.length; Basics.MoveWords[dst: LOOPHOLE[key, POINTER]+SIZE[TEXT[0]], src: LOOPHOLE[entryKey+SIZE[EntryKeyObject[0]]], count: WORDS[EntryKeyObject[entryKey.length]] - WORDS[EntryKeyObject[0]] ]; RETURN[key]; }; }; ValueFromEntry: PUBLIC UNSAFE PROC [entryValue: EntryValue] RETURNS [value: Value ¬ NIL] = UNCHECKED { IF entryValue # NIL THEN { value ¬ NEW[ValueObject[entryValue.length]]; Basics.MoveWords[dst: LOOPHOLE[value, POINTER]+SIZE[ValueObject[0]], src: LOOPHOLE[entryValue, POINTER]+SIZE[ValueObject[0]], count: entryValue.length]; -- entryValue.length is in words RETURN[value]; }; }; DefaultCompare: Compare --[key: InternalKey, entryKey: EntryKey] RETURNS [Comparison]-- = UNCHECKED { FOR i: CARDINAL IN [0 .. MIN[key.length, entryKey.length]) DO kc: CHAR ¬ Ascii.Lower[key[i]]; ec: CHAR ¬ Ascii.Lower[entryKey[i]]; IF kc # ec THEN { IF kc < ec THEN RETURN[less] ELSE RETURN[greater] }; ENDLOOP; IF key.length = entryKey.length THEN RETURN[equal] ELSE {IF key.length < entryKey.length THEN RETURN[less] ELSE RETURN[greater]; }; }; DefaultCompareEntries: CompareEntries --[entryKey1, entryKey2: EntryKey] RETURNS [Comparison]-- = UNCHECKED { FOR i: CARDINAL IN [0 .. MIN[entryKey1.length, entryKey2.length]) DO c1: CHAR ¬ Ascii.Lower[entryKey1[i]]; c2: CHAR ¬ Ascii.Lower[entryKey2[i]]; IF c1 # c2 THEN { IF c1 file _ handle.backing; ENDCASE => file _ NIL; Higher-level BTree access Lower-level BTree access entryKey.length ¬ internalKey.length --Body of UpdateEntry Procedure PathStk hints Private The following are the procedures passed to the BTree package as the RepresentationPrimitives (in addition to the client's Compare and CompareEntries procedures). MoveOverlapped: PUBLIC UNSAFE PROC [dst: POINTER, src: POINTER, nWords: CARD] = UNCHECKED BEGIN WordPtr: TYPE = POINTER TO WORD; Test to see if blocks overlap--does destination overlap with source in the direction of increasing addresses? Note that this is an unsafe operation. IF LOOPHOLE[dst, CARD] > LOOPHOLE[src, CARD] AND LOOPHOLE[dst, CARD] - LOOPHOLE[src, CARD] < nWords THEN { WHILE nWords > 0 DO nWords ¬ nWords - 1 * SIZE[BYTE]; LOOPHOLE[dst+nWords, WordPtr]­ ¬ LOOPHOLE[src+nWords, WordPtr]­; ENDLOOP; RETURN }; Destination either overlaps with source in the reverse direction, or overlaps not at all. We use Basics. Basics.MoveWords[dst: dst, src: src, count: nWords/SIZE[BYTE]]; END; Errors Ê e•NewlineDelimiter –(cedarcode) style™head™Icodešœ ÏeœI™TL™%L™1L™(L™(L™'L™%L™šÏk ˜ Lšœžœ ˜Lšœžœ ˜LšœžœÚ˜åL˜ L˜Lšžœžœžœ˜Lšœžœ˜L˜L˜——šÐbnœžœž˜Lšžœ%˜,Lšžœ ˜Lšžœ˜ Lšœžœ ˜L˜L™—šœ™šÏn œžœžœžœ˜6Lšžœžœž œ˜.šžœ žœžœ˜Lšœžœ ™)Lšœ%Ïc$˜IL˜L™ªš œžœžœžœžœ˜Lšœžœžœ˜7Lšœžœ"˜:L˜Lšœ›˜›Lšœ˜L˜—š œž œžœžœžœ$žœ žœžœ žœž œ˜¬š   œžœžœžœ žœž œ˜ULšžœ"žœžœ˜R—L˜1Lšœ˜——šœ ™ š  œž œžœ˜6Lšžœ˜Lšœ˜——™L™¡L™š  œ¡7œž œ˜`Lšœžœ˜Lšœžœ˜Lšœžœ˜Lšœžœ˜L˜Lšœžœ˜4Lšœžœ#˜6Lšœžœ(˜FLšœžœ#˜9L˜'Lšœ˜L˜—š œ¡Ðck¡œž œ˜lLšžœ¡=˜ULšœ˜L˜—š œ¡¢¡œž œ˜rLšžœ¡=˜ULšœ˜L˜—š œžœžœžœžœžœ žœž ™\šž™Lš œ žœžœžœžœ™ LšÐciÏi8£=™”šžœžœžœžœžœžœžœžœžœžœ žœ™jšžœ ž™Mšœžœžœ™!Mšžœžœ™@Mšžœ™—Mšž™Mšœ™M™—Mš£Z™ZMšœ™Mšœ3žœžœ™?Mšžœ™M™———™Lšœžœžœ˜"Lšœ žœ˜L˜Lšœ˜——…—)º>1