powerd++  0.4.4
io.hpp
Go to the documentation of this file.
1 
7 #ifndef _POWERDXX_SYS_IO_HPP_
8 #define _POWERDXX_SYS_IO_HPP_
9 
10 #include <cstdio> /* fopen(), fprintf() etc. */
11 #include <utility> /* std::swap() */
12 
13 namespace sys {
14 
18 namespace io {
19 
25 enum class feature {
31  read,
32 
38  write,
39 
45  seek,
46 };
47 
49 static constexpr auto const read = feature::read;
51 static constexpr auto const write = feature::write;
53 static constexpr auto const seek = feature::seek;
54 
58 enum class ownership {
64  own,
65 
71  link,
72 };
73 
75 static constexpr auto const own = ownership::own;
77 static constexpr auto const link = ownership::link;
78 
92 template <ownership Ownership, feature ... Features> class file;
93 
100 template <bool, class T = void> struct enable_if {
104  using type = T;
105 
109  static constexpr bool const value{true};
110 };
111 
118 template <class T> struct enable_if<false, T> {
122  static constexpr bool const value{false};
123 };
124 
131 template <auto ... Set> struct set {};
132 
141 template <class SetT, auto Value> struct contains;
142 
151 template <auto ... Set, auto Value>
152 struct contains<set<Set ...>, Value> : enable_if<((Set == Value) || ...)> {};
153 
155 template <class SetT, auto Value>
157 
159 template <class SetT, auto Value>
161 
168 template <class LSetT, class RSetT> struct is_superset_of;
169 
178 template <class LSetT, auto ... RSet>
179 struct is_superset_of<LSetT, set<RSet ...>> :
180  enable_if<(contains_v<LSetT, RSet> && ...)> {};
181 
183 template <class LSetT, class RSetT>
185 
187 template <class LSetT, class RSetT>
189 
193 struct query {
197  struct contains_ftor {
201  char const * const str;
202 
211  constexpr bool operator ()(char const ch) const {
212  for (auto it = str; it && *it; ++it) {
213  if (*it == ch) {
214  return true;
215  }
216  }
217  return false;
218  }
219 
232  template <typename ... CharTs>
233  constexpr bool any(CharTs const ... chars) const {
234  for (auto it = str; it && *it; ++it) {
235  if (((*it == chars) || ...)) {
236  return true;
237  }
238  }
239  return false;
240  }
241 
254  template <typename ... CharTs>
255  constexpr bool all(CharTs const ... chars) const {
256  for (auto ch : {chars ...}) {
257  bool match{false};
258  for (auto it = str; it && *it && !match; ++it) {
259  match = (ch == *it);
260  }
261  if (!match) {
262  return false;
263  }
264  }
265  return true;
266  }
267  } const contains;
268 };
269 
279 template <class FileT, feature ...>
281  protected:
285  FILE * handle;
286 
290  operator FileT &() {
291  return *static_cast<FileT *>(this);
292  }
293 
300  file_feature(FILE * const handle) : handle{handle} {}
301 
302  public:
315  explicit operator bool() const {
316  return this->handle && !feof(this->handle) &&
317  !ferror(this->handle);
318  }
319 
328  bool eof() const {
329  return this->handle && feof(this->handle);
330  }
331 
340  bool error() const {
341  return this->handle && ferror(this->handle);
342  }
343 };
344 
353 template <class FileT, feature ... Tail>
354 class file_feature<FileT, read, Tail ...> :
355  public file_feature<FileT, Tail ...> {
356  public:
357  using file_feature<FileT, Tail ...>::file_feature;
358 
366  int getc() {
367  if (this->handle) {
368  return fgetc(this->handle);
369  }
370  return EOF;
371  }
372 
384  template <typename T>
385  std::size_t read(T & dst) {
386  if (this->handle) {
387  return fread(&dst, sizeof(T), 1, this->handle);
388  }
389  return 0;
390  }
391 
407  template <typename T, std::size_t Count>
408  std::size_t read(T (& dst)[Count], std::size_t const count) {
409  if (this->handle) {
410  return fread(&dst, sizeof(T),
411  (count <= Count ? count : Count),
412  this->handle);
413  }
414  return 0;
415  }
416 
434  template <auto CountFmt, typename ... RefTs>
435  int scanf(char const (& fmt)[CountFmt], RefTs & ... refs) {
436  if (this->handle) {
437  return fscanf(this->handle, fmt, &refs ...);
438  }
439  return EOF;
440  }
441 
459  template <auto Count>
460  bool gets(char (& dst)[Count]) {
461  return this->handle && fgets(dst, Count, this->handle);
462  }
463 };
464 
473 template <class FileT, feature ... Tail>
474 class file_feature<FileT, write, Tail ...> :
475  public file_feature<FileT, Tail ...> {
476  public:
477  using file_feature<FileT, Tail ...>::file_feature;
478 
494  template <auto CountFmt, typename ... ArgTs>
495  FileT & printf(char const (& fmt)[CountFmt], ArgTs const & ... args) {
496  if (this->handle) {
497  fprintf(this->handle, fmt, args ...);
498  }
499  return *this;
500  }
501 
517  template <auto CountFmt>
518  FileT & printf(char const (& fmt)[CountFmt]) {
519  if (this->handle) {
520  fprintf(this->handle, fmt, 0);
521  }
522  return *this;
523  }
524 
540  template <std::size_t Count>
541  FileT & print(char const (& msg)[Count]) {
542  if (this->handle) {
543  fwrite(msg, sizeof(char), Count - 1, this->handle);
544  }
545  return *this;
546  }
547 
557  FileT & putc(int const character) {
558  if (this->handle) {
559  fputc(character, this->handle);
560  }
561  return *this;
562  }
563 
575  template <typename T>
576  FileT & write(T const & src) {
577  if (this->handle) {
578  fwrite(&src, sizeof(T), 1, this->handle);
579  }
580  return *this;
581  }
582 
598  template <typename T, std::size_t Count>
599  FileT & write(T const (& src)[Count], std::size_t const count) {
600  if (this->handle) {
601  fwrite(&src, sizeof(T),
602  (count <= Count ? count : Count),
603  this->handle);
604  }
605  return *this;
606  }
607 
615  FileT & flush() {
616  if (this->handle) {
617  fflush(this->handle);
618  }
619  return *this;
620  }
621 };
622 
631 template <class FileT, feature ... Tail>
632 class file_feature<FileT, seek, Tail ...> :
633  public file_feature<FileT, Tail ...> {
634  public:
635  using file_feature<FileT, Tail ...>::file_feature;
636 
650  FileT & seek(long int const offset, int const origin) {
651  if (this->handle) {
652  fseek(this->handle, offset, origin);
653  }
654  return *this;
655  }
656 
664  FileT & rewind() {
665  if (this->handle) {
666  frewind(this->handle);
667  }
668  return *this;
669  }
670 
678  long int tell() {
679  if (this->handle) {
680  return ftell(this->handle);
681  }
682  return -1;
683  }
684 };
685 
700 template <feature ... Features>
701 class file<own, Features ...> final :
702  public file_feature<file<own, Features ...>, Features ...> {
706  template <ownership, feature ...> friend class file;
707 
708  public:
713  file(file const &) = delete;
714 
721  file(file && move) : file{move.release()} {}
722 
732  explicit file(FILE * const handle) :
733  file_feature<file, Features ...>{handle} {}
734 
738  file() : file{nullptr} {}
739 
751  template <feature ... Superset,
752  class = is_superset_of_t<set<Superset ...>,
753  set<Features ...>>>
755  file{move.release()} {}
756 
783  file(char const * const filename, char const * const mode) :
784  file{(!filename || !mode ||
785  (contains_v<set<Features ...>, write> &&
786  !query{mode}.contains.any('w', '+')) ||
787  (contains_v<set<Features ...>, read> &&
788  !query{mode}.contains.any('r', '+')) ||
789  (contains_v<set<Features ...>, seek> &&
790  query{mode}.contains('a') && !query{mode}.contains('+')))
791  ? nullptr : fopen(filename, mode)} {}
792 
796  ~file() {
797  close();
798  }
799 
808  file & operator =(file && move) {
809  std::swap(this->handle, move.handle);
810  return *this;
811  }
812 
826  template <feature ... Superset,
827  class = is_superset_of_t<set<Superset ...>, set<Features ...>>>
828  file & operator =(file<own, Superset ...> && move) {
829  std::swap(this->handle, move.handle);
830  return *this;
831  }
832 
841  FILE * get() const {
842  return this->handle;
843  }
844 
853  FILE * release() {
854  auto const handle = this->handle;
855  this->handle = nullptr;
856  return handle;
857  }
858 
865  file & close() {
866  if (this->handle) {
867  fclose(this->handle);
868  this->handle = nullptr;
869  }
870  return *this;
871  }
872 
873 };
874 
889 template <feature ... Features>
890 class file<link, Features ...> final :
891  public file_feature<file<link, Features ...>, Features ...> {
892  public:
902  explicit file(FILE * const handle) :
903  file_feature<file, Features ...>{handle} {}
904 
908  file() : file{nullptr} {}
909 
925  template <ownership Ownership, feature ... Superset,
926  class = is_superset_of_t<set<Superset ...>, set<Features ...>>>
927  file(file<Ownership, Superset ...> const & copy) : file{copy.get()} {}
928 
935  template <feature ... Superset,
936  class = is_superset_of_t<set<Superset ...>, set<Features ...>>>
937  file(file<own, Superset ...> &&) = delete;
938 
956  template <ownership Ownership, feature ... Superset,
957  class = is_superset_of_t<set<Superset ...>, set<Features ...>>>
958  file & operator =(file<Ownership, Superset ...> const & copy) {
959  this->handle = copy.get();
960  return *this;
961  }
962 
971  template <feature ... Superset,
972  class = is_superset_of_t<set<Superset ...>, set<Features ...>>>
973  file & operator =(file<own, Superset ...> &&) = delete;
974 
983  FILE * get() const {
984  return this->handle;
985  }
986 };
987 
1007 inline file<link, write> ferr{stderr};
1008 
1012 inline file<link, write> fout{stdout};
1013 
1017 inline file<link, read> fin{stdin};
1018 
1021 } /* namespace io */
1022 
1023 } /* namespace sys */
1024 
1025 #endif /* _POWERDXX_SYS_IO_HPP_ */
sys::io::ownership::own
@ own
The file instance owns the FILE object.
sys::io::file< own, Features ... >::file
file(FILE *const handle)
Take ownership of the given FILE object.
Definition: io.hpp:732
sys::io::file_feature< FileT, write, Tail ... >::write
FileT & write(T const &src)
Write an object to file.
Definition: io.hpp:576
sys::io::file< own, Features ... >::file
file(file< own, Superset ... > &&move)
Move construct from another owning file type instance.
Definition: io.hpp:754
sys::io::file_feature< FileT, write, Tail ... >::print
FileT & print(char const (&msg)[Count])
Print an unformatted string, excluding the last character.
Definition: io.hpp:541
sys::io::file< own, Features ... >::~file
~file()
Free all resources.
Definition: io.hpp:796
sys::io::enable_if<(contains_v< LSetT, RSet > &&...)>::type
void type
Provide the requested type.
Definition: io.hpp:104
sys::io::query
Ask questions about the contents of a string.
Definition: io.hpp:193
sys::io::contains
Check whether a set type contains a value.
Definition: io.hpp:141
sys::io::file_feature< FileT, write, Tail ... >::flush
FileT & flush()
Flush file buffers.
Definition: io.hpp:615
sys::io::file< own, Features ... >::file
file()
Default construct.
Definition: io.hpp:738
sys::io::fout
file< link, write > fout
File access instances for stdout.
Definition: io.hpp:1012
sys::io::feature::seek
@ seek
The file type supports seek operations.
sys
Wrappers around native system interfaces.
sys::io::query::contains_ftor
Test a string whether it contains a set of characters.
Definition: io.hpp:197
sys::io::file_feature< FileT, write, Tail ... >::printf
FileT & printf(char const (&fmt)[CountFmt])
Output a printf style formatted string.
Definition: io.hpp:518
sys::io::is_superset_of_t
typename is_superset_of< LSetT, RSetT >::type is_superset_of_t
Check whether the left hand set is a superest of the right hand set.
Definition: io.hpp:188
sys::io::feature
feature
Feature flags for file type composition.
Definition: io.hpp:25
anonymous_namespace{loadplay.cpp}::filename
const char * filename(char const *const path)
Performs very rudimentary file name argument checks.
Definition: loadplay.cpp:77
sys::io::file_feature< FileT, seek, Tail ... >::tell
long int tell()
Retrieve the current file position.
Definition: io.hpp:678
sys::io::enable_if::value
static constexpr const bool value
The given expression is true.
Definition: io.hpp:109
sys::io::is_superset_of
Check whether the left hand set is a superest of the right hand set.
Definition: io.hpp:168
sys::io::file_feature< FileT, read, Tail ... >::read
std::size_t read(T(&dst)[Count], std::size_t const count)
Read the requested number of objects from the file.
Definition: io.hpp:408
sys::io::file_feature< FileT, seek, Tail ... >::seek
FileT & seek(long int const offset, int const origin)
Seek file position.
Definition: io.hpp:650
sys::io::file< own, Features ... >::close
file & close()
Close the file.
Definition: io.hpp:865
sys::io::file_feature< FileT, write, Tail ... >::printf
FileT & printf(char const (&fmt)[CountFmt], ArgTs const &... args)
Output with printf style formatting.
Definition: io.hpp:495
sys::io::enable_if
Similar to std::enable_if, but it also has the value of the expression.
Definition: io.hpp:100
sys::io::file_feature< FileT, read, Tail ... >::scanf
int scanf(char const (&fmt)[CountFmt], RefTs &... refs)
Read formatted input.
Definition: io.hpp:435
sys::io::file< own, Features ... >::get
FILE * get() const
Provide the internal FILE object pointer.
Definition: io.hpp:841
sys::io::file_feature
Implements the base functionality of all file access types.
Definition: io.hpp:280
sys::io::file< own, Features ... >::file
file(char const *const filename, char const *const mode)
Open a file by name.
Definition: io.hpp:783
sys::io::fin
file< link, read > fin
File access instances for stdin.
Definition: io.hpp:1017
sys::io::query::contains
struct sys::io::query::contains_ftor contains
Query the string for characters.
sys::io::set
Pack a set of integral values in a type.
Definition: io.hpp:131
sys::io::file_feature< FileT, seek, Tail ... >::rewind
FileT & rewind()
Reset file position to the beginning of the file.
Definition: io.hpp:664
sys::io::file< own, Features ... >::file
file(file &&move)
Move construct from a temporary.
Definition: io.hpp:721
sys::io::ownership
ownership
Ownership relation to the underlying FILE object.
Definition: io.hpp:58
sys::io::file_feature< FileT, read, Tail ... >::read
std::size_t read(T &dst)
Read the given object from the file.
Definition: io.hpp:385
sys::io::file_feature::file_feature
file_feature(FILE *const handle)
Construct from a FILE object pointer.
Definition: io.hpp:300
sys::io::file_feature::error
bool error() const
Return whether the file instance is in an error state.
Definition: io.hpp:340
sys::io
This namespace contains c++ wrappers for <cstdio> functionality.
Definition: io.hpp:18
sys::io::file_feature< FileT, read, Tail ... >::getc
int getc()
Read a single character from the file.
Definition: io.hpp:366
sys::io::contains_t
typename contains< SetT, Value >::type contains_t
Check whether a set type contains a value.
Definition: io.hpp:160
sys::io::file< own, Features ... >::release
FILE * release()
Surrender ownership of the internal FILE object pointer.
Definition: io.hpp:853
sys::io::file_feature< FileT, write, Tail ... >::putc
FileT & putc(int const character)
Write a single character to the string.
Definition: io.hpp:557
sys::io::file< own, Features ... >::file
friend class file
Friend all file classes for move assignment.
Definition: io.hpp:706
sys::io::query::contains_ftor::str
const char *const str
The string to ask about.
Definition: io.hpp:201
sys::io::feature::write
@ write
The file type supports write operations.
sys::io::query::contains_ftor::all
constexpr bool all(CharTs const ... chars) const
Check for a set of characters if all of them are part of the string.
Definition: io.hpp:255
sys::io::ownership::link
@ link
The file instance refers to a FILE object managed somewhere else.
sys::io::is_superset_of_v
constexpr const auto is_superset_of_v
Check whether the left hand set is a superest of the right hand set.
Definition: io.hpp:184
sys::io::file_feature::eof
bool eof() const
Return whether the file instance is in EOF state.
Definition: io.hpp:328
sys::io::file_feature::handle
FILE * handle
A pointer to the underlying FILE object.
Definition: io.hpp:285
sys::io::query::contains_ftor::any
constexpr bool any(CharTs const ... chars) const
Check for a set of characters if at least one is part of the string.
Definition: io.hpp:233
sys::io::file
Produces file access types around the C file handling facilities.
Definition: io.hpp:92
sys::io::ferr
file< link, write > ferr
File access instances for stderr.
Definition: io.hpp:1007
sys::io::feature::read
@ read
The file type supports read operations.
sys::io::contains_v
constexpr const auto contains_v
Check whether a set type contains a value.
Definition: io.hpp:156
sys::io::file_feature< FileT, read, Tail ... >::gets
bool gets(char(&dst)[Count])
Read a line from the file.
Definition: io.hpp:460
sys::io::query::contains_ftor::operator()
constexpr bool operator()(char const ch) const
Check for a single character.
Definition: io.hpp:211
sys::io::file_feature< FileT, write, Tail ... >::write
FileT & write(T const (&src)[Count], std::size_t const count)
Write an objects to file.
Definition: io.hpp:599