@@ -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+
6369static 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+
472546simplecpp::TokenList::TokenList (std::vector<std::string> &filenames) : frontToken(nullptr ), backToken(nullptr ), files(filenames) {}
473547
474548simplecpp::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