zen::Xml
Simple C++ XML Processing
|
00001 // ************************************************************************** 00002 // * This file is part of the zen::Xml project. It is distributed under the * 00003 // * Boost Software License: http://www.boost.org/LICENSE_1_0.txt * 00004 // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * 00005 // ************************************************************************** 00006 00007 #ifndef ZEN_XML_IO_HEADER_8917640501480763248343343 00008 #define ZEN_XML_IO_HEADER_8917640501480763248343343 00009 00010 #include <cstdio> 00011 #include <cerrno> 00012 #include <zen/scope_guard.h> 00013 #include <zen/utf.h> 00014 #include "error.h" 00015 00016 namespace zen 00017 { 00023 #if !defined(ZEN_PLATFORM_WINDOWS) && !defined(ZEN_PLATFORM_OTHER) 00024 #error Please specify your platform: #define ZEN_PLATFORM_WINDOWS or ZEN_PLATFORM_OTHER 00025 #endif 00026 00028 struct XmlFileError : public XmlError 00029 { 00030 typedef int ErrorCode; 00031 00032 explicit XmlFileError(ErrorCode ec) : lastError(ec) {} 00034 ErrorCode lastError; 00035 }; 00036 00037 00038 #ifdef ZEN_PLATFORM_WINDOWS 00039 namespace implemenation //sad but true 00040 { 00041 template <class String> inline 00042 FILE* fopen(const String& filename, const wchar_t* mode) 00043 { 00044 #ifdef _MSC_VER 00045 FILE* handle = nullptr; 00046 errno_t rv = ::_wfopen_s(&handle, utfCvrtTo<std::wstring>(filename).c_str(), mode); //more secure? 00047 (void)rv; 00048 return handle; 00049 #else 00050 return ::_wfopen(utfCvrtTo<std::wstring>(filename).c_str(), mode); 00051 #endif 00052 } 00053 } 00054 #endif 00055 00056 00058 00064 template <class String> 00065 void saveStream(const std::string& stream, const String& filename) //throw XmlFileError 00066 { 00067 #ifdef ZEN_PLATFORM_WINDOWS 00068 FILE* handle = implemenation::fopen(utfCvrtTo<std::wstring>(filename).c_str(), L"wb"); 00069 #else 00070 FILE* handle = ::fopen(utfCvrtTo<std::string>(filename).c_str(), "w"); 00071 #endif 00072 if (handle == nullptr) 00073 throw XmlFileError(errno); 00074 ZEN_ON_SCOPE_EXIT(::fclose(handle)); 00075 00076 const size_t bytesWritten = ::fwrite(stream.c_str(), 1, stream.size(), handle); 00077 if (::ferror(handle) != 0) 00078 throw XmlFileError(errno); 00079 00080 (void)bytesWritten; 00081 assert(bytesWritten == stream.size()); 00082 } 00083 00084 00086 00092 template <class String> 00093 std::string loadStream(const String& filename) //throw XmlFileError 00094 { 00095 #ifdef ZEN_PLATFORM_WINDOWS 00096 FILE* handle = implemenation::fopen(utfCvrtTo<std::wstring>(filename).c_str(), L"rb"); 00097 #else 00098 FILE* handle = ::fopen(utfCvrtTo<std::string>(filename).c_str(), "r"); 00099 #endif 00100 if (handle == nullptr) 00101 throw XmlFileError(errno); 00102 ZEN_ON_SCOPE_EXIT(::fclose(handle)); 00103 00104 std::string stream; 00105 const size_t blockSize = 64 * 1024; 00106 do 00107 { 00108 stream.resize(stream.size() + blockSize); //let's pray std::string implements exponential growth! 00109 00110 const size_t bytesRead = ::fread(&*(stream.begin() + stream.size() - blockSize), 1, blockSize, handle); 00111 if (::ferror(handle)) 00112 throw XmlFileError(errno); 00113 if (bytesRead > blockSize) 00114 throw XmlFileError(0); 00115 if (bytesRead < blockSize) 00116 stream.resize(stream.size() - (blockSize - bytesRead)); //caveat: unsigned arithmetics 00117 } 00118 while (!::feof(handle)); 00119 00120 return stream; 00121 } 00122 } 00123 00124 #endif //ZEN_XML_IO_HEADER_8917640501480763248343343