4.1.2010, 14:25 | #1 |
V.I.P. Programiranje
|
IO System
Ovo je mali IO sistem koji služi za pisanje i čitanje iz fajlova. Svodi se na pravljenje IO komponenti izvođenjem iz osnovne klase IOCapable i overridovanjem tri osnovne funkcije: getBinaryData() kada treba upisati podatke u fajl, parseBinaryData() kada su podaci pročitani i trebaju da se obrade, i getID() koja treba da vrati jednobajtni ID broj koji treba da bude različit za svaku komponentu. Onda se pravi instanca IOSystem klase i registruju se željene komponente. IOSystem podržava ::saveToFile() i ::loadFromFile(). Kada se izvrši saveToFile(), IOSystem "pita" svaku komponentu za njene podatke koje treba snimiti u fajl. Kada se pozove loadFromFile(), IOSystem čita podatke iz određenog fajla i pronalazi koji deo fajla pripada kojoj kompoenti, a zatim im prosleđuje njihove podatke da bi ih parseovali. Ovde takođe postoji i klasa ByteDump za ubacivanje bajtova u vektor ("dump") i onda njihov retrieval kao običan niz spreman za pisanje u fajl. Uključuje i klasu ByteWalker koja služi za čitanje bajtova iz niza (pročitaj sledeći bajt, pročitaj sledećih x bajtova, pročitaj bajtove dok ne naiđeš na zero termination itd.). Uključio sam i test.cpp fajl koji prikazuje kako se pravi IO komponenta, kako se registruje, kako se upisuju sve vrste kompleksnih podataka u byte dump i kako se isti podaci čitaju pomoću ByteWalkera. Program ima komentare (doduše na engleskom) pa ne bi bilo problem da se snađete
Sistem može da se koristi kada treba snimiti dosta podataka u jedan fajl. Nije neka filozofija i veoma mi je bio lak za napraviti, ali ako nekom zatreba ovako nešto da ima pri ruci. Otvoren sam za sve kritike / sugestije. Kôd u sledećoj poruci. |
4.1.2010, 14:26 | #2 |
V.I.P. Programiranje
|
Re: IO System
io.h
Kod:
#pragma once #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable : 4018) #include <vector> #include <fstream> #include <sys/stat.h> using namespace std; // Converts data into bytes char* toBytes(void*); class IOCapable { public: // Should put binary data to write to the file and its length into the pointers, while saving. virtual void getBinaryData(char**, long*) = 0; // Should parse the binary data read from the input file, while loading. virtual void parseBinaryData(char*, long) = 0; // Should return the unique ID lengthing one byte, identifying data written by this IO capable component. virtual char getID() = 0; }; class ByteDump { vector<char> dump; public: // Default constructor ByteDump(); // Dump a byte, returns the index in the dump. int dumpByte(char); // Dump an array of bytes, returns the index of first. int dumpBytes(char*, long); // Set a byte value in the dump, based on the index. void setByte(long, char); // Inserts a byte at the specific position in the dump. void insertByte(long, char); // Removes a byte based on the index. void removeByte(long); // Allocates a new array and puts the dump into it. char* getAsArray(); // Returns the current dump length. long getLength(); // Default destructor ~ByteDump(); }; class ByteWalker { private: long position; char* bytes; long length; bool end; public: // Default no-parameters constructor ByteWalker(); // Constructor which takes a byte array and its length. ByteWalker(char*, long); // Sets the byte array, takes array and its length. void setByteArray(char*, long); // Sets the variables pointed by two arguments to byte array and length, respectively. void getByteArray(char**, long*); // Moves the pointer relatively to left. void moveLeft(long); // Moves the pointer relatively to right. void moveRight(long); // Sets the pointer to a specific byte position. void goToPosition(long); // Gets the next byte. char getByte(); // Gets the next array of bytes. char* getBytes(long); // Gets the bytes until the next zero-termination. char* getBytesUntilZero(); // Returns the position of the next byte to be read. long getSeek(); // Returns true if the end of array has been reached. bool isEnd(); // Puts the pointer back to the beginning. void goBack(); // Destructor ~ByteWalker(); }; class IOSystem { private: vector<IOCapable*> Components; public: // Default constructor - no parameters IOSystem(); // Adds (registers) an IO capable component. Accepts an IOCapable derived class, returns the index. int addIOComponent(IOCapable*); // Removes (unregisters) an IO capable component from the array, takes the index, returns nothing. void removeIOComponent(int); // Saves (or dumps) all the data to the file. Each IOCapable component's getBinaryData() is invoked. Returns // true on success, false on fail. Accepts the filename. bool saveToFile(char*); // Loads all the data from the file. Each IOCapable component's parseBinaryData() is invoked. Returns true on // success, false on fail. Accepts the filename. bool loadFromFile(char*); // Destructor ~IOSystem(); }; |
4.1.2010, 14:26 | #3 |
V.I.P. Programiranje
|
Re: IO System
io.cpp
Kod:
#include "io.h" char* toBytes(void * ptr) { return (char*)ptr; } ByteWalker::ByteWalker() { bytes = new char[1]; length = 1; position = 0; end = false; } ByteWalker::ByteWalker(char* _bytes, long _length) { bytes = _bytes; length = _length; position = 0; end = false; } void ByteWalker::setByteArray(char* _bytes, long _length) { bytes = _bytes; length = _length; position = 0; end = false; } void ByteWalker::getByteArray(char** _bytes, long* _length) { *_bytes = bytes; *_length = length; } char* ByteWalker::getBytes(long len) { if (len > length - position) return NULL; char *byte = new char [ len ]; for (int i = position; i < len + position; i++) { byte[i-position] = bytes[i]; } position += len; return byte; } void ByteWalker::moveLeft(long amt = 1) { if (amt > position) return; position -= amt; end = false; } void ByteWalker::moveRight(long amt = 1) { if (position + amt >= length) { end = true; return; } position += amt; } void ByteWalker::goToPosition(long pos) { if (pos < 0 || pos >= length) return; position = pos; end = false; } char ByteWalker::getByte() { if (position > length - 1) { end = true; return 0; } if (position != length - 1) position++; return bytes[position-1]; } char* ByteWalker::getBytesUntilZero() { long len = 0; bool there = false; for (int i=position; i < length; i++) { if (bytes[i] == 0) { there = true; break; } len++; } if (!there) { end = true; return NULL; } return getBytes(len+1); } bool ByteWalker::isEnd() { return end; } long ByteWalker::getSeek() { return position; } ByteWalker::~ByteWalker() { } // ******************************************************** ByteDump::ByteDump() { } int ByteDump::dumpByte(char byte) { dump.push_back(byte); return dump.size() - 1; } int ByteDump::dumpBytes(char* bytes, long length) { int last = dump.size(); // dump.size() - 1 is the last element. When we append a new one, the last element will be current dump.size(). for (int i=0; i < length; i++) { dumpByte(bytes[i]); } return last; } void ByteDump::setByte(long idx, char byte) { if (idx < 0 || idx >= dump.size()) return; dump[idx] = byte; } void ByteDump::insertByte(long idx, char byte) { if (idx < 0 || idx >= dump.size()) return; dump.insert(dump.begin() + idx, byte); } void ByteDump::removeByte(long idx) { if (idx < 0 || idx >= dump.size()) return; dump.erase(dump.begin() + idx); } long ByteDump::getLength() { return dump.size(); } char* ByteDump::getAsArray() { char* arr = new char[getLength()]; for (int i=0; i < dump.size(); i++) { arr[i] = dump[i]; } return arr; } ByteDump::~ByteDump() { } //////////////////////////////////////////////////////////// IOSystem::IOSystem() { } int IOSystem::addIOComponent(IOCapable * component) { Components.push_back(component); return Components.size() - 1; } void IOSystem::removeIOComponent(int idx) { if (idx < 0 || idx > Components.size() - 1) return; Components.erase(Components.begin() + idx); } bool IOSystem::saveToFile(char* filename) { fstream File; File.open(filename, ios::out | ios::binary); if (!File) return false; char idx; char *data; long len = -1; for (int i=0; i < Components.size(); i++) { idx = Components[i]->getID(); File.write(&idx, 1); // First we write the index of the component - it'll help us when parsing. Components[i]->getBinaryData(&data, &len); // Here we ask the component to store the data into variable data and its length to variable len. if (len == -1) return false; File.write((char*)&len, sizeof(long)); // Here we write the length of the stream in bytes. File.write(data, len); // And here we write the data. delete[] data; len = -1; } File.close(); return true; } bool IOSystem::loadFromFile(char* filename) { long fsize; fstream File; File.open(filename, ios::in | ios::binary); if (!File) return false; struct stat results; if (stat(filename, &results) == 0) // Getting the file size fsize = results.st_size; else return false; char* bytes = new char[fsize]; File.get(bytes, fsize); // Retrieving the whole file File.close(); ByteWalker walk(bytes, fsize); int passes = 0; while (walk.getSeek() < fsize) { char ID = 0; ID = walk.getByte(); long size; long *sizeptr = (long*)(walk.getBytes(sizeof(long))); size = *sizeptr; delete sizeptr; char* iocapdata = walk.getBytes(size); for (int i=0; i < Components.size(); i++) { if (Components[i]->getID() == ID) Components[i]->parseBinaryData(iocapdata, size); } delete[] iocapdata; passes++; } delete[] bytes; return true; } IOSystem::~IOSystem() { Components.clear(); } |
4.1.2010, 14:27 | #4 |
V.I.P. Programiranje
|
Re: IO System
test.cpp
Kod:
#include "io.h" // Dummy struct, just showing how to write complex data (see SampleIO::getBinaryData() ). struct Sample { int a, b, c; char x; bool y; }; // We define our sample IO class. class SampleIO : public IOCapable { public: void getBinaryData(char**, long*); void parseBinaryData(char*, long); char getID(); }; // Now implement the code... void SampleIO::getBinaryData(char** data, long* length) { // First we have to create the data we want to be saved to file. // We use ByteDump to do it. ByteDump dump; // First, let's dump one single byte, just for the record dump.dumpByte('D'); // Now, dump an integer int MyInt = 12345; dump.dumpBytes((char*)&MyInt, sizeof(int)); // Let's dump a string! dump.dumpBytes("Hello World!", sizeof("Hello World!")); // Now let's dump something complex. Sample dummy; dummy.a = dummy.b = 123; dummy.x = 'A'; dummy.y = true; dump.dumpBytes((char*)&dummy, sizeof(Sample)); // That's it! // Now we set those pointers we received... *data = dump.getAsArray(); *length = dump.getLength(); } char SampleIO::getID() { // Each IO component has to have unique ID, different from zero, lengthing one byte. Let's say this component's ID is 1. return 5; } void SampleIO::parseBinaryData(char* data, long length) { // Here we have to parse the data loaded from the file. We create a // ByteWalker interface. ByteWalker walk(data, length); // Remember that we dumped first one byte? Let's get it. char byte = walk.getByte(); // 'byte' now contains 'D'. // Then, we dumped an integer so we retrieve sizeof(int) bytes. char * bytes = walk.getBytes(sizeof(int)); int MyInt = *((int*)bytes); delete[] bytes; // MyInt contains 12345. // Now we have to retrieve the string. Since we don't know exact length, // we'll just get bytes until we find a zero termination. char * String = walk.getBytesUntilZero(); // String now contains "Hello World!". delete[] String; // Now we'll retrieve a whole struct from the data. bytes = walk.getBytes(sizeof(Sample)); Sample sample = *((Sample*)bytes); delete[] bytes; // Now sample contains the data we have dumped previously. // a = b = 123, x = 'A', boolean = true. } int main() { IOSystem *io = new IOSystem(); SampleIO *sample = new SampleIO(); // We ask the IOSystem to register a new component, SampleIO. io->addIOComponent((IOCapable*)sample); // We save the data of all components (in this case only one :) ) // to an external file. Each components' getBinaryData() is invoked. io->saveToFile("test.bin"); // Now we parse that same file. This time, each components' parseBinaryData() is invoked. // is invoked. io->loadFromFile("test.bin"); delete sample; return 0; } Poslednja ispravka: Geomaster (6.1.2010 u 15:08) Razlog: IOComponent -> IOCapable |
4.1.2010, 16:43 | #5 |
Deo inventara foruma
Član od: 14.3.2008.
Lokacija: EHCPCGG
Poruke: 12.110
Zahvalnice: 4.319
Zahvaljeno 3.295 puta na 2.274 poruka
|
Re: IO System
Looks familiar
Pokusao sam da procitam ovo juce... I razumeo tek delic svega |
4.1.2010, 16:45 | #6 |
V.I.P. Programiranje
|
Re: IO System
Zašto? Uopšte nije teško za pročitati... Nagledaćeš se ti hard-to-understand kôda, videćeš...
|
4.1.2010, 17:03 | #7 |
Deo inventara foruma
Član od: 14.3.2008.
Lokacija: EHCPCGG
Poruke: 12.110
Zahvalnice: 4.319
Zahvaljeno 3.295 puta na 2.274 poruka
|
Re: IO System
Cek', rekoh ti, tek sam juce poceo da se zamlacujem iole ozbiljno sa klasama
|
6.1.2010, 12:59 | #8 |
Veteran
|
Re: IO System
Deluje mi kao da bih ovaj kod mogao da upotrebim za nesto Imas 2 greske koje kompajler izbacuje, u io.h umesto boolean treba bool, i u test.cpp umesto IOComponent IOCapable.
|
6.1.2010, 15:08 | #9 |
V.I.P. Programiranje
|
Re: IO System
|
Bookmarks sajtovi |
Alatke vezane za temu | |
Vrste prikaza | |
|
|
Slične teme | ||||
tema | temu započeo | forum | Odgovora | Poslednja poruka |
GTA 4 za PC! | JJ92 | Akcione igre | 8690 | 9.5.2023 18:36 |
System restore/backup files | jonathan | Operativni sistemi | 7 | 1.11.2009 17:29 |
System Restore (zauzeće diska) | jonathan | Operativni sistemi | 10 | 13.9.2009 14:14 |
System Restore za neupućene | dacajak | Operativni sistemi | 6 | 16.2.2009 23:11 |
Freelancer/tips&tricks | BabaRoga | Online susreti | 70 | 21.2.2007 19:50 |