ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

423 lines
9.9 KiB

  1. #ifndef BOOSTER_NOWIDE_FSTREAM_H
  2. #define BOOSTER_NOWIDE_FSTREAM_H
  3. #include <booster/config.h>
  4. #include <booster/nowide/convert.h>
  5. #include <fstream>
  6. #include <booster/auto_ptr_inc.h>
  7. #if defined BOOSTER_WIN_NATIVE || defined BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN
  8. #include <booster/streambuf.h>
  9. #include <booster/nowide/cstdio.h>
  10. #endif
  11. namespace booster {
  12. ///
  13. /// \brief This namespace includes implementation of basic STL's / STDLIb's functions
  14. /// such that they accept UTF-8 strings. on Windows. Otherwise it is just an alias
  15. /// of std namespace (i.e. not on Windows)
  16. ///
  17. namespace nowide {
  18. #if !defined BOOSTER_WIN_NATIVE && !defined(BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN)
  19. using std::basic_ifstream;
  20. using std::basic_ofstream;
  21. using std::basic_fstream;
  22. using std::basic_filebuf;
  23. using std::filebuf;
  24. using std::ifstream;
  25. using std::ofstream;
  26. using std::fstream;
  27. #endif
  28. #if defined(BOOSTER_WIN_NATIVE) || defined(BOOSTER_DOXYGEN_DOCS) || defined(BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN)
  29. #if defined BOOSTER_MSVC
  30. template<typename CharType,typename Traits = std::char_traits<CharType> >
  31. class basic_filebuf : public std::basic_filebuf<CharType,Traits> {
  32. public:
  33. typedef std::basic_filebuf<CharType,Traits> my_base_type;
  34. basic_filebuf *open(char const *s,std::ios_base::openmode mode)
  35. {
  36. try {
  37. if(my_base_type::open(convert(s).c_str(),mode)) {
  38. return this;
  39. }
  40. return 0;
  41. }
  42. catch(bad_utf const &e) {
  43. return 0;
  44. }
  45. }
  46. };
  47. #else // not msvc
  48. /// \cond INTERNAL
  49. namespace details {
  50. class stdio_iodev : public booster::io_device {
  51. stdio_iodev(stdio_iodev const &);
  52. void operator=(stdio_iodev const &);
  53. public:
  54. stdio_iodev(FILE *f) :
  55. file_(f)
  56. {
  57. }
  58. size_t read(char *p,size_t n)
  59. {
  60. return fread(p,1,n,file_);
  61. }
  62. size_t write(char const *p,size_t n)
  63. {
  64. size_t res = fwrite(p,1,n,file_);
  65. fflush(file_);
  66. return res;
  67. }
  68. long long seek(long long pos,io_device::pos_type t=set)
  69. {
  70. switch(t) {
  71. case cur:
  72. fseek(file_,pos,SEEK_CUR);
  73. break;
  74. case set:
  75. fseek(file_,pos,SEEK_SET);
  76. break;
  77. case end:
  78. fseek(file_,pos,SEEK_END);
  79. break;
  80. default:
  81. return -1;
  82. }
  83. return ftell(file_);
  84. }
  85. ~stdio_iodev()
  86. {
  87. fclose(file_);
  88. }
  89. private:
  90. FILE *file_;
  91. };
  92. } // details
  93. /// \endcond
  94. template<typename CharType,typename Traits = std::char_traits<CharType> >
  95. class basic_filebuf;
  96. ///
  97. /// Same as std::basic_filebuf<char> but accepts UTF-8 strings under Windows
  98. ///
  99. template<>
  100. class basic_filebuf<char> : public booster::streambuf {
  101. public:
  102. basic_filebuf() : opened_(false)
  103. {
  104. }
  105. ~basic_filebuf()
  106. {
  107. }
  108. basic_filebuf *open(char const *s,std::ios_base::openmode mode)
  109. {
  110. reset_device();
  111. bool seek_end = mode & std::ios_base::ate;
  112. if(seek_end)
  113. mode ^= std::ios_base::ate;
  114. wchar_t const *smode = get_mode(mode);
  115. if(!smode)
  116. return 0;
  117. std::wstring name;
  118. try {
  119. name = convert(s);
  120. }
  121. catch(bad_utf const &) {
  122. return 0;
  123. }
  124. FILE *f = _wfopen(name.c_str(),smode);
  125. if(!f)
  126. return 0;
  127. if(seek_end) {
  128. if(fseek(f,0,SEEK_END)!=0) {
  129. fclose(f);
  130. return 0;
  131. }
  132. }
  133. std::auto_ptr<io_device> dev(new details::stdio_iodev(f));
  134. device(dev);
  135. opened_ = true;
  136. return this;
  137. }
  138. basic_filebuf *close()
  139. {
  140. bool res = sync();
  141. reset_device();
  142. opened_ = false;
  143. return res ? this : 0;
  144. }
  145. bool is_open() const
  146. {
  147. return opened_;
  148. }
  149. private:
  150. static wchar_t const *get_mode(std::ios_base::openmode mode)
  151. {
  152. //
  153. // done according to n2914 table 106 27.9.1.4
  154. //
  155. // note can't use switch case as overload operator can't be used
  156. // in constant expression
  157. if(mode == (std::ios_base::out))
  158. return L"w";
  159. if(mode == (std::ios_base::out | std::ios_base::app))
  160. return L"a";
  161. if(mode == (std::ios_base::app))
  162. return L"a";
  163. if(mode == (std::ios_base::out | std::ios_base::trunc))
  164. return L"w";
  165. if(mode == (std::ios_base::in))
  166. return L"r";
  167. if(mode == (std::ios_base::in | std::ios_base::out))
  168. return L"r+";
  169. if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
  170. return L"w+";
  171. if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app))
  172. return L"a+";
  173. if(mode == (std::ios_base::in | std::ios_base::app))
  174. return L"a+";
  175. if(mode == (std::ios_base::binary | std::ios_base::out))
  176. return L"wb";
  177. if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app))
  178. return L"ab";
  179. if(mode == (std::ios_base::binary | std::ios_base::app))
  180. return L"ab";
  181. if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc))
  182. return L"wb";
  183. if(mode == (std::ios_base::binary | std::ios_base::in))
  184. return L"rb";
  185. if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out))
  186. return L"r+b";
  187. if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
  188. return L"w+b";
  189. if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app))
  190. return L"a+b";
  191. if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app))
  192. return L"a+b";
  193. return 0;
  194. }
  195. bool opened_;
  196. };
  197. #endif
  198. ///
  199. /// Same as std::basic_ifstream<char> but accepts UTF-8 strings under Windows
  200. ///
  201. template<typename CharType,typename Traits = std::char_traits<CharType> >
  202. class basic_ifstream : public std::basic_istream<CharType,Traits>
  203. {
  204. public:
  205. typedef basic_filebuf<CharType,Traits> internal_buffer_type;
  206. typedef std::basic_istream<CharType,Traits> internal_stream_type;
  207. basic_ifstream() :
  208. internal_stream_type(new internal_buffer_type())
  209. {
  210. buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
  211. }
  212. explicit basic_ifstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) :
  213. internal_stream_type(new internal_buffer_type())
  214. {
  215. buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
  216. open(file_name,mode);
  217. }
  218. void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in)
  219. {
  220. if(!buf_->open(file_name,mode | std::ios_base::in)) {
  221. this->setstate(std::ios_base::failbit);
  222. }
  223. else {
  224. this->clear();
  225. }
  226. }
  227. bool is_open()
  228. {
  229. return buf_->is_open();
  230. }
  231. bool is_open() const
  232. {
  233. return buf_->is_open();
  234. }
  235. void close()
  236. {
  237. if(!buf_->close())
  238. this->setstate(std::ios_base::failbit);
  239. else
  240. this->clear();
  241. }
  242. internal_buffer_type *rdbuf() const
  243. {
  244. return buf_.get();
  245. }
  246. ~basic_ifstream()
  247. {
  248. buf_->close();
  249. }
  250. private:
  251. std::auto_ptr<internal_buffer_type> buf_;
  252. };
  253. ///
  254. /// Same as std::basic_ofstream<char> but accepts UTF-8 strings under Windows
  255. ///
  256. template<typename CharType,typename Traits = std::char_traits<CharType> >
  257. class basic_ofstream : public std::basic_ostream<CharType,Traits>
  258. {
  259. public:
  260. typedef basic_filebuf<CharType,Traits> internal_buffer_type;
  261. typedef std::basic_ostream<CharType,Traits> internal_stream_type;
  262. basic_ofstream() :
  263. internal_stream_type(new internal_buffer_type())
  264. {
  265. buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
  266. }
  267. explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) :
  268. internal_stream_type(new internal_buffer_type())
  269. {
  270. buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
  271. open(file_name,mode);
  272. }
  273. void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out)
  274. {
  275. if(!buf_->open(file_name,mode | std::ios_base::out)) {
  276. this->setstate(std::ios_base::failbit);
  277. }
  278. else {
  279. this->clear();
  280. }
  281. }
  282. bool is_open()
  283. {
  284. return buf_->is_open();
  285. }
  286. bool is_open() const
  287. {
  288. return buf_->is_open();
  289. }
  290. void close()
  291. {
  292. if(!buf_->close())
  293. this->setstate(std::ios_base::failbit);
  294. else
  295. this->clear();
  296. }
  297. internal_buffer_type *rdbuf() const
  298. {
  299. return buf_.get();
  300. }
  301. ~basic_ofstream()
  302. {
  303. buf_->close();
  304. }
  305. private:
  306. std::auto_ptr<internal_buffer_type> buf_;
  307. };
  308. ///
  309. /// Same as std::basic_fstream<char> but accepts UTF-8 strings under Windows
  310. ///
  311. template<typename CharType,typename Traits = std::char_traits<CharType> >
  312. class basic_fstream : public std::basic_iostream<CharType,Traits>
  313. {
  314. public:
  315. typedef basic_filebuf<CharType,Traits> internal_buffer_type;
  316. typedef std::basic_iostream<CharType,Traits> internal_stream_type;
  317. basic_fstream() :
  318. internal_stream_type(new internal_buffer_type())
  319. {
  320. buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
  321. }
  322. explicit basic_fstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) :
  323. internal_stream_type(new internal_buffer_type())
  324. {
  325. buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
  326. open(file_name,mode);
  327. }
  328. void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out)
  329. {
  330. if(!buf_->open(file_name,mode)) {
  331. this->setstate(std::ios_base::failbit);
  332. }
  333. else {
  334. this->clear();
  335. }
  336. }
  337. bool is_open()
  338. {
  339. return buf_->is_open();
  340. }
  341. bool is_open() const
  342. {
  343. return buf_->is_open();
  344. }
  345. void close()
  346. {
  347. if(!buf_->close())
  348. this->setstate(std::ios_base::failbit);
  349. else
  350. this->clear();
  351. }
  352. internal_buffer_type *rdbuf() const
  353. {
  354. return buf_.get();
  355. }
  356. ~basic_fstream()
  357. {
  358. buf_->close();
  359. }
  360. private:
  361. std::auto_ptr<internal_buffer_type> buf_;
  362. };
  363. ///
  364. /// Same as std::filebuf but accepts UTF-8 strings under Windows
  365. ///
  366. typedef basic_filebuf<char> filebuf;
  367. ///
  368. /// Same as std::ifstream but accepts UTF-8 strings under Windows
  369. ///
  370. typedef basic_ifstream<char> ifstream;
  371. ///
  372. /// Same as std::ofstream but accepts UTF-8 strings under Windows
  373. ///
  374. typedef basic_ofstream<char> ofstream;
  375. ///
  376. /// Same as std::fstream but accepts UTF-8 strings under Windows
  377. ///
  378. typedef basic_fstream<char> fstream;
  379. #endif
  380. } // nowide
  381. } // booster
  382. #endif