4949namespace pov_base
5050{
5151
52- ITextStream::ITextStream (const UCS2 *sname, unsigned int stype)
52+ ITextStream::ITextStream () :
53+ lineno (1 )
54+ {
55+ }
56+
57+ ITextStream::~ITextStream ()
58+ {
59+ }
60+
61+ IBufferedTextStream::IBufferedTextStream (const UCS2 *sname, unsigned int stype)
5362{
5463 if (sname == NULL )
5564 throw POV_EXCEPTION_CODE (kParamErr );
@@ -59,7 +68,6 @@ ITextStream::ITextStream(const UCS2 *sname, unsigned int stype)
5968 throw POV_EXCEPTION (kCannotOpenFileErr , string (" Cannot open file '" ) + UCS2toASCIIString (sname) + " ' for input." );
6069
6170 filename = UCS2String (sname);
62- lineno = 1 ;
6371 bufferoffset = 0 ;
6472 maxbufferoffset = 0 ;
6573 filelength = 0 ;
@@ -73,7 +81,7 @@ ITextStream::ITextStream(const UCS2 *sname, unsigned int stype)
7381 RefillBuffer ();
7482}
7583
76- ITextStream::ITextStream (const UCS2 *sname, IStream *sstream, POV_LONG initialLine)
84+ IBufferedTextStream::IBufferedTextStream (const UCS2 *sname, IStream *sstream, POV_LONG initialLine)
7785{
7886 if (sname == NULL )
7987 throw POV_EXCEPTION_CODE (kParamErr );
@@ -96,13 +104,13 @@ ITextStream::ITextStream(const UCS2 *sname, IStream *sstream, POV_LONG initialLi
96104 RefillBuffer ();
97105}
98106
99- ITextStream ::~ITextStream ()
107+ IBufferedTextStream ::~IBufferedTextStream ()
100108{
101109 delete stream;
102110 stream = NULL ;
103111}
104112
105- int ITextStream ::getchar ()
113+ int IBufferedTextStream ::getchar ()
106114{
107115 int chr = 0 ;
108116
@@ -146,27 +154,28 @@ int ITextStream::getchar()
146154 return chr;
147155}
148156
149- void ITextStream ::ungetchar (int chr)
157+ void IBufferedTextStream ::ungetchar (int chr)
150158{
151159 ungetbuffer = chr;
152160 if (chr == ' \n ' )
153161 lineno--;
154162}
155163
156- bool ITextStream ::eof () const
164+ bool IBufferedTextStream ::eof () const
157165{
158166 if (ungetbuffer != EOF)
159167 return false ;
160168 if (bufferoffset >= maxbufferoffset)
169+ // NB this relies on RefillBuffer being called by each read operation that exhausts the buffer
161170 return true ;
162171 return stream->eof ();
163172}
164173
165- bool ITextStream ::seekg (ITextStream::FilePos fp)
174+ bool IBufferedTextStream ::seekg (ITextStream::FilePos fp)
166175{
167176 bool result = true ;
168177
169- if ((fp.offset < curpos) && ((curpos - fp.offset ) < maxbufferoffset))
178+ if ((fp.offset < curpos) && ((curpos - fp.offset ) <= maxbufferoffset))
170179 {
171180 bufferoffset = maxbufferoffset - (curpos - fp.offset );
172181 lineno = fp.lineno ;
@@ -194,7 +203,7 @@ bool ITextStream::seekg(ITextStream::FilePos fp)
194203 return result;
195204}
196205
197- ITextStream::FilePos ITextStream ::tellg () const
206+ ITextStream::FilePos IBufferedTextStream ::tellg () const
198207{
199208 FilePos fp;
200209
@@ -207,7 +216,7 @@ ITextStream::FilePos ITextStream::tellg() const
207216 return fp;
208217}
209218
210- bool ITextStream ::ReadRaw (unsigned char * buf, size_t size)
219+ bool IBufferedTextStream ::ReadRaw (unsigned char * buf, size_t size)
211220{
212221 unsigned char * p = buf;
213222 size_t remain = size;
@@ -251,7 +260,7 @@ bool ITextStream::ReadRaw(unsigned char* buf, size_t size)
251260 return false ;
252261}
253262
254- void ITextStream ::RefillBuffer ()
263+ void IBufferedTextStream ::RefillBuffer ()
255264{
256265 if (bufferoffset < maxbufferoffset)
257266 {
@@ -269,6 +278,148 @@ void ITextStream::RefillBuffer()
269278 curpos = stream->tellg () ;
270279}
271280
281+ IMemTextStream::IMemTextStream (const UCS2 *formalName, unsigned char * data, size_t size, const FilePos& formalStart)
282+ {
283+ if (formalName == NULL )
284+ throw POV_EXCEPTION_CODE (kParamErr );
285+ if (data == NULL )
286+ throw POV_EXCEPTION_CODE (kParamErr );
287+
288+ buffer = data;
289+ filename = UCS2String (formalName);
290+ lineno = formalStart.lineno ;
291+ bufferoffset = 0 ;
292+ maxbufferoffset = size;
293+ ungetbuffer = EOF;
294+ mFormalStart = formalStart.offset ;
295+ fail = false ;
296+ }
297+
298+ IMemTextStream::~IMemTextStream ()
299+ {
300+ }
301+
302+ int IMemTextStream::getchar ()
303+ {
304+ int chr = 0 ;
305+
306+ if (ungetbuffer != EOF)
307+ {
308+ chr = ungetbuffer;
309+ ungetbuffer = EOF;
310+ }
311+ else
312+ {
313+ if (bufferoffset >= maxbufferoffset)
314+ {
315+ chr = EOF;
316+ fail = true ;
317+ }
318+ else
319+ {
320+ chr = buffer[bufferoffset];
321+ bufferoffset++;
322+ }
323+ }
324+
325+ if (chr == 10 )
326+ {
327+ if ((bufferoffset < maxbufferoffset) && (buffer[bufferoffset] == 13 ))
328+ bufferoffset++;
329+ chr = ' \n ' ;
330+ lineno++;
331+ }
332+ else if (chr == 13 )
333+ {
334+ if ((bufferoffset < maxbufferoffset) && (buffer[bufferoffset] == 10 ))
335+ bufferoffset++;
336+ chr = ' \n ' ;
337+ lineno++;
338+ }
339+
340+ return chr;
341+ }
342+
343+ void IMemTextStream::ungetchar (int chr)
344+ {
345+ ungetbuffer = chr;
346+ if (chr == ' \n ' )
347+ lineno--;
348+ }
349+
350+ bool IMemTextStream::eof () const
351+ {
352+ if (ungetbuffer != EOF)
353+ return false ;
354+ return fail;
355+ }
356+
357+ bool IMemTextStream::seekg (ITextStream::FilePos fp)
358+ {
359+ fail = false ;
360+
361+ if ((fp.offset < mFormalStart + maxbufferoffset) && (mFormalStart <= fp.offset ))
362+ {
363+ bufferoffset = fp.offset - mFormalStart ;
364+ lineno = fp.lineno ;
365+ ungetbuffer = EOF;
366+ }
367+ else
368+ {
369+ fail = true ;
370+ }
371+
372+ return !fail;
373+ }
374+
375+ ITextStream::FilePos IMemTextStream::tellg () const
376+ {
377+ FilePos fp;
378+
379+ fp.lineno = lineno;
380+ fp.offset = mFormalStart + bufferoffset;
381+
382+ if (ungetbuffer != EOF)
383+ fp.offset --;
384+
385+ return fp;
386+ }
387+
388+ bool IMemTextStream::ReadRaw (unsigned char * buf, size_t size)
389+ {
390+ if (fail)
391+ return false ;
392+
393+ unsigned char * p = buf;
394+ size_t remain = size;
395+
396+ if (remain == 0 )
397+ return true ;
398+
399+ // read from unget buffer first
400+ if (ungetbuffer != EOF)
401+ {
402+ *(p++) = (unsigned char )ungetbuffer;
403+ ungetbuffer = EOF;
404+ if (--remain == 0 )
405+ return true ;
406+ }
407+
408+ // next read from the regular buffer
409+ if (bufferoffset < maxbufferoffset)
410+ {
411+ size_t copyFromBuffer = min (remain, size_t (maxbufferoffset - bufferoffset));
412+ memcpy (p, &(buffer[bufferoffset]), copyFromBuffer);
413+ remain -= copyFromBuffer;
414+ bufferoffset += copyFromBuffer;
415+ p += copyFromBuffer;
416+ if (remain == 0 )
417+ return true ;
418+ }
419+
420+ return false ;
421+ }
422+
272423OTextStream::OTextStream (const UCS2 *sname, unsigned int stype, bool append)
273424{
274425 if (sname == NULL )
0 commit comments