Skip to content

Commit 8e965a9

Browse files
committed
Improved cached macro performance.
1 parent fa3a1dc commit 8e965a9

File tree

8 files changed

+296
-64
lines changed

8 files changed

+296
-64
lines changed

source/base/fileinputoutput.cpp

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -383,21 +383,36 @@ POV_LONG GetFileLength(const Path& p)
383383
return result;
384384
}
385385

386-
bool IMemStream::read(void *buffer, size_t count)
386+
bool IMemStream::read(void *buffer, size_t maxCount)
387387
{
388-
if (!fail)
388+
size_t count = 0;
389+
390+
if (fail)
391+
return false;
392+
393+
unsigned char* p = reinterpret_cast<unsigned char*>(buffer);
394+
395+
if (maxCount == 0)
396+
return true;
397+
398+
// read from unget buffer first
399+
if (mUngetBuffer != EOF)
389400
{
390-
if ((count <= size) && (pos <= size-count))
391-
{
392-
memcpy(buffer,&start[pos],count);
393-
pos += count;
394-
}
395-
else
396-
{
397-
fail = true;
398-
}
401+
*(p++) = (unsigned char)mUngetBuffer;
402+
mUngetBuffer = EOF;
403+
if (++count == maxCount)
404+
return true;
399405
}
400-
return !fail;
406+
407+
size_t copyFromBuffer = min(maxCount-count, size-pos);
408+
memcpy(p, &(start[pos]), copyFromBuffer);
409+
count += copyFromBuffer;
410+
pos += copyFromBuffer;
411+
if (count == maxCount)
412+
return true;
413+
414+
fail = true;
415+
return false;
401416
}
402417

403418
int IMemStream::Read_Byte()
@@ -407,6 +422,11 @@ int IMemStream::Read_Byte()
407422
{
408423
v = EOF;
409424
}
425+
else if (mUngetBuffer != EOF)
426+
{
427+
v = mUngetBuffer;
428+
mUngetBuffer = EOF;
429+
}
410430
else
411431
{
412432
if (pos < size)
@@ -419,14 +439,12 @@ int IMemStream::Read_Byte()
419439

420440
bool IMemStream::UnRead_Byte(int c)
421441
{
422-
if (!fail)
423-
{
424-
if (pos > 0)
425-
pos--;
426-
else
427-
fail = true;
428-
}
429-
return !fail;
442+
if (fail)
443+
return false;
444+
445+
mUngetBuffer = c;
446+
447+
return true;
430448
}
431449

432450
bool IMemStream::getline(char *s,size_t buflen)
@@ -438,13 +456,19 @@ bool IMemStream::getline(char *s,size_t buflen)
438456

439457
POV_LONG IMemStream::tellg() const
440458
{
441-
return formalStart + pos;
459+
size_t physicalPos = pos;
460+
if (mUngetBuffer != EOF)
461+
++physicalPos;
462+
return formalStart + physicalPos;
442463
}
443464

444465
bool IMemStream::seekg(POV_LONG posi, unsigned int whence)
445466
{
446467
if(!fail)
447468
{
469+
// Any seek operation renders the unget buffer's content obsolete.
470+
mUngetBuffer = EOF;
471+
448472
switch(whence)
449473
{
450474
case seek_set:

source/base/fileinputoutput.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ class IMemStream : public IStream
185185
size_t pos;
186186
POV_LONG formalStart;
187187
const unsigned char * start;
188+
int mUngetBuffer;
188189
};
189190

190191
class OStream : public IOBase

source/base/textstream.cpp

Lines changed: 163 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,16 @@
4949
namespace 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+
272423
OTextStream::OTextStream(const UCS2 *sname, unsigned int stype, bool append)
273424
{
274425
if(sname == NULL)

0 commit comments

Comments
 (0)