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