FStream.hxx.in 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
  3. #ifndef @KWSYS_NAMESPACE@_FStream_hxx
  4. #define @KWSYS_NAMESPACE@_FStream_hxx
  5. #include <@KWSYS_NAMESPACE@/Configure.hxx>
  6. #include <@KWSYS_NAMESPACE@/Encoding.hxx>
  7. #include <fstream>
  8. #if defined(_WIN32)
  9. # if !defined(_MSC_VER) && @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
  10. # include <ext/stdio_filebuf.h>
  11. # endif
  12. #endif
  13. namespace @KWSYS_NAMESPACE@ {
  14. #if defined(_WIN32) && \
  15. (defined(_MSC_VER) || @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H)
  16. # if defined(_NOEXCEPT)
  17. # define @KWSYS_NAMESPACE@_FStream_NOEXCEPT _NOEXCEPT
  18. # else
  19. # define @KWSYS_NAMESPACE@_FStream_NOEXCEPT
  20. # endif
  21. # if defined(_MSC_VER)
  22. template <typename CharType, typename Traits>
  23. class basic_filebuf : public std::basic_filebuf<CharType, Traits>
  24. {
  25. # if _MSC_VER >= 1400
  26. public:
  27. typedef std::basic_filebuf<CharType, Traits> my_base_type;
  28. basic_filebuf* open(char const* s, std::ios_base::openmode mode)
  29. {
  30. const std::wstring wstr = Encoding::ToWindowsExtendedPath(s);
  31. return static_cast<basic_filebuf*>(my_base_type::open(wstr.c_str(), mode));
  32. }
  33. # endif
  34. };
  35. # else
  36. inline std::wstring getcmode(const std::ios_base::openmode mode)
  37. {
  38. std::wstring cmode;
  39. bool plus = false;
  40. if (mode & std::ios_base::app) {
  41. cmode += L"a";
  42. plus = mode & std::ios_base::in ? true : false;
  43. } else if (mode & std::ios_base::trunc ||
  44. (mode & std::ios_base::out && (mode & std::ios_base::in) == 0)) {
  45. cmode += L"w";
  46. plus = mode & std::ios_base::in ? true : false;
  47. } else {
  48. cmode += L"r";
  49. plus = mode & std::ios_base::out ? true : false;
  50. }
  51. if (plus) {
  52. cmode += L"+";
  53. }
  54. if (mode & std::ios_base::binary) {
  55. cmode += L"b";
  56. } else {
  57. cmode += L"t";
  58. }
  59. return cmode;
  60. };
  61. # endif
  62. template <typename CharType, typename Traits = std::char_traits<CharType> >
  63. class basic_efilebuf
  64. {
  65. public:
  66. # if defined(_MSC_VER)
  67. typedef basic_filebuf<CharType, Traits> internal_buffer_type;
  68. # else
  69. typedef __gnu_cxx::stdio_filebuf<CharType, Traits> internal_buffer_type;
  70. # endif
  71. basic_efilebuf()
  72. : file_(0)
  73. {
  74. buf_ = 0;
  75. }
  76. bool _open(char const* file_name, std::ios_base::openmode mode)
  77. {
  78. if (_is_open() || file_) {
  79. return false;
  80. }
  81. # if defined(_MSC_VER)
  82. const bool success = buf_->open(file_name, mode) != 0;
  83. # else
  84. const std::wstring wstr = Encoding::ToWindowsExtendedPath(file_name);
  85. bool success = false;
  86. std::wstring cmode = getcmode(mode);
  87. file_ = _wfopen(wstr.c_str(), cmode.c_str());
  88. if (file_) {
  89. if (buf_) {
  90. delete buf_;
  91. }
  92. buf_ = new internal_buffer_type(file_, mode);
  93. success = true;
  94. }
  95. # endif
  96. return success;
  97. }
  98. bool _is_open()
  99. {
  100. if (!buf_) {
  101. return false;
  102. }
  103. return buf_->is_open();
  104. }
  105. bool _is_open() const
  106. {
  107. if (!buf_) {
  108. return false;
  109. }
  110. return buf_->is_open();
  111. }
  112. bool _close()
  113. {
  114. bool success = false;
  115. if (buf_) {
  116. success = buf_->close() != 0;
  117. # if !defined(_MSC_VER)
  118. if (file_) {
  119. success = fclose(file_) == 0 ? success : false;
  120. file_ = 0;
  121. }
  122. # endif
  123. }
  124. return success;
  125. }
  126. static void _set_state(bool success, std::basic_ios<CharType, Traits>* ios,
  127. basic_efilebuf* efilebuf)
  128. {
  129. # if !defined(_MSC_VER)
  130. ios->rdbuf(efilebuf->buf_);
  131. # else
  132. static_cast<void>(efilebuf);
  133. # endif
  134. if (!success) {
  135. ios->setstate(std::ios_base::failbit);
  136. } else {
  137. ios->clear();
  138. }
  139. }
  140. ~basic_efilebuf()
  141. {
  142. if (buf_) {
  143. delete buf_;
  144. }
  145. }
  146. protected:
  147. internal_buffer_type* buf_;
  148. FILE* file_;
  149. };
  150. template <typename CharType, typename Traits = std::char_traits<CharType> >
  151. class basic_ifstream
  152. : public std::basic_istream<CharType, Traits>
  153. , public basic_efilebuf<CharType, Traits>
  154. {
  155. public:
  156. typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
  157. internal_buffer_type;
  158. typedef std::basic_istream<CharType, Traits> internal_stream_type;
  159. basic_ifstream()
  160. : internal_stream_type(new internal_buffer_type())
  161. {
  162. this->buf_ =
  163. static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
  164. }
  165. explicit basic_ifstream(char const* file_name,
  166. std::ios_base::openmode mode = std::ios_base::in)
  167. : internal_stream_type(new internal_buffer_type())
  168. {
  169. this->buf_ =
  170. static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
  171. open(file_name, mode);
  172. }
  173. void open(char const* file_name,
  174. std::ios_base::openmode mode = std::ios_base::in)
  175. {
  176. mode = mode | std::ios_base::in;
  177. this->_set_state(this->_open(file_name, mode), this, this);
  178. }
  179. bool is_open() { return this->_is_open(); }
  180. void close() { this->_set_state(this->_close(), this, this); }
  181. using basic_efilebuf<CharType, Traits>::_is_open;
  182. internal_buffer_type* rdbuf() const { return this->buf_; }
  183. ~basic_ifstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); }
  184. };
  185. template <typename CharType, typename Traits = std::char_traits<CharType> >
  186. class basic_ofstream
  187. : public std::basic_ostream<CharType, Traits>
  188. , public basic_efilebuf<CharType, Traits>
  189. {
  190. using basic_efilebuf<CharType, Traits>::_is_open;
  191. public:
  192. typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
  193. internal_buffer_type;
  194. typedef std::basic_ostream<CharType, Traits> internal_stream_type;
  195. basic_ofstream()
  196. : internal_stream_type(new internal_buffer_type())
  197. {
  198. this->buf_ =
  199. static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
  200. }
  201. explicit basic_ofstream(char const* file_name,
  202. std::ios_base::openmode mode = std::ios_base::out)
  203. : internal_stream_type(new internal_buffer_type())
  204. {
  205. this->buf_ =
  206. static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
  207. open(file_name, mode);
  208. }
  209. void open(char const* file_name,
  210. std::ios_base::openmode mode = std::ios_base::out)
  211. {
  212. mode = mode | std::ios_base::out;
  213. this->_set_state(this->_open(file_name, mode), this, this);
  214. }
  215. void close() { this->_set_state(this->_close(), this, this); }
  216. bool is_open() { return this->_is_open(); }
  217. internal_buffer_type* rdbuf() const { return this->buf_; }
  218. ~basic_ofstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); }
  219. };
  220. typedef basic_ifstream<char> ifstream;
  221. typedef basic_ofstream<char> ofstream;
  222. # undef @KWSYS_NAMESPACE@_FStream_NOEXCEPT
  223. #else
  224. using std::ofstream;
  225. using std::ifstream;
  226. #endif
  227. namespace FStream {
  228. enum BOM
  229. {
  230. BOM_None,
  231. BOM_UTF8,
  232. BOM_UTF16BE,
  233. BOM_UTF16LE,
  234. BOM_UTF32BE,
  235. BOM_UTF32LE
  236. };
  237. // Read a BOM, if one exists.
  238. // If a BOM exists, the stream is advanced to after the BOM.
  239. // This function requires a seekable stream (but not a relative
  240. // seekable stream).
  241. @KWSYS_NAMESPACE@_EXPORT BOM ReadBOM(std::istream& in);
  242. }
  243. }
  244. #endif