Skip to content

Commit 19426ef

Browse files
committed
added FileStreamBuffered to reduce the amount of fgetc() calls [skip ci]
1 parent 69be83e commit 19426ef

File tree

1 file changed

+78
-1
lines changed

1 file changed

+78
-1
lines changed

simplecpp.cpp

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ using mode_t = unsigned short;
4848
# include <sys/types.h>
4949
#endif
5050

51+
#ifdef __GNUC__
52+
# define unlikely(x) __builtin_expect(!!(x), 0)
53+
#else
54+
# define unlikely(x) (x)
55+
#endif
56+
5157
static bool isHex(const std::string &s)
5258
{
5359
return s.size()>2 && (s.compare(0,2,"0x")==0 || s.compare(0,2,"0X")==0);
@@ -459,6 +465,77 @@ class FileStream : public simplecpp::TokenList::Stream {
459465
int lastStatus;
460466
};
461467

468+
class FileStreamBuffered : public simplecpp::TokenList::Stream {
469+
public:
470+
FileStreamBuffered(const std::string &filename, std::vector<std::string> &files)
471+
: file(fopen(filename.c_str(), "rb"))
472+
, lastStatus(0)
473+
, buf_len(0)
474+
, buf_idx(-1)
475+
{
476+
if (!file) {
477+
files.push_back(filename);
478+
throw simplecpp::Output(files, simplecpp::Output::FILE_NOT_FOUND, "File is missing: " + filename);
479+
}
480+
init();
481+
}
482+
483+
~FileStreamBuffered() {
484+
fclose(file);
485+
file = nullptr;
486+
}
487+
488+
virtual int get() {
489+
read_internal();
490+
return buf[buf_idx++];
491+
}
492+
virtual int peek() {
493+
read_internal();
494+
return buf[buf_idx];
495+
}
496+
virtual void unget() {
497+
--buf_idx;
498+
}
499+
virtual bool good() {
500+
return lastStatus != EOF;
501+
}
502+
503+
private:
504+
void read_internal() {
505+
// check if we are in the last chunk
506+
if (unlikely(buf_idx >= buf_len)) {
507+
if (buf_len != sizeof(buf)) {
508+
lastStatus = EOF;
509+
return;
510+
}
511+
}
512+
513+
if (unlikely(buf_idx == -1 || buf_idx == buf_len))
514+
{
515+
buf_idx = 0;
516+
buf_len = fread(buf, 1, sizeof(buf), file);
517+
if (buf_len == 0) {
518+
lastStatus = EOF;
519+
}
520+
else if (buf_len != sizeof(buf)) {
521+
if (ferror(file)) {
522+
// TODO: is this correct?
523+
lastStatus = EOF;
524+
}
525+
}
526+
}
527+
}
528+
529+
FileStreamBuffered(const FileStreamBuffered&);
530+
FileStreamBuffered &operator=(const FileStreamBuffered&);
531+
532+
FILE *file;
533+
int lastStatus;
534+
unsigned char buf[8192];
535+
int buf_len;
536+
int buf_idx;
537+
};
538+
462539
simplecpp::TokenList::TokenList(std::vector<std::string> &filenames) : frontToken(nullptr), backToken(nullptr), files(filenames) {}
463540

464541
simplecpp::TokenList::TokenList(std::istream &istr, std::vector<std::string> &filenames, const std::string &filename, OutputList *outputList)
@@ -479,7 +556,7 @@ simplecpp::TokenList::TokenList(const std::string &filename, std::vector<std::st
479556
: frontToken(nullptr), backToken(nullptr), files(filenames)
480557
{
481558
try {
482-
FileStream stream(filename, filenames);
559+
FileStreamBuffered stream(filename, filenames);
483560
readfile(stream,filename,outputList);
484561
} catch (const simplecpp::Output & e) { // TODO handle extra type of errors
485562
outputList->push_back(e);

0 commit comments

Comments
 (0)