/***************************************************************************** * cleaner.h * * A set of classes to facilitate easy, automatic resource * disposal and handling. * * Toggle if(true) / if(false) in CleanerDebug::msg to * enable / disable debug output. * * Usage Example * ------------- * * #include * * #include * #include * #include * * #include "cleaner.h" * * using std::string; * using std::cout; * using std::endl; * using std::vector; * * class Foo * { * public: virtual ~Foo() { cout << "~Foo()" << endl; } * }; * * class Bar : public Foo * { * public: ~Bar() { cout << "~Bar()" << endl; } * }; * * int main() * { * Cleaner cleaner; * * FILE *f = fopen(__FILE__, "r"); * * if(!f) * { * cout << "Could not open file: [" << __FILE__ << "]" << endl; * return(1); * } * * int fileIndex = cleaner.addFile(f); * * int *iPtr = new int; * * cleaner.addPointer(iPtr); * * double *dArray = new double[100]; * * cleaner.addArray(dArray); * * vector v; * * v.push_back(new Bar()); * v.push_back(new Bar()); * v.push_back(new Bar()); * * cleaner.addPointerVector(v); * * if(false) * { * if(!cleaner.removeEntry(fileIndex)) * { * cout << "Invalid entry index: [" << fileIndex << "]" << endl; * } * else * { * cout << "fclose(" << f << ")" << endl; * fclose(f); * } * } * * return(0); * } * * Example Output * -------------- * * Cleaner() * ~Cleaner() => delete(004204B0) * ~FileCleanerEntry() => fclose(00418738) * ~CleanerEntry() * ~Cleaner() => delete(00420480) * ~PointerCleanerEntry() => delete(0040828F) * ~CleanerEntry() * ~Cleaner() => delete(004204A0) * ~ArrayCleanerEntry() => delete [] (003208DC) * ~CleanerEntry() * ~Cleaner() => delete(004202E0) * ~PointerVectorCleanerEntry() => delete(00420470) * ~Bar() * ~Foo() * ~PointerVectorCleanerEntry() => delete(00420430) * ~Bar() * ~Foo() * ~PointerVectorCleanerEntry() => delete(00420440) * ~Bar() * ~Foo() * ~CleanerEntry() * *****************************************************************************/ #ifndef _CLEANER_H_ # define _CLEANER_H_ #include #include #include #include #include using std::string; using std::ostringstream; using std::vector; using std::cout; using std::endl; // -------------------------------- // class CleanerDebug // -------------------------------- class CleanerDebug { public: static void msg(const string &theMessage) { if(true) { cout << theMessage << endl; } } }; // -------------------------------- // class CleanerEntry // -------------------------------- class CleanerEntry { public: virtual ~CleanerEntry() { CleanerDebug::msg("~CleanerEntry()"); } }; // -------------------------------- // class FileCleanerEntry // -------------------------------- class FileCleanerEntry : public CleanerEntry { public: FileCleanerEntry(FILE *f) : mF(f) { } ~FileCleanerEntry() { ostringstream out; out << "~FileCleanerEntry() => fclose(" << mF << ")"; CleanerDebug::msg(out.str()); fclose(mF); } private: FILE *mF; }; // -------------------------------- // class PointerCleanerEntry // -------------------------------- template class PointerCleanerEntry : public CleanerEntry { public: PointerCleanerEntry(T *ptr) : mPtr(ptr) { } ~PointerCleanerEntry() { ostringstream out; out << "~PointerCleanerEntry() => delete(" << mPtr << ")"; CleanerDebug::msg(out.str()); delete(mPtr); mPtr = 0; } private: T *mPtr; }; // -------------------------------- // class ArrayCleanerEntry // -------------------------------- template class ArrayCleanerEntry : public CleanerEntry { public: ArrayCleanerEntry(T *array) { } ~ArrayCleanerEntry() { ostringstream out; out << "~ArrayCleanerEntry() => delete [] (" << mArray << ")"; CleanerDebug::msg(out.str()); delete [] mArray; mArray = 0; } private: T *mArray; }; // -------------------------------- // class PointerVectorCleanerEntry // -------------------------------- template class PointerVectorCleanerEntry : public CleanerEntry { public: PointerVectorCleanerEntry(vector &pointerVector) { for(int n = pointerVector.size(), i = 0; i < n; i ++) mPointerVector.push_back(pointerVector[i]); } ~PointerVectorCleanerEntry() { for(int n = mPointerVector.size(), i = 0; i < n; i ++) { ostringstream out; out << "~PointerVectorCleanerEntry() => delete(" << mPointerVector[i] << ")"; CleanerDebug::msg(out.str()); delete(mPointerVector[i]); mPointerVector[i] = 0; } } private: vector mPointerVector; }; // -------------------------------- // class Cleaner // -------------------------------- class Cleaner { public: Cleaner() { CleanerDebug::msg("Cleaner()"); } ~Cleaner() { for(int n = mEntries.size(), i = 0; i < n; i ++) { ostringstream out; out << "~Cleaner() => delete(" << mEntries[i] << ")"; CleanerDebug::msg(out.str()); delete(mEntries[i]); mEntries[i] = 0; } mEntries.clear(); } int addEntry(CleanerEntry *theEntry) { mEntries.push_back(theEntry); return(mEntries.size() - 1); } int addFile(FILE *f) { return(addEntry(new FileCleanerEntry(f))); } template int addPointer(T *pointer) { return( addEntry(new PointerCleanerEntry(pointer)) ); } template int addArray(T *array) { return( addEntry(new ArrayCleanerEntry(array)) ); } template int addPointerVector(vector &pointerVector) { return( addEntry(new PointerVectorCleanerEntry(pointerVector)) ); } bool removeEntry(int number) { int n = mEntries.size(); if(number < 0 || number >= n) return(false); vector mNewEntries; for(int i = 0; i < n; i ++) if(i != number) mNewEntries.push_back(mEntries[i]); mEntries = mNewEntries; return(true); } private: vector mEntries; Cleaner(const Cleaner &); Cleaner &operator =(const Cleaner &); }; #endif