DIRECTORY RopeFrom, RopeEdit, RopeEditingAlloc, RopeReader, Rope, RopeInline, RTStorageOps, File, Space, PropertyTypes, Directory, Inline, IO, RopeEditingBLT; RopeFromFileImpl: CEDAR MONITOR IMPORTS RopeEditingBLT, RopeEditingAlloc, RopeReader, Rope, RopeInline, RopeEdit, RopeFrom, Space, Inline, Directory, RTStorageOps, IO EXPORTS RopeFrom SHARES Rope = BEGIN OPEN fileI:File, RopeFrom, RopeInline; pagesPerSpace: NAT = RopeReader.pagesPerArray; charsPerPage: NAT = RopeReader.charsPerPage; charsPerArray: NAT = RopeReader.charsPerArray; charsPerSpace: NAT = charsPerArray; spaceMin: NAT = charsPerSpace/2; -- put in shared array if less than 1/2 swapUnitSize: NAT = 16; -- based on Paul's advice CharsArray: TYPE = RopeReader.CharsArray; Chars: TYPE = REF CharsArray; File: PUBLIC PROC [ file: fileI.Capability, start: Offset _ 0, length: Offset _ MaxLen, -- defaults to rest of file activate: BOOLEAN _ FALSE, fileLen: Offset _ MaxLen, okToMapFile: BOOLEAN _ TRUE] RETURNS [rope: ROPE] = { MakeRope: PROC [startSpace, numToDo: Offset] RETURNS [rope: ROPE] = TRUSTED { chars: REF RopeReader.CharsArray; fileSpace: Space.Handle; len: NAT _ charsPerSpace; firstSpace: BOOLEAN _ FALSE; IF numToDo = 0 THEN RETURN [NIL]; IF numToDo > 1 THEN { -- split into balanced parts half: Offset _ numToDo/2; front: ROPE _ MakeRope[startSpace, half]; back: ROPE _ MakeRope[startSpace+half, numToDo-half]; RETURN [Rope.Concat[front,back]] }; IF startSpace+1 = numSpaces THEN -- this is the last space len _ len - endSkip; IF startSpace = 0 THEN { -- this is the first space for the file len _ len - startSkip; firstSpace _ TRUE }; IF ~okToMapFile OR len < spaceMin THEN { -- don't make a separate space for it start, nwords: NAT; charOffset, skipWords: NAT _ 0; base: ROPE; IF firstSpace THEN { charOffset _ startSkip MOD 2; skipWords _ startSkip/2 }; nwords _ (len+charOffset+1)/2; -- number to copy from file [chars, start, base] _ RopeEditingAlloc.AllocWords[nwords]; fileSpace _ GetSpace[]; Space.Map[fileSpace, Space.WindowOrigin[file, startPage+startSpace*pagesPerSpace]]; Space.Activate[fileSpace]; Inline.LongCOPY[from: Space.LongPointer[fileSpace]+skipWords, nwords: nwords, to: LOOPHOLE[chars,LONG POINTER]+start/2]; FreeSpace[fileSpace]; RETURN [qZone.NEW[Tsubstr _ [node[substr[len,base,start+charOffset,RopeEdit.Depth[base]+1]]]]] }; [chars,fileSpace] _ GetArraySpace[]; Space.Map[fileSpace,Space.WindowOrigin[file, startPage+startSpace*pagesPerSpace]]; IF swapUnitSize > pagesPerSpace THEN Space.CreateUniformSwapUnits[swapUnitSize, fileSpace]; IF activate THEN Space.Activate[fileSpace]; rope _ RopeReader.CharsRope[chars,fileSpace]; IF len < charsPerSpace THEN rope _ qZone.NEW[Tsubstr _ [node[substr[len, rope, IF firstSpace THEN startSkip ELSE 0, 1+ RopeEdit.Depth[rope]]]]]}; GetFileLen: PROC = TRUSTED { Directory.GetProperty[file: file, property: PropertyTypes.tByteLength, propertyValue: DESCRIPTOR[@fileLen, SIZE[Offset]]] }; startPage: Offset; startSkip, endSkip: NAT; numPages, numSpaces: Offset; start _ start+charsPerPage; -- to skip over leader page startPage _ start/charsPerPage; startSkip _ start MOD charsPerPage; IF fileLen = MaxLen THEN GetFileLen; fileLen _ fileLen+charsPerPage; -- to compensate for leader page IF fileLen <= start THEN RETURN [NIL]; length _ MIN[length,fileLen-start]; IF length = 0 THEN RETURN[NIL]; numPages _ (start+length+charsPerPage-1)/charsPerPage-startPage; numSpaces _ (numPages+pagesPerSpace-1)/pagesPerSpace; endSkip _ numSpaces*charsPerSpace-length-startSkip; rope _ MakeRope[0,numSpaces]}; Stream: PUBLIC PROC [stream: IO.Handle, length: Offset _ MaxLen] RETURNS [rope: ROPE] = { MakeRope: PROC [len: Offset] RETURNS [ROPE] = { chars: REF RopeReader.CharsArray; start, nchars, charloc: NAT; base: ROPE; IF len = 0 THEN RETURN [NIL]; IF len > charsPerSpace THEN { -- split into balanced parts half: Offset _ MAX[len/2,charsPerSpace]; front: ROPE _ MakeRope[half]; back: ROPE _ MakeRope[len-half]; RETURN [Rope.Concat[front,back]] }; nchars _ Short[len]; [chars, start, base] _ RopeEditingAlloc.AllocWords[(nchars+1)/2]; charloc _ start; UNTIL nchars = 0 DO nread: NAT; block.length _ 0; nread _ IO.GetBlock[self: stream, block: block, startIndex: 0, stopIndexPlusOne: nchars]; RopeEditingBLT.StringToArrayBlt[block,0,chars,charloc,nread]; nchars _ nchars-nread; charloc _ charloc+nread; ENDLOOP; RETURN [qZone.NEW[Tsubstr _ [node[substr[len,base,start,1+RopeEdit.Depth[base]]]]]] }; start,fileLen: Offset; block: REF TEXT; fileLen _ IO.GetLength[stream]; start _ IO.GetIndex[stream]; IF fileLen <= start THEN RETURN [NIL]; length _ MIN[length,fileLen-start]; IF length = 0 THEN RETURN [NIL]; block _ RopeEditingAlloc.GetBlock[]; rope _ MakeRope[length]; RopeEditingAlloc.FreeBlock[block] }; fileSpace: Space.Handle _ Space.nullHandle; -- shared file space numSpaces: INT _ 0; -- number allocated freedSpaces: INT _ 0; GetSpace: ENTRY PROC RETURNS [space: Space.Handle] = TRUSTED { ENABLE UNWIND => NULL; IF fileSpace # Space.nullHandle THEN space _ fileSpace ELSE { -- need to allocate one space _ Space.Create[pagesPerSpace, Space.virtualMemory]; numSpaces _ numSpaces+1 }; fileSpace _ Space.nullHandle }; FreeSpace: ENTRY PROC [space: Space.Handle] = TRUSTED { ENABLE UNWIND => NULL; IF fileSpace = Space.nullHandle THEN Space.Unmap[fileSpace _ space] ELSE { Space.Delete[space]; freedSpaces _ freedSpaces+1 }}; collectibleSpaces: INT _ 0; GetArraySpace: PROC RETURNS [chars: REF CharsArray, space: Space.Handle] = TRUSTED { chars _ NARROW[RTStorageOps.NewCollectibleSubspace[pagesPerSpace,CODE[CharsArray]]]; collectibleSpaces _ collectibleSpaces+1; space _ Space.GetHandle[Space.PageFromLongPointer[LOOPHOLE[chars]]] }; StartRopeFromFile: PUBLIC PROC = { }; END. ¤-- RopeFromFileImpl.Mesa -- written by Bill Paxton, February 1981 -- last edit by Paxton, November 12, 1982 3:17 pm Last Edited by: Maxwell, January 5, 1983 12:11 pm -- ***** Operations -- make skipWords*2+charOffset=startSkip -- ***** These two routines are the only monitored procedures -- ***** They provide a shared space for reading files -- Operation to get a space for file mapping -- ***** Initialization Ê‚˜JšÏc™Jš)™)Jš1™1J™1šÏk ˜ J˜ J˜ J˜J˜ J˜J˜ J˜ J˜J˜J˜J˜ J˜Jšžœ˜J˜J˜—šœž ˜šž˜J˜IJšœ2ž˜4—Jšžœ ˜Jšžœ˜ —Jšž˜Jšžœ"˜&J˜Jšœžœ˜.Jšœžœ˜,Jšœžœ˜.Jšœžœ˜#Jšœ žœ'˜HJšœžœ˜1J˜Jšœ žœ˜)Jšœžœžœ ˜J˜Jš™J˜šÏnœžœžœ˜J˜J˜Jšœ˜4Jšœ žœžœ˜J˜Jšœ žœžœ˜Jšžœžœ˜J˜šŸœžœ˜,Jšžœžœžœ˜ Jšœžœ˜!J˜Jšœžœ˜Jšœ žœžœ˜Jšžœ žœžœžœ˜!šžœ žœ˜2J˜Jšœžœ˜)Jšœžœ+˜5Jšžœ˜#—šžœžœ˜:J˜—šžœžœ'˜@Jšœ$žœ˜+—šžœžœžœ%˜NJšœžœ˜Jšœžœ˜Jšœžœ˜ šžœ žœ˜Jš(™(Jšœžœ˜J˜—Jšœ˜:J˜;J˜˜˜J˜%——J˜˜=Jšœžœžœžœ ˜:—J˜JšžœžœP˜a—J˜$˜,J˜%—šžœž˜$J˜6—Jšžœ žœ˜+J˜-šžœž˜šœ žœ˜,Jšœžœ žœ žœ˜*J˜J˜———šŸ œžœžœ˜J˜FJšœž œ žœ ˜5J˜—J˜Jšœžœ˜J˜J˜Jšœ˜7J˜Jšœžœ˜#Jšžœžœ ˜$Jšœ ˜@Jšžœžœžœžœ˜&Jšœ žœ˜#Jšžœ žœžœžœ˜J˜@J˜5J˜3J˜J˜—šŸœžœžœ žœ!˜@Jšžœžœ˜J˜šŸœžœžœžœ˜/Jšœžœ˜!Jšœžœ˜Jšœžœ˜ Jšžœ žœžœžœ˜šžœžœ˜:Jšœžœ˜(Jšœžœ˜Jšœžœ˜ Jšžœ˜#—J˜J˜AJ˜šžœ ž˜Jšœžœ˜ J˜JšœžœO˜YJ˜=J˜/Jšžœ˜—JšžœžœE˜VJ˜—J˜Jšœžœžœ˜J˜Jšœ žœ˜Jšœžœ˜Jšžœžœžœžœ˜&Jšœ žœ˜#Jšžœ žœžœžœ˜ J˜$J˜J˜$J˜—Jš=™=Jš6™6J˜Jšœ,˜@Jšœ žœ˜'Jšœ žœ˜J˜š Ÿœžœžœžœžœ˜>Jšžœžœžœ˜Jšžœžœ˜6šžœ˜J˜9J˜—J˜J˜—šŸ œžœžœžœ˜7Jšžœžœžœ˜Jšžœžœ˜CJšžœ7˜;J˜J˜—Jš,™,J˜Jšœžœ˜J˜š Ÿ œžœžœ žœ$žœ˜TJšœžœ3žœ˜TJ˜(Jšœ2žœ ˜FJ˜J˜—Jš™J˜šŸœžœžœ˜"J˜J˜—Jšžœ˜J˜—…—xž