FStream.hxx.in 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 : public std::basic_istream<CharType, Traits>,
  152. public basic_efilebuf<CharType, Traits>
  153. {
  154. public:
  155. typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
  156. internal_buffer_type;
  157. typedef std::basic_istream<CharType, Traits> internal_stream_type;
  158. basic_ifstream()
  159. : internal_stream_type(new internal_buffer_type())
  160. {
  161. this->buf_ =
  162. static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
  163. }
  164. explicit basic_ifstream(char const* file_name,
  165. std::ios_base::openmode mode = std::ios_base::in)
  166. : internal_stream_type(new internal_buffer_type())
  167. {
  168. this->buf_ =
  169. static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
  170. open(file_name, mode);
  171. }
  172. void open(char const* file_name,
  173. std::ios_base::openmode mode = std::ios_base::in)
  174. {
  175. mode = mode | std::ios_base::in;
  176. this->_set_state(this->_open(file_name, mode), this, this);
  177. }
  178. void close() { this->_set_state(this->_close(), this, this); }
  179. using basic_efilebuf<CharType, Traits>::is_open;
  180. internal_buffer_type* rdbuf() const { return this->buf_; }
  181. ~basic_ifstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); }
  182. };
  183. template <typename CharType, typename Traits = std::char_traits<CharType> >
  184. class basic_ofstream : public std::basic_ostream<CharType, Traits>,
  185. public basic_efilebuf<CharType, Traits>
  186. {
  187. using basic_efilebuf<CharType, Traits>::is_open;
  188. public:
  189. typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
  190. internal_buffer_type;
  191. typedef std::basic_ostream<CharType, Traits> internal_stream_type;
  192. basic_ofstream()
  193. : internal_stream_type(new internal_buffer_type())
  194. {
  195. this->buf_ =
  196. static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
  197. }
  198. explicit basic_ofstream(char const* file_name,
  199. std::ios_base::openmode mode = std::ios_base::out)
  200. : internal_stream_type(new internal_buffer_type())
  201. {
  202. this->buf_ =
  203. static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
  204. open(file_name, mode);
  205. }
  206. void open(char const* file_name,
  207. std::ios_base::openmode mode = std::ios_base::out)
  208. {
  209. mode = mode | std::ios_base::out;
  210. this->_set_state(this->_open(file_name, mode), this, this);
  211. }
  212. void close() { this->_set_state(this->_close(), this, this); }
  213. internal_buffer_type* rdbuf() const { return this->buf_; }
  214. ~basic_ofstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); }
  215. };
  216. typedef basic_ifstream<char> ifstream;
  217. typedef basic_ofstream<char> ofstream;
  218. #undef @KWSYS_NAMESPACE@_FStream_NOEXCEPT
  219. #else
  220. using std::ofstream;
  221. using std::ifstream;
  222. #endif
  223. namespace FStream {
  224. enum BOM
  225. {
  226. BOM_None,
  227. BOM_UTF8,
  228. BOM_UTF16BE,
  229. BOM_UTF16LE,
  230. BOM_UTF32BE,
  231. BOM_UTF32LE
  232. };
  233. // Read a BOM, if one exists.
  234. // If a BOM exists, the stream is advanced to after the BOM.
  235. // This function requires a seekable stream (but not a relative
  236. // seekable stream).
  237. @KWSYS_NAMESPACE@_EXPORT BOM ReadBOM(std::istream& in);
  238. }
  239. }
  240. #endif