// ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * // * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** #ifndef SERIALIZE_H_INCLUDED #define SERIALIZE_H_INCLUDED #include #include #include #include #include #include namespace zen { //unchecked, unformatted serialization template T readPOD (wxInputStream& stream); template void writePOD(wxOutputStream& stream, const T& pod); template S readString (wxInputStream& stream); template void writeString(wxOutputStream& stream, const S& str); //############# wxWidgets stream adapter ############# // can be used as base classes (have virtual destructors) class FileInputStream : public wxInputStream { public: FileInputStream(const Zstring& filename) : //throw FileError fileObj(filename) {} private: virtual size_t OnSysRead(void* buffer, size_t bufsize) { return fileObj.read(buffer, bufsize); //throw FileError } zen::FileInput fileObj; }; class FileOutputStream : public wxOutputStream { public: FileOutputStream(const Zstring& filename) : //throw FileError fileObj(filename, zen::FileOutput::ACC_OVERWRITE) {} private: virtual size_t OnSysWrite(const void* buffer, size_t bufsize) { fileObj.write(buffer, bufsize); //throw FileError return bufsize; } zen::FileOutput fileObj; }; class ReadInputStream //throw FileError { protected: ReadInputStream(wxInputStream& stream, const wxString& errorObjName) : stream_(stream), errorObjName_(errorObjName) {} template T readNumberC() const; //throw FileError, checked read operation template S readStringC() const; //throw FileError, checked read operation typedef std::shared_ptr > CharArray; //there's no guarantee std::string has a ref-counted implementation... so use this "thing" CharArray readArrayC() const; //throw FileError void check() const; wxInputStream& getStream() { return stream_; } private: wxInputStream& stream_; const wxString& errorObjName_; //used for error text only }; class WriteOutputStream //throw FileError { protected: WriteOutputStream(const wxString& errorObjName, wxOutputStream& stream) : stream_(stream), errorObjName_(errorObjName) {} template void writeNumberC(T number) const; //throw FileError, checked write operation template void writeStringC(const S& str) const; //throw FileError, checked write operation void writeArrayC(const std::vector& buffer) const; //throw FileError void check() const; wxOutputStream& getStream() { return stream_; } private: wxOutputStream& stream_; const wxString& errorObjName_; //used for error text only! }; //-----------------------implementation------------------------------- template inline T readPOD(wxInputStream& stream) { T pod = 0; stream.Read(reinterpret_cast(&pod), sizeof(T)); return pod; } template inline void writePOD(wxOutputStream& stream, const T& pod) { stream.Write(reinterpret_cast(&pod), sizeof(T)); } template inline S readString(wxInputStream& stream) { typedef typename S::value_type CharType; const auto strLength = readPOD(stream); if (strLength <= 1000) { CharType buffer[1000]; stream.Read(buffer, sizeof(CharType) * strLength); return S(buffer, strLength); } else { std::vector buffer(strLength); //throw std::bad_alloc stream.Read(&buffer[0], sizeof(CharType) * strLength); return S(&buffer[0], strLength); } } template inline void writeString(wxOutputStream& stream, const S& str) { writePOD(stream, static_cast(str.length())); stream.Write(str.c_str(), sizeof(typename S::value_type) * str.length()); } inline void ReadInputStream::check() const { if (stream_.GetLastError() != wxSTREAM_NO_ERROR) throw zen::FileError(_("Error reading from synchronization database:") + " \n" + "\"" + errorObjName_.c_str() + "\""); } template inline T ReadInputStream::readNumberC() const //checked read operation { T output = readPOD(stream_); check(); return output; } template inline S ReadInputStream::readStringC() const //checked read operation { S output; try { output = readString(stream_); //throw (std::bad_alloc) check(); } catch (std::exception&) { throw FileError(_("Error reading from synchronization database:") + " \n" + "\"" + errorObjName_.c_str() + "\""); } return output; } inline ReadInputStream::CharArray ReadInputStream::readArrayC() const { const std::uint32_t byteCount = readNumberC(); CharArray buffer(new std::vector(byteCount)); if (byteCount > 0) { stream_.Read(&(*buffer)[0], byteCount); check(); if (stream_.LastRead() != byteCount) //some additional check throw FileError(_("Error reading from synchronization database:") + " \n" + "\"" + errorObjName_.c_str() + "\""); } return buffer; } template inline void WriteOutputStream::writeNumberC(T number) const //checked write operation { writePOD(stream_, number); check(); } template inline void WriteOutputStream::writeStringC(const S& str) const //checked write operation { writeString(stream_, str); check(); } inline void WriteOutputStream::writeArrayC(const std::vector& buffer) const { writeNumberC(static_cast(buffer.size())); if (buffer.size() > 0) { stream_.Write(&buffer[0], buffer.size()); check(); if (stream_.LastWrite() != buffer.size()) //some additional check throw FileError(_("Error writing to synchronization database:") + " \n" + "\"" + errorObjName_.c_str() + "\""); } } inline void WriteOutputStream::check() const { if (stream_.GetLastError() != wxSTREAM_NO_ERROR) throw FileError(_("Error writing to synchronization database:") + " \n" + "\"" + errorObjName_.c_str() + "\""); } } #endif //SERIALIZE_H_INCLUDED