libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
file.hpp
Go to the documentation of this file.
1 #ifndef LIBJMMCG_CORE_FILE_HPP
2 #define LIBJMMCG_CORE_FILE_HPP
3 
4 /******************************************************************************
5 ** Copyright © 2002 by J.M.McGuiness, coder@hussar.me.uk
6 **
7 ** This library is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU Lesser General Public
9 ** License as published by the Free Software Foundation; either
10 ** version 2.1 of the License, or (at your option) any later version.
11 **
12 ** This library is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ** Lesser General Public License for more details.
16 **
17 ** You should have received a copy of the GNU Lesser General Public
18 ** License along with this library; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 
22 /**
23  \file Wrap up into a class creating a file, so that it is deleted upon object destruction. This class is completely ANSI.
24 */
25 
26 #include "exception.hpp"
27 
28 #include <cassert>
29 #include <fstream>
30 #include <string>
31 
32 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE {
33 
37 
38  /**
39  This templating is done to generalise this class. Why? There are ASCII mode files and binary ones. ASCII mode translates the CR/LF combinations. Binary does not. Also it allows this class to manage Unicode character sets. (One that use double bytes for the character set.)
40  */
41  template <typename basic_file_type,ppd::generic_traits::api_type API_,typename Mdl_>
42  class file : public basic_file_type {
43  public:
44  typedef basic_file_type file_type;
45  typedef crt_exception<API_,Mdl_> exception_type;
46 
47  file(const tstring &, const std::ios_base::openmode,const bool =true);
48  file(file const &)=delete;
49  virtual ~file();
50  file &operator=(const file &);
51  // Why is "false" always returned? That's because comparing two files
52  // is non obvious: Do I compare the file names & the contents? What
53  // about the path to the two files? One may be relative, the other
54  // may be absolute. Even if they are the *same* file, but created with
55  // the names with these different paths they'll compare different,
56  // unless I do somethig very tricky with the path situation.
57  // Why am I going on about this? Well what if you want to create a set
58  // (or map) of these "File<...>" objects you could fall foul of the
59  // fact that they require "operator<(...)" to be defined. This in turn
60  // implies that "operator==(...)" is defined to do something sensible.
61  // If you don't like this, derive from this class and override the
62  // function.
63  virtual const bool operator==(const file &) const noexcept(true) {
64  return false;
65  }
66 
67  const tstring &name(void) const noexcept(true) {
68  return fname;
69  }
70 
71  private:
72  bool auto_delete;
73  tstring fname;
74  std::ios_base::openmode mode;
75 
76  void check_open(void);
77  void remove(void);
78 
79  // I don't allow copying.
80  // Why? Well I need the file name for the current object to put the
81  // data from the input file object. How do I pass in this file name
82  // when the copy constructor only takes one parameter, and there's
83  // no way to pass in the destination file name. That's why I don't
84  // allow this.
85  explicit file(const tstring &) noexcept(true);
86  };
87 
88  template<typename basic_file_type,ppd::generic_traits::api_type API_,typename Mdl_> inline
89  file<basic_file_type,API_,Mdl_>::file(const tstring &nm, const std::ios_base::openmode flags,const bool ad)
90  : basic_file_type(nm.c_str(), flags), auto_delete(ad), fname(nm), mode(flags) {
91  check_open();
92  }
93 
94  template<typename basic_file_type,ppd::generic_traits::api_type API_,typename Mdl_> inline
95  file<basic_file_type,API_,Mdl_>::~file(void) {
96  if (auto_delete) {
97  remove();
98  }
99  }
100 
101  template<typename basic_file_type,ppd::generic_traits::api_type API_,typename Mdl_> inline file<basic_file_type,API_,Mdl_> &
102  file<basic_file_type,API_,Mdl_>::operator=(const file<basic_file_type,API_,Mdl_> &tf) {
103  remove();
104  open(tf.fname,mode|=std::ios_base::out);
105  check_open();
106  file_type::operator<<(tf.rdbuf());
107  return *this;
108  }
109 
110  template<typename basic_file_type,ppd::generic_traits::api_type API_,typename Mdl_> inline void
111  file<basic_file_type,API_,Mdl_>::check_open(void) noexcept(false) {
112  if (!file_type::is_open()) {
113  info::function desc(__LINE__,__PRETTY_FUNCTION__,typeid(&file<basic_file_type,API_,Mdl_>::check_open),info::function::argument(_T("file name"),fname));
114  desc.add_arg(info::function::argument(_T("open mode"), mode));
115  throw exception(_T("Failed to open the specified file."), desc, JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
116  }
117  }
118 
119  template<typename basic_file_type,ppd::generic_traits::api_type API_,typename Mdl_> inline void
120  file<basic_file_type,API_,Mdl_>::remove(void) noexcept(false) {
121  file_type::close();
122  if (::remove(fname.c_str())) {
123  throw exception(_T("Failed to delete the specified file."), info::function(__LINE__,__PRETTY_FUNCTION__,typeid(&file<basic_file_type,API_,Mdl_>::remove), info::function::argument(_T("file name"), fname)), JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
124  }
125  }
126 
127 } }
128 
129 #endif