nlib
InputStream.h
Go to the documentation of this file.
1 
2 #pragma once
3 #ifndef INCLUDE_NN_NLIB_INPUTSTREAM_H_
4 #define INCLUDE_NN_NLIB_INPUTSTREAM_H_
5 
6 #include "nn/nlib/Config.h"
7 #include "nn/nlib/TypeTraits.h"
8 
9 NLIB_NAMESPACE_BEGIN
10 
11 // code snippets:
12 // InputStream& stream = 'stream that inherits InputStream';
13 // if (!stream.Read(dataptr, nbyte)) { error = stream.GetErrorValue(); ..... }
14 // while ((c = stream.Read()) >= 0) { c is [0x00 - 0xFF] }
15 // if (!stream) { error = stream.GetErrorValue(); ..... }
17  public:
19  is_buf_curidx_(0),
20  is_buf_endidx_(0),
21  is_buf_(NULL),
22  is_bufsize_(0),
23  errno_(0) {}
25  // NOTE:
26  // cannot call Close_() from this destructor.
27  // the destructor of the derived class has to call Close_() if needed.
28  }
29  // returns true if there has been no errors
30  // you can also write the codes such that 'if (!!stream) { ... }'
31  errno_t GetErrorValue() const NLIB_NOEXCEPT { return errno_; }
32  // use Pos64() if you need a 64bit value on 32bit arch
33  size_t Pos() const NLIB_NOEXCEPT { return static_cast<size_t>(Pos64()); }
34  uint64_t Pos64() const NLIB_NOEXCEPT { return pos_ + is_buf_curidx_; }
36  if (*this && is_buf_curidx_ == is_buf_endidx_) {
37  CheckBuffer();
38  return *this && is_buf_curidx_ == is_buf_endidx_;
39  }
40  return false;
41  }
42  // < 0 if EOS or error, otherwise returns a byte and ++pos
44  if (NLIB_UNLIKELY(is_buf_curidx_ == is_buf_endidx_)) {
45  CheckBuffer();
46  if (NLIB_UNLIKELY(is_buf_curidx_ == is_buf_endidx_)) return -1;
47  }
48  return is_buf_[is_buf_curidx_++];
49  }
50  // < 0 if EOS or error, otherwise returns a byte and pos is unchanged
52  if (NLIB_UNLIKELY(is_buf_curidx_ == is_buf_endidx_)) {
53  CheckBuffer();
54  if (NLIB_UNLIKELY(is_buf_curidx_ == is_buf_endidx_)) return -1;
55  }
56  return is_buf_[is_buf_curidx_];
57  }
58  // returns skipped number of bytes
59  size_t Skip(size_t nbytes) NLIB_NOEXCEPT;
60  size_t Read(void* ptr, size_t nbytes) NLIB_NOEXCEPT NLIB_NONNULL {
61 #ifndef NLIB_NONNULL_ENABLED
62  if (!ptr) {
63  this->SetError(EINVAL);
64  return 0;
65  }
66 #endif
67  if (nbytes > RSIZE_MAX) { // INT01-C
68  this->SetError(EINVAL);
69  return 0;
70  }
71  if (is_buf_curidx_ + nbytes <= is_buf_endidx_) {
72  nlib_memcpy(ptr, nbytes, &is_buf_[is_buf_curidx_], nbytes);
73  is_buf_curidx_ += nbytes;
74  return nbytes;
75  }
76  return this->Read_(ptr, nbytes);
77  }
78  bool Close() NLIB_NOEXCEPT;
79  NLIB_SAFE_BOOL(InputStream, errno_ == 0)
80 
81  protected:
82  void ResetBuffer(void* p, size_t nbytes) NLIB_NOEXCEPT {
83  is_buf_ = reinterpret_cast<unsigned char*>(p);
84  is_bufsize_ = static_cast<int>(nbytes);
85  }
86  void SetError(errno_t e) const NLIB_NOEXCEPT {
87  if (errno_ == 0) errno_ = e;
88  }
89 
90  private:
91  virtual size_t FillBuffer_(void* p, size_t nbytes) NLIB_NOEXCEPT = 0;
92  virtual bool Close_() NLIB_NOEXCEPT = 0;
93  virtual void* GetWorkBuffer_(size_t* nbytes) NLIB_NOEXCEPT;
94  size_t Read_(void* ptr, size_t nbytes) NLIB_NOEXCEPT;
95 
96  // By default, Skip_() reads data on is_buf_.
97  // you can override it if you can implement more efficient code.
98  virtual size_t Skip_(size_t nbytes) NLIB_NOEXCEPT;
99 
100  private:
101  void CheckBuffer() NLIB_NOEXCEPT;
102  bool GetWorkBuffer() NLIB_NOEXCEPT;
103 
104  private:
105  uint64_t pos_;
106  size_t is_buf_curidx_;
107  size_t is_buf_endidx_;
108  unsigned char* is_buf_;
109  size_t is_bufsize_;
110  mutable ErrnoT errno_;
111  // errno_ is changed only from derived classes.
112  // FillBuffer_() or Close_() changes errno_ in other words.
113 
115 };
116 
118  public:
120  virtual ~NullInputStream() NLIB_NOEXCEPT {}
121 
122  private:
123  char dummy_buf_[256];
124  virtual size_t FillBuffer_(void* p, size_t nbytes) NLIB_NOEXCEPT NLIB_OVERRIDE;
125  virtual bool Close_() NLIB_NOEXCEPT NLIB_OVERRIDE { return true; }
126  virtual size_t Skip_(size_t nbytes) NLIB_NOEXCEPT NLIB_OVERRIDE;
127 };
128 
129 namespace detail {
130 
131 template<size_t N>
132 class MiniBufIn {
133  public:
134  NLIB_STATIC_ASSERT(N >= 16);
135  static NLIB_CEXPR const size_t buf_size = N;
136  NLIB_ALWAYS_INLINE MiniBufIn() NLIB_NOEXCEPT { cur_ = end_ = &buf_[0]; }
137  template<class IS>
138  NLIB_ALWAYS_INLINE bool Prefetch(IS* stream, size_t n) NLIB_NOEXCEPT {
139  if (cur_ + n > end_) {
140  NLIB_ASSERT(n <= N);
141  size_t rem = end_ - cur_;
142  nlib_memmove(reinterpret_cast<void*>(&buf_[0]), N,
143  cur_, rem);
144  size_t nread = stream->Read(&buf_[rem], N - rem);
145  cur_ = &buf_[0];
146  end_ = &buf_[0] + rem + nread;
147  return (nread + rem >= n);
148  }
149  return true;
150  }
151  template<class IS>
152  NLIB_ALWAYS_INLINE int Peek(IS* stream) NLIB_NOEXCEPT {
153  if (NLIB_UNLIKELY(cur_ == end_)) {
154  size_t nread = stream->Read(&buf_[0], N);
155  if (NLIB_UNLIKELY(nread == 0)) return -1;
156  cur_ = &buf_[0];
157  end_ = &buf_[0] + nread;
158  }
159  return *cur_;
160  }
161  template<class IS>
162  NLIB_ALWAYS_INLINE int Read(IS* stream) NLIB_NOEXCEPT {
163  int c;
164  if (NLIB_UNLIKELY(cur_ == end_)) {
165  size_t nread = stream->Read(&buf_[0], N);
166  if (NLIB_UNLIKELY(nread == 0)) return -1;
167  cur_ = &buf_[0] + 1;
168  end_ = &buf_[0] + nread;
169  return buf_[0];
170  } else {
171  c = *cur_;
172  ++cur_;
173  return c;
174  }
175  }
176 
177  NLIB_ALWAYS_INLINE void Advance(size_t n) NLIB_NOEXCEPT {
178  // Prefetch(stream, n) must be successful beforehand
179  cur_ += n;
180  }
181  NLIB_ALWAYS_INLINE const uint8_t& operator[](size_t n) NLIB_NOEXCEPT {
182  // Prefetch(stream, n + 1) must be successful beforehand
183  return cur_[n];
184  }
185  template<class IS>
187  size_t ReadBytes(IS* stream, void* data, size_t nbytes) NLIB_NOEXCEPT {
188  if (cur_ + nbytes <= end_) {
189  nlib_memcpy(data, nbytes, cur_, nbytes);
190  cur_ += nbytes;
191  return nbytes;
192  }
193  uint8_t* p = reinterpret_cast<uint8_t*>(data);
194  size_t rem = end_ - cur_;
195  nlib_memcpy(reinterpret_cast<void*>(p), nbytes, cur_, rem);
196  cur_ = end_ = &buf_[0];
197  size_t nread = stream->Read(p + rem, nbytes - rem);
198  return nread + rem;
199  }
200  template<class IS, class T>
201  size_t Read(IS* stream, T* data, size_t count) NLIB_NOEXCEPT {
202  NLIB_STATIC_ASSERT(sizeof(*data) <= N);
203  NLIB_STATIC_ASSERT(IsPod<T>::value);
204  size_t nbytes = sizeof(*data) * count;
205  size_t nread = ReadBytes(stream, data, nbytes);
206  if (NLIB_LIKELY(nread == nbytes)) return count;
207  size_t mod = nread % sizeof(*data);
208  uint8_t* p = reinterpret_cast<uint8_t*>(data);
209  nlib_memcpy(reinterpret_cast<void*>(&buf_[0]), N,
210  p + nread - mod, mod);
211  end_ = &buf_[mod];
212  return nread / sizeof(*data);
213  }
214  NLIB_ALWAYS_INLINE size_t size() const NLIB_NOEXCEPT { return end_ - cur_; }
215 
216  private:
217  uint8_t* cur_;
218  uint8_t* end_;
219  uint8_t buf_[N];
220 };
221 
222 } // namespace detail
223 NLIB_NAMESPACE_END
224 
225 #endif // INCLUDE_NN_NLIB_INPUTSTREAM_H_
#define NLIB_OVERRIDE
Defines override if it is available for use. If not, holds an empty string.
Definition: Config.h:210
size_t Read(void *ptr, size_t nbytes) noexcept
Reads the number of bytes of data specified by nBytes into the memory region specified by ptr...
Definition: InputStream.h:60
#define NLIB_ALWAYS_INLINE
Indicates that the compiler is forced to perform inline expansion of functions.
Definition: Platform_unix.h:69
Substitute definitions for the C++11 standard header type_traits. These substitute definitions are us...
uint64_t Pos64() const noexcept
Returns the current position in the stream as a 64-bit value.
Definition: InputStream.h:34
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Definition: Config.h:145
#define NLIB_SAFE_BOOL(class_name, exp)
Defines a safe operator bool function in the class. Uses the C++11 explicit bool if it is available f...
Definition: Config.h:160
errno_t GetErrorValue() const noexcept
Gets the error value.
Definition: InputStream.h:31
bool IsEos() noexcept
Returns true if the stream is finished being read through to the end. If the stream has not been read...
Definition: InputStream.h:35
#define NLIB_CHECK_RESULT
Indicates that the caller of the function must check the returned value.
Definition: Platform_unix.h:74
int Read() noexcept
Reads one byte of data from the stream.
Definition: InputStream.h:43
#define NLIB_UNLIKELY(x)
Indicates to the compiler that condition x is likely to be false.
Definition: Platform_unix.h:72
#define RSIZE_MAX
Defines a value somewhat smaller than the maximum value of size_t.
Definition: Platform.h:541
void ResetBuffer(void *p, size_t nbytes) noexcept
Sets the buffer held by InputStream.
Definition: InputStream.h:82
#define NLIB_VIS_PUBLIC
Symbols for functions and classes are made available outside of the library.
Definition: Platform_unix.h:61
size_t Pos() const noexcept
Returns the current position in the stream.
Definition: InputStream.h:33
virtual ~InputStream() noexcept
Destructor. This function is called from the derived class.
Definition: InputStream.h:24
#define NLIB_LIKELY(x)
Indicates to the compiler that condition x is likely to be true.
Definition: Platform_unix.h:71
constexpr InputStream() noexcept
Instantiates the object. This function is called from the derived class.
Definition: InputStream.h:18
The base class for input streams. This class cannot be instantiated.
Definition: InputStream.h:16
Class that wraps errno_t. This class improves visual representations in the Visual Studio debugger...
Definition: Config.h:474
static errno_t nlib_memcpy(void *s1, size_t s1max, const void *s2, size_t n)
An implementation corresponding to N1078 memcpy_s.
Definition: Platform.h:3170
NLIB_CHECK_RESULT int Peek() noexcept
Reads the next byte without consuming the stream.
Definition: InputStream.h:51
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:86
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
Definition: Config.h:80
A file that contains the configuration information for each development environment.
void SetError(errno_t e) const noexcept
Sets an error to InputStream.
Definition: InputStream.h:86
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:211
#define NLIB_STATIC_ASSERT(exp)
Defines a static assertion. Uses static_assert if it is available for use.
Definition: Config.h:136
bool Read(BinaryReader *r, T *x)
You can read to user-defined class objects by specializing this function template.
Definition: BinaryReader.h:152
The class for streams that always load 0.
Definition: InputStream.h:117
static errno_t nlib_memmove(void *s1, size_t s1max, const void *s2, size_t n)
An implementation corresponding to N1078 memmove_s.
Definition: Platform.h:3188
#define NLIB_NONNULL
Indicates that you cannot specify NULL for all arguments.
Definition: Platform_unix.h:76
int errno_t
Indicates with an int-type typedef that a POSIX error value is returned as the return value...
Definition: NMalloc.h:24