zen::Xml
Simple C++ XML Processing
 All Classes Namespaces Functions Variables Pages
io.h
1 // **************************************************************************
2 // * This file is part of the FreeFileSync project. It is distributed under *
3 // * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
4 // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
5 // **************************************************************************
6 
7 #ifndef ZEN_XML_IO_HEADER_8917640501480763248343343
8 #define ZEN_XML_IO_HEADER_8917640501480763248343343
9 
10 #include <cstdio>
11 #include <cerrno>
12 #include <zen/scope_guard.h>
13 #include <zen/utf.h>
14 #include "error.h"
15 
16 namespace zen
17 {
23 #if !defined(ZEN_WIN) && !defined(ZEN_LINUX) && !defined(ZEN_MAC)
24 #error Please specify your platform: #define ZEN_WIN, ZEN_LINUX or ZEN_MAC
25 #endif
26 
27 
29 struct XmlFileError : public XmlError
30 {
31  typedef int ErrorCode;
32 
33  explicit XmlFileError(ErrorCode ec) : lastError(ec) {}
35  ErrorCode lastError;
36 };
37 
38 
39 #ifdef ZEN_WIN
40 namespace implemenation //sad but true
41 {
42 template <class String> inline
43 FILE* fopen(const String& filename, const wchar_t* mode)
44 {
45 #ifdef _MSC_VER
46  FILE* handle = nullptr;
47  errno_t rv = ::_wfopen_s(&handle, utfCvrtTo<std::wstring>(filename).c_str(), mode); //more secure?
48  (void)rv;
49  return handle;
50 #else
51  return ::_wfopen(utfCvrtTo<std::wstring>(filename).c_str(), mode);
52 #endif
53 }
54 }
55 #endif
56 
57 
59 
65 template <class String>
66 void saveStream(const std::string& stream, const String& filename) //throw XmlFileError
67 {
68 #ifdef ZEN_WIN
69  FILE* handle = implemenation::fopen(utfCvrtTo<std::wstring>(filename).c_str(), L"wb");
70 #else
71  FILE* handle = ::fopen(utfCvrtTo<std::string>(filename).c_str(), "w");
72 #endif
73  if (handle == nullptr)
74  throw XmlFileError(errno);
75  ZEN_ON_SCOPE_EXIT(::fclose(handle));
76 
77  const size_t bytesWritten = ::fwrite(stream.c_str(), 1, stream.size(), handle);
78  if (::ferror(handle) != 0)
79  throw XmlFileError(errno);
80 
81  (void)bytesWritten;
82  assert(bytesWritten == stream.size());
83 }
84 
85 
87 
93 template <class String>
94 std::string loadStream(const String& filename) //throw XmlFileError
95 {
96 #ifdef ZEN_WIN
97  FILE* handle = implemenation::fopen(utfCvrtTo<std::wstring>(filename).c_str(), L"rb");
98 #else
99  FILE* handle = ::fopen(utfCvrtTo<std::string>(filename).c_str(), "r");
100 #endif
101  if (handle == nullptr)
102  throw XmlFileError(errno);
103  ZEN_ON_SCOPE_EXIT(::fclose(handle));
104 
105  std::string stream;
106  const size_t blockSize = 64 * 1024;
107  do
108  {
109  stream.resize(stream.size() + blockSize); //let's pray std::string implements exponential growth!
110 
111  const size_t bytesRead = ::fread(&*(stream.begin() + stream.size() - blockSize), 1, blockSize, handle);
112  if (::ferror(handle))
113  throw XmlFileError(errno);
114  if (bytesRead > blockSize)
115  throw XmlFileError(0);
116  if (bytesRead < blockSize)
117  stream.resize(stream.size() - (blockSize - bytesRead)); //caveat: unsigned arithmetics
118  }
119  while (!::feof(handle));
120 
121  return stream;
122 }
123 }
124 
125 #endif //ZEN_XML_IO_HEADER_8917640501480763248343343
void saveStream(const std::string &stream, const String &filename)
Save byte stream to a file.
Definition: io.h:66
std::string loadStream(const String &filename)
Load byte stream from a file.
Definition: io.h:94
ErrorCode lastError
Native error code: errno.
Definition: io.h:35
Exception thrown due to failed file I/O.
Definition: io.h:29
Exception base class for zen::Xml.
Definition: error.h:13