diff options
Diffstat (limited to 'wx+/serialize.h')
-rw-r--r-- | wx+/serialize.h | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/wx+/serialize.h b/wx+/serialize.h new file mode 100644 index 00000000..c15e963d --- /dev/null +++ b/wx+/serialize.h @@ -0,0 +1,274 @@ +// ************************************************************************** +// * 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 <vector> +#include <cstdint> +#include <memory> +#include <wx/stream.h> +#include <zen/file_error.h> +#include <zen/file_io.h> + + +namespace zen +{ +//unchecked, unformatted serialization +template <class T> T readPOD (wxInputStream& stream); +template <class T> void writePOD(wxOutputStream& stream, const T& pod); + +template <class S> S readString (wxInputStream& stream); +template <class S> 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 <class T> + T readNumberC() const; //throw FileError, checked read operation + + template <class S> + S readStringC() const; //throw FileError, checked read operation + + typedef std::shared_ptr<std::vector<char> > 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 <class T> + void writeNumberC(T number) const; //throw FileError, checked write operation + + template <class S> + void writeStringC(const S& str) const; //throw FileError, checked write operation + + void writeArrayC(const std::vector<char>& buffer) const; //throw FileError + + void check() const; + + wxOutputStream& getStream() { return stream_; } + +private: + wxOutputStream& stream_; + const wxString& errorObjName_; //used for error text only! +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//-----------------------implementation------------------------------- +template <class T> inline +T readPOD(wxInputStream& stream) +{ + T pod = 0; + stream.Read(reinterpret_cast<char*>(&pod), sizeof(T)); + return pod; +} + + +template <class T> inline +void writePOD(wxOutputStream& stream, const T& pod) +{ + stream.Write(reinterpret_cast<const char*>(&pod), sizeof(T)); +} + + +template <class S> inline +S readString(wxInputStream& stream) +{ + typedef typename S::value_type CharType; + + const auto strLength = readPOD<std::uint32_t>(stream); + if (strLength <= 1000) + { + CharType buffer[1000]; + stream.Read(buffer, sizeof(CharType) * strLength); + return S(buffer, strLength); + } + else + { + std::vector<CharType> buffer(strLength); //throw std::bad_alloc + stream.Read(&buffer[0], sizeof(CharType) * strLength); + return S(&buffer[0], strLength); + } +} + + +template <class S> inline +void writeString(wxOutputStream& stream, const S& str) +{ + writePOD(stream, static_cast<std::uint32_t>(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 <class T> +inline +T ReadInputStream::readNumberC() const //checked read operation +{ + T output = readPOD<T>(stream_); + check(); + return output; +} + + +template <class S> inline +S ReadInputStream::readStringC() const //checked read operation +{ + S output; + try + { + output = readString<S>(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<std::uint32_t>(); + CharArray buffer(new std::vector<char>(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 <class T> inline +void WriteOutputStream::writeNumberC(T number) const //checked write operation +{ + writePOD<T>(stream_, number); + check(); +} + + +template <class S> inline +void WriteOutputStream::writeStringC(const S& str) const //checked write operation +{ + writeString(stream_, str); + check(); +} + + +inline +void WriteOutputStream::writeArrayC(const std::vector<char>& buffer) const +{ + writeNumberC<std::uint32_t>(static_cast<std::uint32_t>(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 |