@@ -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+
5864static 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+
469546simplecpp::TokenList::TokenList (std::vector<std::string> &filenames) : frontToken(nullptr ), backToken(nullptr ), files(filenames) {}
470547
471548simplecpp::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