diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:23:19 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:23:19 +0200 |
commit | 0887aee8c54d0ed51bb2031431e2bcdafebb4c6e (patch) | |
tree | 69537ceb9787bb25ac363cc4e6cdaf0804d78363 /zenxml/io.h | |
parent | 5.12 (diff) | |
download | FreeFileSync-0887aee8c54d0ed51bb2031431e2bcdafebb4c6e.tar.gz FreeFileSync-0887aee8c54d0ed51bb2031431e2bcdafebb4c6e.tar.bz2 FreeFileSync-0887aee8c54d0ed51bb2031431e2bcdafebb4c6e.zip |
5.13
Diffstat (limited to 'zenxml/io.h')
-rw-r--r-- | zenxml/io.h | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/zenxml/io.h b/zenxml/io.h new file mode 100644 index 00000000..4286ae6c --- /dev/null +++ b/zenxml/io.h @@ -0,0 +1,124 @@ +// ************************************************************************** +// * This file is part of the zenXML project. It is distributed under the * +// * Boost Software License: http://www.boost.org/LICENSE_1_0.txt * +// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * +// ************************************************************************** + +#ifndef ZEN_XML_IO_HEADER_8917640501480763248343343 +#define ZEN_XML_IO_HEADER_8917640501480763248343343 + +#include <cstdio> +#include <cerrno> +#include <zen/scope_guard.h> +#include <zen/utf.h> +#include "error.h" + +namespace zen +{ +/** +\file +\brief Save and load byte streams from files +*/ + +#if !defined(ZEN_PLATFORM_WINDOWS) && !defined(ZEN_PLATFORM_OTHER) +#error Please specify your platform: #define ZEN_PLATFORM_WINDOWS or ZEN_PLATFORM_OTHER +#endif + +///Exception thrown due to failed file I/O +struct XmlFileError : public XmlError +{ + typedef int ErrorCode; + + explicit XmlFileError(ErrorCode ec) : lastError(ec) {} + ///Native error code: errno + ErrorCode lastError; +}; + + +#ifdef ZEN_PLATFORM_WINDOWS +namespace implemenation //sad but true +{ +template <class String> inline +FILE* fopen(const String& filename, const wchar_t* mode) +{ +#ifdef _MSC_VER + FILE* handle = nullptr; + errno_t rv = ::_wfopen_s(&handle, utfCvrtTo<std::wstring>(filename).c_str(), mode); //more secure? + (void)rv; + return handle; +#else + return ::_wfopen(utfCvrtTo<std::wstring>(filename).c_str(), mode); +#endif +} +} +#endif + + +///Save byte stream to a file +/** +\tparam String Arbitrary string-like type: e.g. std::string, wchar_t*, char[], wchar_t, wxString, MyStringClass, ... +\param stream Input byte stream +\param filename Output file name +\throw XmlFileError +*/ +template <class String> +void saveStream(const std::string& stream, const String& filename) //throw XmlFileError +{ +#ifdef ZEN_PLATFORM_WINDOWS + FILE* handle = implemenation::fopen(utfCvrtTo<std::wstring>(filename).c_str(), L"wb"); +#else + FILE* handle = ::fopen(utfCvrtTo<std::string>(filename).c_str(), "w"); +#endif + if (handle == nullptr) + throw XmlFileError(errno); + ZEN_ON_SCOPE_EXIT(::fclose(handle)); + + const size_t bytesWritten = ::fwrite(stream.c_str(), 1, stream.size(), handle); + if (::ferror(handle) != 0) + throw XmlFileError(errno); + + (void)bytesWritten; + assert(bytesWritten == stream.size()); +} + + +///Load byte stream from a file +/** +\tparam String Arbitrary string-like type: e.g. std::string, wchar_t*, char[], wchar_t, wxString, MyStringClass, ... +\param filename Input file name +\return Output byte stream +\throw XmlFileError +*/ +template <class String> +std::string loadStream(const String& filename) //throw XmlFileError +{ +#ifdef ZEN_PLATFORM_WINDOWS + FILE* handle = implemenation::fopen(utfCvrtTo<std::wstring>(filename).c_str(), L"rb"); +#else + FILE* handle = ::fopen(utfCvrtTo<std::string>(filename).c_str(), "r"); +#endif + if (handle == nullptr) + throw XmlFileError(errno); + ZEN_ON_SCOPE_EXIT(::fclose(handle)); + + std::string stream; + const size_t blockSize = 64 * 1024; + do + { + stream.resize(stream.size() + blockSize); //let's pray std::string implements exponential growth! + + const size_t bytesRead = ::fread(&*(stream.begin() + stream.size() - blockSize), 1, blockSize, handle); + if (::ferror(handle)) + throw XmlFileError(errno); + if (bytesRead > blockSize) + throw XmlFileError(0); + if (bytesRead < blockSize) + stream.resize(stream.size() - (blockSize - bytesRead)); //caveat: unsigned arithmetics + } + while (!::feof(handle)); + + return stream; +} +} + +#endif //ZEN_XML_IO_HEADER_8917640501480763248343343 |