![]() |
![]() |
![]() |
#1 |
V.I.P. Programiranje
|
![]()
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. |
![]() |
![]() |
![]() |
#2 |
V.I.P. Programiranje
|
![]()
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(); }; |
![]() |
![]() |
![]() |
#3 |
V.I.P. Programiranje
|
![]()
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 |
V.I.P. Programiranje
|
![]()
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 |
![]() |
![]() |
![]() |
#5 |
Deo inventara foruma
Član od: 14.3.2008.
Lokacija: EHCPCGG
Poruke: 12.050
Zahvalnice: 4.287
Zahvaljeno 3.250 puta na 2.251 poruka
|
![]()
Looks familiar
![]() Pokusao sam da procitam ovo juce... I razumeo tek delic svega ![]() |
![]() |
![]() |
![]() |
#6 |
V.I.P. Programiranje
|
![]()
Zašto? Uopšte nije teško za pročitati... Nagledaćeš se ti hard-to-understand kôda, videćeš...
|
![]() |
![]() |
![]() |
#7 |
Deo inventara foruma
Član od: 14.3.2008.
Lokacija: EHCPCGG
Poruke: 12.050
Zahvalnice: 4.287
Zahvaljeno 3.250 puta na 2.251 poruka
|
![]()
Cek', rekoh ti, tek sam juce poceo da se zamlacujem iole ozbiljno sa klasama
![]() |
![]() |
![]() |
![]() |
#8 |
Veteran
|
![]()
Deluje mi kao da bih ovaj kod mogao da upotrebim za nesto
![]() |
![]() |
![]() |
![]() |
#9 |
V.I.P. Programiranje
|
![]() |
![]() |
![]() |
![]() |
Bookmarks sajtovi |
Alatke vezane za temu | |
Vrste prikaza | |
|
|
![]() |
||||
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 |