Skip to content

Commit 2077365

Browse files
committed
added FileStreamBuffered to reduce the amount of fgetc() calls [skip ci]
1 parent efa845d commit 2077365

File tree

1 file changed

+75
-1
lines changed

1 file changed

+75
-1
lines changed

simplecpp.cpp

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ using mode_t = unsigned short;
6060
# include <sys/types.h>
6161
#endif
6262

63+
#ifdef __GNUC__
64+
# define unlikely(x) __builtin_expect(!!(x), 0)
65+
#else
66+
# define unlikely(x) (x)
67+
#endif
68+
6369
static bool isHex(const std::string &s)
6470
{
6571
return s.size()>2 && (s.compare(0,2,"0x")==0 || s.compare(0,2,"0X")==0);
@@ -469,6 +475,74 @@ class FileStream : public simplecpp::TokenList::Stream {
469475
int lastStatus{};
470476
};
471477

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

474548
simplecpp::TokenList::TokenList(std::istream &istr, std::vector<std::string> &filenames, const std::string &filename, OutputList *outputList)
@@ -489,7 +563,7 @@ simplecpp::TokenList::TokenList(const std::string &filename, std::vector<std::st
489563
: frontToken(nullptr), backToken(nullptr), files(filenames)
490564
{
491565
try {
492-
FileStream stream(filename, filenames);
566+
FileStreamBuffered stream(filename, filenames);
493567
readfile(stream,filename,outputList);
494568
} catch (const simplecpp::Output & e) { // TODO handle extra type of errors
495569
outputList->push_back(e);

0 commit comments

Comments
 (0)