Skip to content

Commit 54a5b51

Browse files
committed
added FileStreamBuffered to reduce the amount of fgetc() calls [skip ci]
1 parent 211f4c0 commit 54a5b51

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
@@ -55,6 +55,12 @@ using mode_t = unsigned short;
5555
# include <sys/types.h>
5656
#endif
5757

58+
#ifdef __GNUC__
59+
# define unlikely(x) __builtin_expect(!!(x), 0)
60+
#else
61+
# define unlikely(x) (x)
62+
#endif
63+
5864
static bool isHex(const std::string &s)
5965
{
6066
return s.size()>2 && (s.compare(0,2,"0x")==0 || s.compare(0,2,"0X")==0);
@@ -466,6 +472,77 @@ class FileStream : public simplecpp::TokenList::Stream {
466472
int lastStatus;
467473
};
468474

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

471548
simplecpp::TokenList::TokenList(std::istream &istr, std::vector<std::string> &filenames, const std::string &filename, OutputList *outputList)
@@ -486,7 +563,7 @@ simplecpp::TokenList::TokenList(const std::string &filename, std::vector<std::st
486563
: frontToken(nullptr), backToken(nullptr), files(filenames)
487564
{
488565
try {
489-
FileStream stream(filename, filenames);
566+
FileStreamBuffered stream(filename, filenames);
490567
readfile(stream,filename,outputList);
491568
} catch (const simplecpp::Output & e) { // TODO handle extra type of errors
492569
outputList->push_back(e);

0 commit comments

Comments
 (0)