<> <> <> <> <> <> <> <<>> DIRECTORY Basics USING [bytesPerWord], FS USING [defaultStreamOptions, OpenFile, StreamFromOpenFile, StreamOptions], IO USING [GetBlock, GetIndex, GetLength, STREAM], Rope, RopeEdit, RopeEditingAlloc, RopeEditingBLT, RopeFile USING [FromStream], RopeFrom, RopePrivate, RopeReader; RopeFromFileImpl: CEDAR MONITOR IMPORTS FS, IO, Rope, RopeEdit, RopeEditingAlloc, RopeEditingBLT, RopeFile, RopeFrom, RopePrivate EXPORTS RopeFrom SHARES Rope = BEGIN OPEN RopeFrom, RopePrivate; charsPerArray: NAT = RopeReader.charsPerArray; charsPerSpace: NAT = charsPerArray; spaceMin: NAT = charsPerSpace/2; -- put in shared array if less than 1/2 CharsArray: TYPE = RopeReader.CharsArray; Chars: TYPE = REF CharsArray; <<-- ***** Operations>> File: PUBLIC PROC [ file: FS.OpenFile, start: Offset _ 0, <> <<0 means first page after leader page>> length: Offset _ MaxLen, <> activate: BOOLEAN _ FALSE, <> fileLen: Offset _ MaxLen] <> RETURNS [rope: ROPE] = { stream: IO.STREAM _ NIL; options: FS.StreamOptions _ FS.defaultStreamOptions; options[tiogaRead] _ FALSE; -- include the formatting information options[closeFSOpenFileOnClose] _ FALSE; -- don't close the openFile stream _ FS.StreamFromOpenFile[ openFile: file, accessRights: $read, streamOptions: options, streamBufferParms: [vmPagesPerBuffer: 2, nBuffers: 1]]; RETURN[RopeFile.FromStream[stream: stream, start: start, len: length]]; }; Stream: PUBLIC PROC [stream: IO.STREAM, 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]; -- ensure proper evaluation order! front first back: ROPE = MakeRope[len-half]; -- then the back RETURN [Rope.Concat[front,back]]; }; nchars _ Short[len]; [chars, start, base] _ RopeEditingAlloc.AllocWords[ (nchars+(Basics.bytesPerWord-1))/Basics.bytesPerWord]; charloc _ start; UNTIL nchars = 0 DO nread: NAT; block.length _ 0; nread _ IO.GetBlock[self: stream, block: block, startIndex: 0, count: 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]; }; <<-- ***** Initialization>> StartRopeFromFile: PUBLIC PROC = { }; END.