SECTION "StringStreams"

GET "LibHdr"

GET "b.IOHdr"

MANIFEST {
   OSFileReadCatalogue	  = #x05;
   OSFileLoadFile	  = #xFF;
   OSFileSaveFile	  = #x00 };

LET BufferRdch(channel) = VALOF
{  LET buffer, bufferPointer, bufferCount =
      cis!s.buffer.address, cis!s.buffer.pointer, cis!s.buffer.count;
   LET c = ?;
   IF bufferPointer>=bufferCount THEN RESULTIS EndStreamCh;
   c := 0%(buffer+bufferPointer);
   cis!s.buffer.pointer := bufferPointer+1;
   RESULTIS c }

AND BufferWrch(ch, channel) BE
{  LET bufferSize, buffer, bufferCount=
      cos!s.buffer.size, cos!s.buffer.address, cos!s.buffer.count;
   IF bufferCount>=bufferSize THEN {
      WriteF("Stream %x6 full: buffer %x6 size %n count %n*n",
	     cos*4, buffer, bufferSize, bufferCount);
      Stop() };
   0%(buffer+bufferCount) := ch;
   cos!s.buffer.count := bufferCount+1 }

LET MakeStringStream(direction, arg, size) = VALOF
{  LET StringWrCh(ch, channel) BE
   {  BufferWrch(ch, channel);
      0%(cos!s.buffer.address-1) := cos!s.buffer.count };
   LET stream = MakeNewStream("string:",
			      s.is.store.bits,
			      direction,
			      BufferRdch,
			      StringWrch);
   stream!s.buffer.address := arg;
   stream!s.buffer.size := size;
   stream!s.buffer.pointer := 0;
   TEST direction=s.op.input THEN
      stream!s.buffer.count := size
   ELSE {
      stream!s.buffer.count := 0;
      0%(arg-1) := 0 };
   RESULTIS stream }

AND FindStringInput(s, n) =
   MakeStringStream(s.op.input, s, n)

AND StringF(format, a, b, c, d, e, f, g, h, i, j, k) = VALOF
{  LET o = Output();
   LET buffer = GetVec(256/BytesPerWord);
   LET s, res = ?, ?;
   s := MakeStringStream(s.op.output, buffer*BytesPerWord+1, 255);
   SelectOutput(s);
   WriteF(format, a, b, c, d, e, f, g, h, i, j, k);
   EndWrite();
   SelectOutput(o);
   res := GetVec((buffer%0)/4);
   CopyString(buffer, res);
   FreeVec(buffer);
   RESULTIS res }

AND CopyString(source, dest) BE
   MoveWords(1, (source%0)/4+1, source, dest)

AND FindFileInput(name) = VALOF
{  LET FileEndRead(stream) BE
   {  FreeVec((stream!s.buffer.address)/BytesPerWord);
      EndStream(stream) }
   AND FileUnread() BE
   {  LET bufferPointer = cis!s.buffer.pointer;
      IF bufferPointer>0 THEN
	 cis!s.buffer.pointer := bufferPointer-1 };

   LET parameterBlock = VEC 3;
   LET result = OSFile(OSFileReadCatalogue, name, parameterBlock);
   LET buffer, filelength = ?, ?;

   IF result~=1 THEN RESULTIS 0;
   fileLength := parameterBlock!2;
   buffer := GetVec(fileLength/BytesPerWord)*BytesPerWord;
   IF buffer=0 THEN RESULTIS FindInput(name);

   parameterBlock!0 := buffer;
   parameterBlock!1 := 0;
   parameterBlock!2 := 0;
   parameterBlock!3 := 0;
   result := OSFile(OSFileLoadFile, name, parameterBlock);
   IF result2~=0 THEN RESULTIS 0;

   result := MakeNewStream(name,
			   s.is.store.bits,
			   s.op.input,
			   BufferRdch,
			   BufferWrch);

   result!s.buffer.address := buffer;
   result!s.buffer.size := filelength;
   result!s.buffer.count := filelength;
   result!s.buffer.pointer := 0;
   result!s.unreader := FileUnread;
   result!s.endreader := FileEndRead;
   RESULTIS result }

AND FindFileOutput(name, size) = VALOF
{  LET FileEndWrite(stream) BE
   {  LET parameterBlock = VEC 3;
      parameterBlock!0 := 0;
      parameterBlock!1 := 0;
      parameterBlock!2 := stream!s.buffer.address;
      parameterBlock!3 := parameterBlock!0+stream!s.buffer.count;
      OSFile(OSFileSaveFile, @(stream!s.name), parameterBlock);
      FreeVec((stream!s.buffer.address)/BytesPerWord);
      EndStream(stream) };
   LET buffer = GetVec(size)*BytesPerWord;
   LET result = ?;

   IF buffer=0 THEN RESULTIS FindOutput(name);

   result := MakeNewStream(name,
			   s.is.store.bits,
			   s.op.output,
			   BufferRdch,
			   BufferWrch);

   result!s.buffer.address := buffer;
   result!s.buffer.size := size;
   result!s.buffer.count := 0;
   result!s.buffer.pointer := 0;
   result!s.endwriter := FileEndWrite;
   RESULTIS result }
