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