Титульная страница   Пространства имен   Иерархия классов   Алфавитный указатель   Классы   Файлы   Члены пространства имен   Члены классов   Члены файла  

findtextimpl.cpp

См. документацию.
00001 /*
00002  * Copyright (C) Sergey P. Derevyago, 2003-2004.
00003  *
00004  * Permission to copy, use, modify, sell and distribute this software is granted
00005  * provided this copyright notice appears in all copies.
00006  * This software is provided "as is" without express or implied warranty, and
00007  * with no claim as to its suitability for any purpose.
00008  *
00009  */
00010 
00015 #include "findtext.hpp"
00016 #include <string.h>
00017 #include <errno.h>
00018 #include "findfile.hpp"
00019 #include "textfinder.hpp"
00020 #include "autofile.hpp"
00021 #include "stringbuf.hpp"
00022 
00023 using namespace std;
00024 
00025 namespace {
00026 
00028  struct AutoFlag {
00030         bool& flag;
00031 
00033         AutoFlag(bool& f) : flag(f) {}
00035         ~AutoFlag() { flag=0; }
00036  };
00037 
00038  struct OpenCloseSender;
00039 
00043  class FindTextImpl : public FindText, FindFileCallback, Publisher<FoundMsg>,
00044    Publisher<InfoMsg>, Publisher<ErrorMsg> {
00045        friend struct OpenCloseSender;
00046 
00048        bool running;
00050        bool shouldStop;
00052        sh_ptr<TextFinder> txtFnd;
00053 
00054        virtual void search(const std::string& dir, bool recur,
00055          const std::string& mask, const std::string& text);
00056 
00057        virtual void stopSearch();
00058 
00059        virtual Publisher<FoundMsg>& foundPub();
00060 
00061        virtual Publisher<InfoMsg>& infoPub();
00062 
00063        virtual Publisher<ErrorMsg>& errorPub();
00064 
00070        virtual bool found(const std::string& fileName);
00071 
00076        bool readLine(FILE* f, string& str, const std::string& file);
00077 
00078   public:
00082        FindTextImpl() : running(0), shouldStop(0) {}
00083  };
00084 
00089  struct OpenCloseSender {
00091         FindTextImpl& fti;
00093         const string& file;
00094 
00096         OpenCloseSender(FindTextImpl& fti_, const string& file_) : fti(fti_),
00097           file(file_)
00098         {
00099          fti.Publisher<InfoMsg>::send(InfoMsg(fti, InfoMsg::opened, file));
00100         }
00101 
00103         ~OpenCloseSender()
00104         {
00105          fti.Publisher<InfoMsg>::send(InfoMsg(fti, InfoMsg::closed, file));
00106         }
00107  };
00108 
00109  void FindTextImpl::search(const std::string& dir, bool recur,
00110          const std::string& mask, const std::string& text)
00111  {
00112   try {
00113       if (running)
00114          throw newCException(_FLINE_, "search() already running");
00115       running=1;
00116       
00117       AutoFlag autoRunning(running);
00118       AutoFlag autoShouldStop(shouldStop);
00119 
00120       txtFnd=Factory::newTextFinder(text);
00121 
00122       sh_ptr<FindFile> ff=Factory::newFindFile();
00123       ff->find(dir, recur, mask, *this);
00124   }
00125   catch (...) {
00126         throw newCException(_FLINE_, "Can't search", toCException(_FLINE_));
00127   }
00128  }
00129 
00130  void FindTextImpl::stopSearch()
00131  {
00132   if (!running) throw newCException(_FLINE_, "search() isn't running");
00133   shouldStop=1;
00134  }
00135 
00136  Publisher<FoundMsg>& FindTextImpl::foundPub()
00137  {
00138   return *this;
00139  }
00140 
00141  Publisher<InfoMsg>& FindTextImpl::infoPub()
00142  {
00143   return *this;
00144  }
00145 
00146  Publisher<ErrorMsg>& FindTextImpl::errorPub()
00147  {
00148   return *this;
00149  }
00150 
00151  bool FindTextImpl::found(const std::string& fileName)
00152  {
00153   try {
00154       if (shouldStop) return 0;
00155 
00156       AutoFILE f(fopen(fileName.c_str(), "r"));
00157       if (!f.get()) {
00158          Publisher<ErrorMsg>::send(ErrorMsg(*this, StringBuf("Can't open \"")+
00159            fileName+"\": "+strerror(errno)));
00160          return 1;
00161       }
00162 
00163       OpenCloseSender ocs(*this, fileName);
00164 
00165       string str;
00166       str.reserve(1024);
00167 
00168       for (int lineNum=1; readLine(f.get(), str, fileName); lineNum++) {
00169           if (txtFnd->findIn(str))
00170              Publisher<FoundMsg>::send(FoundMsg(*this, fileName, lineNum, str));
00171       }
00172 
00173       return 1;
00174   }
00175   catch (...) {
00176         throw newCException(_FLINE_, "Can't process \""+fileName+"\"", 
00177           toCException(_FLINE_));
00178   }
00179  }
00180 
00181  bool FindTextImpl::readLine(FILE* f, string& str, const std::string& file)
00182  {
00183   if (feof(f)) return 0;
00184   str.clear();
00185   
00186   for (int ch; ; ) {
00187       switch (ch=fgetc(f)) {
00188              case EOF: {
00189                   if (ferror(f)) {
00190                      Publisher<ErrorMsg>::send(ErrorMsg(*this,
00191                        StringBuf("Can't read from \"")+file+"\": "+
00192                        strerror(errno)));
00193                      return 0;
00194                   }
00195 
00196                   return (str.size()) ? 1 : 0;
00197              }
00198              case '\n': return 1;
00199              default: {
00200                       str.push_back(ch);
00201                       break;
00202              }
00203       }
00204   }
00205  }
00206 
00207 }
00208 
00209 sh_ptr<FindText> Factory::newFindText()
00210 {
00211  try { return sh_ptr<FindText>(new FindTextImpl); }
00212  catch (...) {
00213        throw newCException(_FLINE_, "Can't create FindTextImpl object",
00214          toCException(_FLINE_));
00215  }
00216 }

Документация по ftext. Последние изменения: Sat Mar 20 17:58:15 2004. Создано системой doxygen1.3