file_case.{h,cpp}: wether->whether; 2017
[s-roff.git] / include / file_case.h
blobda2558c3f9a6e9739e290bec724b182745aaf1fa
1 /*@ file_case: input file encapsulator
3 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #ifndef _FILE_CASE_H
18 #define _FILE_CASE_H
20 #include "config.h"
21 #include "lib.h"
23 #include <assert.h>
24 #include <stdio.h>
26 class file_case{
27 char const *_path;
28 FILE *_file; // fc_have_stdio
29 void *_layer; // E.g., gzFile
30 uint32_t _flags;
31 uint8_t _dummy[4];
33 public:
34 // Flags for ctor / muxer()
35 enum{
36 fc_none = 0,
37 fc_dont_close = 1<<0, // Don't close the file, if any
38 fc_pipe = 1<<1, // _file is not seekable
39 fc_const_path = 1<<2, // Don't dup path, and don't a_delete it
40 fc_take_path = 1<<3, // Don't dup path, but a_delete it
41 fc_have_stdio = 1<<4, // .file() may be used
42 _fc_freebit = 5,
43 fc_mask = (1<<_fc_freebit) - 1
46 // Flags only for muxer()
47 enum{
48 mux_need_seek = 1<<(_fc_freebit+0), // File must be seekable
49 mux_need_binary = 1<<(_fc_freebit+1), // Need binary I/O
50 mux_unpack = 1<<(_fc_freebit+2), // Do auto-check for FILE{.gz,.bz2..}
51 mux_no_unpack = 1<<(_fc_freebit+3), // Do NOT auto-check
52 mux_need_stdio = 1<<(_fc_freebit+4), // Only then may .file() be used
53 _mux_freebit = _fc_freebit + 5,
54 mux_mask = ~fc_mask,
55 mux_default = fc_none,
56 // Defines the global default strategy for dealing with packed files in case
57 // none of the above has been given explicitly by a callee
58 _mux_unpack_default = mux_unpack
61 enum seek_whence{
62 seek_set,
63 seek_cur,
64 seek_end
67 file_case(FILE *fp, char const *path, uint32_t flags=fc_none);
68 ~file_case(void);
70 bool close(void);
71 char const *path(void) const;
72 FILE *file(void) const;
73 bool is_pipe(void) const;
75 bool is_eof(void) const;
76 int get_c(void);
77 int unget_c(int c);
78 char *get_line(char *buf, size_t buf_size);
79 size_t get_buf(void *buf, size_t buf_size);
80 void rewind(void);
81 int seek(long offset, seek_whence whence=seek_set);
83 // Factory muxer; note that fc_take_path will be honoured even on failure
84 // If path is NULL or "-" we'll go for stdin
85 static file_case *muxer(char const *path=NULL, uint32_t flags=mux_default);
87 CLASS_DISABLE_COPY(file_case);
90 inline
91 file_case::file_case(FILE *fp, char const *path, uint32_t flags)
92 : _path(path), _file(fp), _layer(NULL), _flags(flags){
93 assert(!(flags & (fc_const_path | fc_take_path)) ||
94 !(flags & fc_const_path) != !(flags & fc_take_path));
95 assert(!(flags & ~fc_mask));
98 inline
99 file_case::~file_case(void){
100 if(_file != NULL || _layer != NULL) // xxx (uintptr_t)a|(uintptr_t)b
101 close();
104 inline char const *
105 file_case::path(void) const{
106 return _path;
109 inline FILE *
110 file_case::file(void) const{
111 assert(_flags & fc_have_stdio);
112 return _file;
115 inline bool
116 file_case::is_pipe(void) const{
117 return ((_flags & fc_pipe) != 0);
120 #endif // _FILE_CASE_H
121 // s-it2-mode