/* * @(#) f_iter.cpp - Text file iterator demo. * (c) 1996 Ivan Maidanski http://ivmai.chat.ru * Freeware program source. All rights reserved. ** * Language: ISO/ANSI C++ * Tested with: Watcom C++ v10.0 * Last modified: 1996-05-24 09:05:00 GMT+04:00 */ #include #include #include #include typedef enum {FALSE,TRUE} BOOL; class TString { public: TString(const char *AStr="",int BlockSize=16); TString(char Ch,int BlockSize=1) : Block(BlockSize) { Count=(Block+1)/Block; Str=new char[Block*Count];Str[0]=Ch;Str[1]='\0'; }; TString(const TString& String) : Block(String.Block), Count(String.Count) { Str=new char[Block*Count]; strcpy(Str,String.Str); }; ~TString() { delete[] Str; }; operator const char* () const { return (Str); }; TString& operator= (const TString& String); TString& operator+= (const TString& String); BOOL operator== (const TString& String) const { return (strcmp(Str,String.Str)? FALSE : TRUE); }; BOOL operator!= (const TString& String) const { return (strcmp(Str,String.Str)? TRUE : FALSE); }; char operator[] (int Pos) const { return ((Pos>=0 && Pos0) { Cnt=strlen(Str)-Cnt; if (Cnt>=0) Str[Cnt]='\0'; } }; friend istream& operator>> (istream& Stream,TString& String); private: char* Str; int Count; const int Block; }; TString::TString(const char *AStr,int BlockSize) : Block(BlockSize) { Count=(strlen(AStr)+Block)/Block; Str=new char[Block*Count]; strcpy(Str,AStr); }; TString& TString::operator= (const TString& String) { delete[] Str; Count=(strlen(String.Str)+Block)/Block; Str=new char[Block*Count]; strcpy(Str,String.Str); return (*this); }; TString& TString::operator+= (const TString& String) { int OldCount=Count; Count=(strlen(Str)+strlen(String.Str)+Block)/Block; if (OldCount> (istream& Stream,TString& String) { char Ch; String=""; while (!Stream.eof() && (Stream.read(&Ch,1), Ch!='\n')) String+=Ch; return (Stream); }; class TFile { public: TFile(const TString&) { err=0; }; TFile(const TFile&) { err=0; }; virtual ~TFile() {}; virtual char Read()=0; virtual void Seek(long APos=0)=0; virtual long Where()=0; virtual long Length()=0; int Error() const { return (err); }; protected: int err; // 0 - no error, -1 - end of file, -2 - cannot open }; class TOpenedFile : public TFile { public: TOpenedFile(const TString& AName) : TFile(AName), Name(AName) { fid=open(AName,O_RDONLY || O_TEXT); err=(fid<0)? -2 : 0; }; TOpenedFile(const TOpenedFile& AFile) : TFile(AFile), Name(AFile.Name) { fid=open(Name,O_RDONLY || O_TEXT); err=(fid<0)? -2 : 0; }; virtual ~TOpenedFile() { close(fid); }; virtual char Read() { char Ch='\0'; err=(read(fid,&Ch,1)<1)? -1 : 0; return (Ch); }; virtual void Seek(long APos=0) { err=(lseek(fid,APos,0)<0)? -2 : 0; }; virtual long Where() { err=0; return(tell(fid)); }; virtual long Length(); private: const TString Name; int fid; }; long TOpenedFile::Length() { long Pos=tell(fid); long Len=lseek(fid,0,2); err=(lseek(fid,Pos,0)<0)? -2 : 0; return (Len); }; class TClosedFile : public TFile { public: TClosedFile(const TString& AName) : TFile(AName), Name(AName) { Pos=0; }; TClosedFile(const TClosedFile& AFile) : TFile(AFile), Name(AFile.Name) { Pos=0; }; virtual ~TClosedFile() {}; virtual char Read(); virtual void Seek(long APos=0) { err=0; Pos=APos; }; virtual long Where() { err=0; return (Pos); }; virtual long Length(); private: const TString Name; long Pos; }; char TClosedFile::Read() { char Ch='\0'; int fid=open(Name,O_RDONLY || O_TEXT); err=(fid<0)? -2 : 0; if (!err) { lseek(fid,Pos,0); err=(read(fid,&Ch,1)<1)? -1 : 0; if (!err) Pos=tell(fid); close(fid); } return (Ch); }; long TClosedFile::Length() { int fid=open(Name,O_RDONLY || O_TEXT); long Len=lseek(fid,0,2); err=(fid<0)? -2 : 0; if (!err) close(fid); return (Len); }; class TFileIter { public: TFileIter(TFile* AFile) : File(AFile) {}; TFileIter(const TFileIter& AFileIter) : File(AFileIter.File) {}; virtual ~TFileIter() {}; virtual BOOL Next(); TString Get() const { return (Value); }; void Reset() { File->Seek(); }; int Error() const { if (File->Error()!=-1) return (File->Error()); else return (0); }; protected: TFile* File; TString Value; }; BOOL TFileIter::Next() { Value=File->Read(); return (File->Error()<0? FALSE : TRUE); }; class TSubORFileIter : public TFileIter { public: TSubORFileIter(TFile* AFile,const TString& ADelimiter=" .,;\t\n") : TFileIter(AFile), Delimiter(ADelimiter) {}; virtual BOOL Next(); private: const TString Delimiter; }; BOOL TSubORFileIter::Next() { char Ch; Value=""; while (Ch=File->Read(), !File->Error() && strchr(Delimiter,Ch)); while (!File->Error() && !strchr(Delimiter,Ch)) { Value+=Ch; Ch=File->Read(); } return ((Value==TString("") && File->Error()<0)? FALSE : TRUE); }; class TSubANDFileIter : public TFileIter { public: TSubANDFileIter(TFile* AFile,const TString& ADelimiter="\n") : TFileIter(AFile), Delimiter(ADelimiter) {}; virtual BOOL Next(); private: const TString Delimiter; }; BOOL TSubANDFileIter::Next() { char Ch; int Cnt=0; Value=""; while (Ch=File->Read(), !File->Error()) { Value+=Ch; if (Delimiter[Cnt]==Ch) Cnt++; else Cnt=0; if (Cnt==strlen(Delimiter)) { Value.Trunc(Cnt); return (TRUE); } } return ((Value==TString("") && File->Error()<0)? FALSE : TRUE); }; int main(int,char**) { TString Name; cout << "Text file iterator classes demo.\n" << " Enter file name: "; cin >> Name; TString Mode; cout << " Enter file access mode (Opened,Closed)? "; cin >> Mode; TFile* File; if (Mode[0]=='o') File=new TOpenedFile(Name); else File=new TClosedFile(Name); cout << " Enter iterator type (Symbol,Line,ORString,ANDString)? "; cin >> Mode; TFileIter* Iter; if (Mode[0]=='o' || Mode[0]=='a') { TString Delimiter; cout << " Enter delimiter string: "; cin >> Delimiter; if (Mode[0]=='o') if (Delimiter!=TString("")) { Delimiter+="\n"; Iter=new TSubORFileIter(File,Delimiter); } else Iter=new TSubORFileIter(File); else Iter=new TSubANDFileIter(File,Delimiter); } else if (Mode[0]=='l') Iter=new TSubANDFileIter(File); else Iter=new TFileIter(File); cout << " Result:\n"; while (Iter->Next()) cout << Iter->Get() << "\n"; delete Iter; delete File; return (0); }