[Bastion-cvs] bastion/src/save BastionInput.h,NONE,1.1 BastionOutput.h,NONE,1.1 Common.h,NONE,1.1 Co
Brought to you by:
jacek_kolodziej
|
From: Paweł Kęp. <t_...@us...> - 2004-07-14 22:37:32
|
Update of /cvsroot/bastion/bastion/src/save In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24353 Added Files: BastionInput.h BastionOutput.h Common.h Configuration.cpp Configuration.h FileManager.cpp FileManager.h ObjectCreator.cpp ObjectCreator.h SaveManager.cpp SaveManager.h Serializer.cpp Serializer.h Log Message: Witam wszystkich. Zeby nie bylo, ze sie obijam to wrzucam wstepna wersje savowania. Na razie tylko nowej klasy Configuration, ktora zawierac bedzie wszytskie informacje zachowywane o stanie naszej gry (np. ustawienia) pomiedzy kolejnymi uruchomieniami. Szczegoly juz wkrotce. Wszystko powinno sie komilowac, ale na razie nie mam za bardzo czasu zeby to sprawdzic. Bardzo ekstremalnie w swojej implemantacji uzywam polimorfizmu, co moze powodowac pewne problemy kiedy sami byscie chcieli wykozystac cos odemnie wiec na razie proponuje sie wstrzymac, az wszystko przetesuje. Pozdrawiam --- NEW FILE: Configuration.h --- #ifndef __CONFIGURATION_H__ #define __CONFIGURATION_H__ #include <string> #include "Serializer.h" #include "SaveManager.h" using namespace std; class FileManager; class Configuration { friend class ObjectCreator; static string DEFAULT_FILE_NAME; static Configuration *instance; SaveManager *saveManager; FileManager *fileManager; Configuration() { } void init(); void setFileManager(FileManager *fileManager); static void* create(); public : SaveManager* getSaveManager() const; FileManager* getFileManager() const; static Configuration* load(); void desc(Description *desc) { desc->create(typeid(this)); if (desc->check((void*) saveManager)) saveManager->desc(desc); } void save(); }; #endif --- NEW FILE: Common.h --- #ifndef __COMMON_H__ #define __COMMON_H__ #include <string> using namespace std; /** * Klasa wyjatku rzucana przez klasy implementujace BastionInput i * BastionOutput w przypadku wystapienia powaznego bledu (glownie * w konstruktorach np. gdy nie mozna otworzyc pliku). */ class BastionIOException { }; /** * Klasa stanowiaca abstrakcje strumienia wejsciowego. Umozliwia * sekwencyjny odczyt serii nastepujacych po sobie bajtow. Prostota * interfejsu (w porownaniu do standardowych strumieni w C++) * umozliwia jego latwa implementacje. */ class BastionInput { public : /** * Destruktor wirtualny na potrzeby podklas. */ virtual ~BastionInput() { // pusta implementacja } /** * Metoda wczytujaca do wskazanego bufora sekwencje bajtow * podanej wielkosci. * \param buffer bufor do ktorego maja zostac wczytane dane * \param size ilosc bajtow do wczytania * \return liczba wczytanych bajtow lub -1 w przypadku bledu */ virtual int read(char* buffer, int size) = 0; /** * Zamyka strumien. Po zamknieciu strumienia odczyt z niego daje * nieokreslony wynik. Strumien powinnien zawsze byc zamykany. */ virtual void close() = 0; }; /** * Klasa stanowiaca abstrakcje strumienia wyjsciowego. Umozliwia * sekwencyjny zapis serii nastepujacych po sobie bajtow. Prostota * interfejsu (w porownaniu do standardowych strumieni w C++) * umozliwia jego latwa implementacje. */ class BastionOutput { public : /** * Destruktor wirtualny na potrzeby podklas. */ virtual ~BastionOutput() { // pusta implementacja } /** * Metoda zapisujaca do strumienia sekwencje bajtow podrana z * przekazanego bufora. * \param buffer bufor z ktorego maja zostac pobrane dane * \param size ilosc bajtow do zapisania * \return liczba zapisanych bajtow lub -1 w przypadku bledu */ virtual int write(const char* buffer, int size) = 0; /** * Zamyka strumien. Po zamknieciu strumienia zapis do niego daje * nieokreslony wynik. Strumien powinnien zawsze byc zamykany. */ virtual void close() = 0; }; #endif --- NEW FILE: SaveManager.cpp --- #include "SaveManager.h" #include "FileManager.h" #include "Common.h" #include "BastionInput.h" #include "BastionOutput.h" void* SaveDescription::create() { return new SaveDescription(); } SaveManager::SaveManager() { } SaveManager* SaveManager::createDefault() { SaveManager *result = new SaveManager(); for (int i = 0; i < 12; i++) { SaveDescription *desc = new SaveDescription("--PUSTE--", ""); result->saveDescription.push_back(desc); } return result; } void* SaveManager::create() { return new SaveManager; } vector<SaveDescription*> SaveManager::getSaves() const { return saveDescription; } void save(SaveDescription* save, World *world) { // TODO: napisac } World* load(SaveDescription* save) { // TODO: napisac if (!save->isEmpty()) { } return NULL; } --- NEW FILE: SaveManager.h --- #ifndef __SAVER_H__ #define __SAVER_H__ #include <vector> #include <string> #include <sys/time.h> #include "Serializer.h" using namespace std; class Game; class SaveDescription { friend class ObjectCreator; friend class SaveManager; int saveId; string saveName; time_t saveDate; string saveDesc; bool saveEmpty; static void* create(); SaveDescription() { } SaveDescription(string name, string desc) { saveDate = time(NULL); saveId = -1; saveName = name; saveDesc = desc; saveEmpty = true; } public : void desc(Description *desc) { desc->create(typeid(this)); desc->add(saveDate); desc->add(saveId); desc->add(saveName); desc->add(saveDesc); desc->add(saveEmpty); } void setName(string name) { saveName = name; } void setDesc(string desc) { saveDesc = desc; } string getName() const { return saveName; } time_t getDate() const { return saveDate; } string getDesc() const { return saveDesc; } bool isEmpty() const { return saveEmpty; } }; class FileManager; class World; class SaveManager { friend class ObjectCreator; friend class Configuration; vector<SaveDescription*> saveDescription; static SaveManager* createDefault(); static void* create(); SaveManager(); public : void desc(Description* desc) { Description::ObjectVector<SaveDescription*> objects(desc); desc->create(typeid(this)); objects.add(saveDescription); } vector<SaveDescription*> getSaves() const; void save(SaveDescription* save, World *world); World* load(SaveDescription* save); }; #endif --- NEW FILE: BastionInput.h --- #ifndef __BASTIONINPUT_H__ #define __BASTIONINPUT_H__ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <iostream> #include "Common.h" using namespace std; class BufferedBastionInput : public BastionInput { BastionInput *input; char *buffer; char *source; int count; int left; public : BufferedBastionInput(BastionInput *reader, int size) { buffer = new char[size]; source = buffer; input = reader; count = size; left = 0; } ~BufferedBastionInput() { close(); delete[] buffer; delete input; } int read(char* dest, int size) { int result = 0; while (size > 0) { if (left == 0) { left = input->read(buffer, count); if (left == 0) return result; if (left == -1) return -1; source = buffer; } int copy = min(left, size); result += copy; left -= copy; size -= copy; while (copy-- > 0) *(dest++) = *(source++); } return result; } void close() { source = buffer; left = 0; input->close(); } }; class BastionInputFile : public BastionInput { static const int attr = O_RDONLY; /// Uchwyt do pliku int fileDesc; int openFile(const char* dir, const char* file) { char buffer[256]; strcpy(buffer, dir); strcat(buffer, "/"); strcat(buffer, file); return ::open(buffer, attr); } public : BastionInputFile(int file) { fileDesc = file; } BastionInputFile(const char *dir, const char *file) { fileDesc = openFile(dir, file); if (fileDesc == -1) throw BastionIOException(); } ~BastionInputFile() { close(); } int read(char *data, int size) { if (fileDesc != -1) { size = ::read(fileDesc, data, size); if (size == -1) cerr << "FILE READ ERROR!!!" << endl; } return size; } void close() { if (fileDesc > 2) { ::close(fileDesc); fileDesc = -1; } } }; #endif --- NEW FILE: FileManager.cpp --- #include "FileManager.h" #include "BastionInput.h" #include "BastionOutput.h" const string FileManager::CONF_DIR("conf"); const string FileManager::SAVE_DIR("save"); BastionInput* FileManager::getConfigurationInput(string name) { BastionInput *result = NULL; try { result = new BastionInputFile(CONF_DIR.c_str(), name.c_str()); result = new BufferedBastionInput(result, DEF_BUF_SIZE); } catch (BastionIOException exception) { cerr << "ERROR: configuration output file open faild\n"; } return result; } BastionOutput* FileManager::getConfigurationOutput(string name) { BastionOutput *result = NULL; try { result = new BastionOutputFile(CONF_DIR.c_str(), name.c_str()); result = new BufferedBastionOutput(result, DEF_BUF_SIZE); } catch (BastionIOException exception) { cerr << "ERROR: configuration output file open faild\n"; } return result; } --- NEW FILE: Configuration.cpp --- #include "Configuration.h" #include "FileManager.h" #include "SaveManager.h" #include "Serializer.h" string Configuration::DEFAULT_FILE_NAME = "bastion.conf"; Configuration* Configuration::instance = NULL; void Configuration::setFileManager(FileManager* fileManager) { this->fileManager = fileManager; } void* Configuration::create() { return new Configuration(); } SaveManager* Configuration::getSaveManager() const { return saveManager; } FileManager* Configuration::getFileManager() const { return fileManager; } void Configuration::init() { saveManager = SaveManager::createDefault(); } Configuration* Configuration::load() { if (instance == NULL) { FileManager *fileManager = new FileManager(); BastionInput *input = fileManager->getConfigurationInput(DEFAULT_FILE_NAME); if (input == NULL) { instance = new Configuration(); instance->init(); } else { instance = readObject<Configuration>(input); delete input; } instance->setFileManager(fileManager); } return instance; } void Configuration::save() { BastionOutput* output = fileManager->getConfigurationOutput(DEFAULT_FILE_NAME); if (output != NULL) { writeObject<Configuration>(this, output); } delete output; } --- NEW FILE: Serializer.h --- #ifndef __SERIALIZE_H__ #define __SERIALIZE_H__ #include <typeinfo> #include <string> #include <vector> #include "Common.h" using namespace std; /** * SLOWNIKCZEK :) * * bastionizacja - zapisanie lub wczytanie obiektu gry BASTION * wykonywane za pomoca ponizszego API. * * obiekt - instancja klasy spelniajacej warunki bastionizacji */ /** * Zapisuje przekazany jako pierwszy argument obiekt do podanego * jako drugi argument strumienia wyjsciowego. Klasa przekazanego * do zapisania obiektu musi spelniac wymogi bastionizacji. * * Przyklad wywolania: * World *world = ... * writeObject<World>(world, saveFile); */ template<class T> void writeObject(T* obj, BastionOutput* stream); /** * Wczytuje obiekt danego typu ze wskazanego strumienia wejsciowego. * Klasa wczytywanego obiektu musi spelniac wymogi bastionizacji. * * Przyklad wywolania: * World *world = readObject<World>(saveFile); */ template<class T> T* readObject(BastionInput* stream); /** * Klasa opisu obiektu. Jej zadaniem jest umozliwienie opisania * struktury klasy - jej nadklas, konstruktorow, atrybutow i * skladowych. Dzieki takiemu opisowi funkcje writeObject(...) i * readObject(...) moga poprawnie zbastionizowac przekazane obiekty. */ class Description { private : /// Blokowanie kopiowanie obiektow klasy Description Description(Description const& desc); /// Blokowanie kopiowania obiektow klasy Description Description& operator=(Description const& desc); protected : /// Tworzenie obiektu tylko dla podklas Description() { // pusta implementacja } public : /// Zwraca obiekt Description na potrzeby readObject(...). static Description *getReader(BastionInput* stream); /// Zwraca obiekt Description na potrzeby writeObject(...). static Description *getWriter(BastionOutput* stream); /// Destruktor wirtualny na potrzeby klas podklas. virtual ~Description() { // pusta implementacja } /** * Klasa pomocnicza uzywana do definiowania atrybutow obiektow * bedacych wekorami wartosci prostych lub wskaznikow do takich * wartosci. */ template <class T> class AttrVector { Description *desc; public : /// Tworzy nowego "pomocnika" AttrVector(Description *desc) { this->desc = desc; } /// Dodaje definicje wskazanego wektora void add(vector<T> &vec) { int size = vec.size(); desc->add(size); vec.resize(size); while (size > 0) desc->add(vec[--size]); } }; /** * Klasa pomocnicza uzywana do definiowania atrybutow obiektow * bedacych wekorami wskaznikow do innych obiektow. */ template <class T> class ObjectVector { Description *desc; public : /// Tworzy nowego "pomocnika" ObjectVector(Description *desc) { this->desc = desc; } /// Dodaje definicje wskazanego wektora void add(vector<T> &vec) { int size = vec.size(); desc->add(size); vec.resize(size); while (--size >= 0) if (desc->check((void*) vec[size])) vec[size]->desc(desc); } }; /** * Funkcja definiujaca "konstruktor" dla obiektu danej klasy. * Odpowiednia funkcja jest wybierana na podstawie przekazanej * informacji o typie obiektu. * * Przyklad wywolania ("typeid" to slowo kluczowe w C++): * desc->create(typeid(this)); */ virtual void create(const type_info& info) = 0; /** * Funkcja sprawdzajaca, czy wskazywany przez wskaznik obiekt * zostal juz przetworzony. Zaraz po tym wywolaniu powinno * nastapic warunkowe (w przypadku zwrocenia przez ta metode * true) wywolanie metody desc tego obiektu. */ virtual bool check(void* &object) = 0; /** * Funkcje definiujace attrybuty obiektu bedace wskaznikami lub * dynamicznymi obszarami pamieci. Implementacja automatycznie * wykrywa wskazniki wskazujace na ten sam element w pamieci. * Jako drugi argument wszystkich funkcji przekazywana jest * liczba elementow danego typu do ktorego prowadzi wskaznik * (wielkosc dynamicznie alokowanej tablicy). */ virtual void add(string* &pointer, int size) = 0; virtual void add(double* &pointer, int size) = 0; virtual void add(float* &pointer, int size) = 0; virtual void add(long* &pointer, int size) = 0; virtual void add(int* &pointer, int size) = 0; virtual void add(short* &pointer, int size) = 0; virtual void add(char* &pointer, int size) = 0; virtual void add(bool* &pointer, int size) = 0; virtual void add(string* &pointer) = 0; virtual void add(double* &pointer) = 0; virtual void add(float* &pointer) = 0; virtual void add(long* &pointer) = 0; virtual void add(int* &pointer) = 0; virtual void add(short* &pointer) = 0; virtual void add(char* &pointer) = 0; virtual void add(bool* &pointer) = 0; /** * Funkcja definujaca atrybuty obiektu bedace tablicami * wartosci prostych. Drugi argument okresla ilosc elemntow * w talocy (a nie jej wielkosc w bajtach). */ virtual void add(const string *array, int size) = 0; virtual void add(const double *array, int size) = 0; virtual void add(const float *array, int size) = 0; virtual void add(const long *array, int size) = 0; virtual void add(const int *array, int size) = 0; virtual void add(const short *array, int size) = 0; virtual void add(const char *array, int size) = 0; virtual void add(const bool *array, int size) = 0; virtual void add(string array[], int size) = 0; virtual void add(double array[], int size) = 0; virtual void add(float array[], int size) = 0; virtual void add(long array[], int size) = 0; virtual void add(int array[], int size) = 0; virtual void add(short array[], int size) = 0; virtual void add(char array[], int size) = 0; virtual void add(bool array[], int size) = 0; /** * Funkcje definujace attrybuty obiektu bedace wartosciami prostymi. * Jako argument pobieraja referencje (nie wskaznik!!!) do danego * atrybutu. */ virtual void add(string &value) = 0; virtual void add(double &value) = 0; virtual void add(float &value) = 0; virtual void add(long &value) = 0; virtual void add(int &value) = 0; virtual void add(short &value) = 0; virtual void add(char &value) = 0; virtual void add(bool &value) = 0; }; /** * Zapisuje przekazany jako pierwszy argument obiekt * do podanego strumienia. */ template<class T> void writeObject(T* obj, BastionOutput* stream) { Description *writer = Description::getWriter(stream); if (writer->check((void*)obj)) obj->desc(writer); delete writer; } /** * Wczytuje obiekt podanego typu ze strumienia. */ template<class T> T* readObject(BastionInput* stream) { Description *reader = Description::getReader(stream); void *obj = 0; if (reader->check(obj)) ((T*) obj)->desc(reader); delete reader; return (T*)obj; }; #endif --- NEW FILE: Serializer.cpp --- #include "Serializer.h" #include <map> #include <iostream> #include "ObjectCreator.h" using namespace std; // TODO: zapisywanie/odczytywanie atrybutow wskaznikowych // TODO: sprawdzanie zachodzacych na siebie fragmentow pamieci class DescriptionImpl : public Description { protected: virtual void updateBuffer(char *data, int size) = 0; public : void add(long &attr) { updateBuffer((char*)&attr, sizeof(long)); } void add(int &attr) { updateBuffer((char*)&attr, sizeof(int)); } void add(short &attr) { updateBuffer((char*)&attr, sizeof(short)); } void add(char &attr) { updateBuffer((char*)&attr, sizeof(char)); } void add(float &attr) { updateBuffer((char*)&attr, sizeof(float)); } void add(double &attr) { updateBuffer((char*)&attr, sizeof(double)); } void add(bool &attr) { updateBuffer((char*)&attr, sizeof(bool)); } void add(double array[], int size) { updateBuffer((char*)array, size*sizeof(double)); } void add(float array[], int size) { updateBuffer((char*)array, size*sizeof(float)); } void add(long array[], int size) { updateBuffer((char*)array, size*sizeof(long)); } void add(int array[], int size) { updateBuffer((char*)array, size*sizeof(int)); } void add(short array[], int size) { updateBuffer((char*)array, size*sizeof(short)); } void add(char array[], int size) { updateBuffer((char*)array, size); } void add(bool array[], int size) { updateBuffer((char*)array, size*sizeof(bool)); } void add(const double *array, int size) { updateBuffer((char*)array, size*sizeof(double)); } void add(const float *array, int size) { updateBuffer((char*)array, size*sizeof(float)); } void add(const long *array, int size) { updateBuffer((char*)array, size*sizeof(long)); } void add(const int *array, int size) { updateBuffer((char*)array, size*sizeof(int)); } void add(const short *array, int size) { updateBuffer((char*)array, size*sizeof(short)); } void add(const char *array, int size) { updateBuffer((char*)array, size); } void add(const bool *array, int size) { updateBuffer((char*)array, size*sizeof(bool)); } }; class Writer : public DescriptionImpl { map<void*, int> mapping; BastionOutput *output; void *last; bool isNew; protected : /// Funkcja wrzucajaca do bufora dany obszar pamieci void updateBuffer(char *object, int size) { output->write(object, size); } public : Writer(BastionOutput *file) { output = file; isNew = true; mapping[NULL] = 0; } void create(const type_info &info) { int index = ObjectCreator::find(info); if (isNew) { if (index == -1) { cerr << "ERROR WHILE SERIALIZING OBJECT:"; cerr << info.name() << endl; } updateBuffer((char*)&index, sizeof(int)); } mapping[last] = index; isNew = false; } bool check(void* &object) { updateBuffer((char*)&object, sizeof(void*)); if (mapping.find(object) == mapping.end()) { last = object; isNew = true; return true; } return false; } void add(string &attr) { int length = attr.length(); DescriptionImpl::add(length); DescriptionImpl::add(attr.c_str(), length); } void add(string* &pointer, int size) { if (check((void*)pointer)) { updateBuffer((char*) pointer, sizeof(int)); add((const string*) pointer, size); } } void add(double* &pointer, int size) { if (check((void*)pointer)) { updateBuffer((char*) pointer, sizeof(int)); DescriptionImpl::add((const double*) pointer, size); } } void add(float* &pointer, int size) { if (check((void*)pointer)) { updateBuffer((char*) pointer, sizeof(int)); DescriptionImpl::add((const float*) pointer, size); } } void add(long* &pointer, int size) { if (check((void*)pointer)) { updateBuffer((char*) pointer, sizeof(int)); DescriptionImpl::add((const long*) pointer, size); } } void add(int* &pointer, int size) { if (check((void*)pointer)) { updateBuffer((char*) pointer, sizeof(int)); DescriptionImpl::add((const int*) pointer, size); } } void add(short* &pointer, int size) { if (check((void*)pointer)) { updateBuffer((char*) pointer, sizeof(int)); DescriptionImpl::add((const short*) pointer, size); } } void add(char* &pointer, int size) { if (check((void*)pointer)) { updateBuffer((char*) pointer, sizeof(int)); DescriptionImpl::add((const char*) pointer, size); } } void add(bool* &pointer, int size) { if (check((void*)pointer)) { updateBuffer((char*) pointer, sizeof(int)); DescriptionImpl::add((const bool*) pointer, size); } } void add(string* &pointer) { if (check((void*)pointer)) add(*pointer); } void add(double* &pointer) { if (check((void*)pointer)) DescriptionImpl::add(*pointer); } void add(float* &pointer) { if (check((void*)pointer)) DescriptionImpl::add(*pointer); } void add(long* &pointer) { if (check((void*)pointer)) DescriptionImpl::add(*pointer); } void add(int* &pointer) { if (check((void*)pointer)) DescriptionImpl::add(*pointer); } void add(short* &pointer) { if (check((void*)pointer)) DescriptionImpl::add(*pointer); } void add(char* &pointer) { if (check((void*)pointer)) DescriptionImpl::add(*pointer); } void add(bool* &pointer) { if (check((void*)pointer)) DescriptionImpl::add(*pointer); } void add(string array[], int size) { while (size-- > 0) add(array[size]); } void add(const string *array, int size) { string *pointer = (string*) array; while (size-- > 0) add(pointer[size]); } }; class Reader : public DescriptionImpl { map<void*, void*> mapping; BastionInput *input; protected: /// Funkcja wrzucajaca do bufora dany obszar pamieci void updateBuffer(char *object, int size) { input->read(object, size); } public : Reader(BastionInput *file) { input = file; mapping[NULL] = NULL; } void create(const type_info &info) { } bool check(void* (&object)) { void *pointer = 0; int index; updateBuffer((char*) &pointer, sizeof(void*)); if (mapping.find(pointer) == mapping.end()) { updateBuffer((char*) &index, sizeof(int)); object = ObjectCreator::create(index); if (object == NULL) cerr << "NULL POINTER CREATED (" << index << ")" << endl; mapping[pointer] = object; return true; } object = mapping[pointer]; return false; } void add(string &attr) { int length = 0; DescriptionImpl::add(length); if (length > 0) { char table[length]; DescriptionImpl::add((const char*)table, length); attr = string(table, length); } } void add(string* &pointer, int size) { if (check((void*)pointer)) { pointer = new string[size]; add((const string*) pointer, size); } } void add(double* &pointer, int size) { if (check((void*)pointer)) { pointer = new double[size]; updateBuffer((char*) pointer, size*sizeof(double)); } } void add(float* &pointer, int size) { if (check((void*)pointer)) { pointer = new float[size]; updateBuffer((char*) pointer, size*sizeof(float)); } } void add(long* &pointer, int size) { if (check((void*)pointer)) { pointer = new long[size]; updateBuffer((char*) pointer, size*sizeof(long)); } } void add(int* &pointer, int size) { if (check((void*)pointer)) { pointer = new int[size]; updateBuffer((char*) pointer, size*sizeof(int)); } } void add(short* &pointer, int size) { if (check((void*)pointer)) { pointer = new short[size]; updateBuffer((char*) pointer, size*sizeof(short)); } } void add(char* &pointer, int size) { if (check((void*)pointer)) { pointer = new char[size]; updateBuffer((char*) pointer, size); } } void add(bool* &pointer, int size) { if (check((void*)pointer)) { pointer = new bool[size]; updateBuffer((char*) pointer, size*sizeof(bool)); } } void add(string* &pointer) { if (check((void*)pointer)) { pointer = new string; add(*pointer); } } void add(double* &pointer) { if (check((void*)pointer)) { pointer = new double; DescriptionImpl::add(*pointer); } } void add(float* &pointer) { if (check((void*)pointer)) { pointer = new float; DescriptionImpl::add(*pointer); } } void add(long* &pointer) { if (check((void*)pointer)) { pointer = new long; DescriptionImpl::add(*pointer); } } void add(int* &pointer) { if (check((void*)pointer)) { pointer = new int; DescriptionImpl::add(*pointer); } } void add(short* &pointer) { if (check((void*)pointer)) { pointer = new short; DescriptionImpl::add(*pointer); } } void add(char* &pointer) { if (check((void*)pointer)) { pointer = new char; DescriptionImpl::add(*pointer); } } void add(bool* &pointer) { if (check((void*)pointer)) { pointer = new bool; DescriptionImpl::add(*pointer); } } void add(string array[], int size) { while (size-- > 0) add(array[size]); } void add(const string *array, int size) { string *pointer = (string*) array; while (size-- > 0) add(pointer[size]); } }; Description* Description::getReader(BastionInput *stream) { return new Reader(stream); } Description* Description::getWriter(BastionOutput *stream) { return new Writer(stream); } --- NEW FILE: FileManager.h --- #ifndef __FILE_MANAGER_H__ #define __FILE_MANAGER_H__ #include <string> #include "Common.h" using namespace std; class FileManager { friend class Configuration; const static int DEF_BUF_SIZE = 4096; const static string SAVE_DIR; const static string CONF_DIR; FileManager() { } BastionInput* getConfigurationInput(string name); BastionOutput* getConfigurationOutput(string name); public : }; #endif --- NEW FILE: ObjectCreator.cpp --- #include "ObjectCreator.h" #include "Configuration.h" #include <iostream> using namespace std; ObjectCreator* ObjectCreator::creatorTable[] = { NULL, // Puste pierwsze wejscie. Nie zmieniac go !!! new ObjectCreator(typeid(SaveDescription*), SaveDescription::create), new ObjectCreator(typeid(SaveManager*), SaveManager::create), new ObjectCreator(typeid(Configuration*), Configuration::create) }; int ObjectCreator::find(const type_info& info) { // Przegladamy tablice w poszukiwaniu obiektu ObjectCreator z // type_info jak podane int size = sizeof(creatorTable)/sizeof(ObjectCreator*); for (int i = 0; i < size; ++i) if (creatorTable[i] != NULL) if (creatorTable[i]->getTypeInfo() == info) return i; return -1; } void* ObjectCreator::create(int index) { int size = sizeof(creatorTable)/sizeof(ObjectCreator*); if (index > 0 && index < size) { ObjectCreator *creator = creatorTable[index]; if (creator != NULL) return creator->createObject(); } return NULL; } --- NEW FILE: BastionOutput.h --- #ifndef __BASTIONOUTPUT_H__ #define __BASTIONOUTPUT_H__ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <iostream> #include "Common.h" using namespace std; class BufferedBastionOutput : public BastionOutput { BastionOutput *output; char *buffer; char *dest; int count; int left; public : BufferedBastionOutput(BastionOutput *writer, int size) { buffer = new char[size]; dest = buffer; output = writer; count = size; left = size; } ~BufferedBastionOutput() { close(); delete[] buffer; delete output; } int write(const char* source, int size) { int result = 0; while (size > 0) { if (left == 0) { left = output->write(buffer, count); if (left < count) { dest = buffer; left = count; return result; } if (left == -1) return -1; } int copy = min(left, size); result += copy; left -= copy; size -= copy; while (copy-- > 0) *(dest++) = *(source++); } return result; } void flush() { if (dest != buffer) { output->write(buffer, dest-buffer); dest = buffer; left = count; } } void close() { flush(); output->close(); } }; class BastionOutputFile : public BastionOutput { // Prawa uzywane do otwarcia pliku static const int attr = O_WRONLY|O_CREAT; /// Uchwyt pliku int fileDesc; int createDir(const char *dir, int len) { if (mkdir(dir, 0777) == -1) { int result = -1; if (errno == ENOENT) { while (--len > 0) { if (dir[len] == '/') { ((char*) dir)[len] = 0; result = createDir(dir, len); ((char*) dir)[len] = '/'; if (result != -1) return mkdir(dir, 0777); } } } return result; } return 0; } int openFile(const char *dir, const char *file) { char buffer[256]; strcpy(buffer, dir); strcat(buffer, "/"); strcat(buffer, file); return ::open(buffer, attr, 0333); } public : BastionOutputFile(int file) { fileDesc = file; } BastionOutputFile(const char *dir, const char *file) { fileDesc = openFile(dir, file); if (fileDesc == -1) { if (createDir(dir, strlen(dir)) == -1 || (fileDesc = openFile(dir, file)) == -1) { cerr << "FILE OPEN ERROR!!!" << endl; throw BastionIOException(); } } } ~BastionOutputFile() { close(); } int write(const char *data, int size) { if (fileDesc != -1) if (::write(fileDesc, data, size) != size) { cerr << "FILE WRITE ERROR!!!" << endl; return -1; } return size; } void close() { if (fileDesc > 2) { ::close(fileDesc); fileDesc = -1; } } }; #endif --- NEW FILE: ObjectCreator.h --- #ifndef __OBJECT_CREATOR_H__ #define __OBJECT_CREATOR_H__ #include <typeinfo> using namespace std; class ObjectCreator { static ObjectCreator* creatorTable[]; void* (*creator)(); const type_info& typeInfo; ObjectCreator(const type_info& objectType, void* (*objectCreator)()) : typeInfo(objectType), creator(objectCreator) { } void* createObject() { return creator(); } const type_info& getTypeInfo() { return typeInfo; } public : /** * \return indeks creatora dla obiektu danego typu lub -1 w * przypadku bledu (nie znalezienia typu) */ static int find(const type_info& info); /** * Tworzy instancje obiektu o podanym indeksie. Dla indeksu * rownego 0 zwraca zawsze NULL'a. */ static void* create(int index); }; #endif |