nlib
InputStream.h
[詳解]
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 {
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  template<size_t N>
92  size_t Read(nlib_byte_t (&buf)[N]) NLIB_NOEXCEPT { return Read(&buf[0], N); }
93  bool Close() NLIB_NOEXCEPT;
94  NLIB_SAFE_BOOL(InputStream, errno_ == 0)
95 
96  protected:
97  void ResetBuffer(void* p, size_t nbytes) NLIB_NOEXCEPT {
98  is_buf_ = static_cast<unsigned char*>(p);
99  is_bufsize_ = static_cast<int>(nbytes);
100  }
101  void SetError(errno_t e) const NLIB_NOEXCEPT {
102  if (errno_ == 0) errno_ = e;
103  }
104 
105  private:
106  virtual size_t FillBuffer_(void* p, size_t nbytes) NLIB_NOEXCEPT = 0;
107  virtual bool Close_() NLIB_NOEXCEPT = 0;
108  virtual void* GetWorkBuffer_(size_t* nbytes) NLIB_NOEXCEPT;
109  size_t Read_(void* ptr, size_t nbytes) NLIB_NOEXCEPT;
110 
111  // By default, Skip_() reads data on is_buf_.
112  // you can override it if you can implement more efficient code.
113  virtual size_t Skip_(size_t nbytes) NLIB_NOEXCEPT;
114 
115  private:
116  void CheckBuffer() NLIB_NOEXCEPT;
117  bool GetWorkBuffer() NLIB_NOEXCEPT;
118 
119  private:
120  uint64_t pos_;
121  size_t is_buf_curidx_;
122  size_t is_buf_endidx_;
123  unsigned char* is_buf_;
124  size_t is_bufsize_;
125  mutable ErrnoT errno_;
126  // errno_ is changed only from derived classes.
127  // FillBuffer_() or Close_() changes errno_ in other words.
128 
130 };
131 
133  public:
135  virtual ~NullInputStream() NLIB_NOEXCEPT {}
136 
137  private:
138  char dummy_buf_[256];
139  virtual size_t FillBuffer_(void* p, size_t nbytes) NLIB_NOEXCEPT NLIB_OVERRIDE;
140  virtual bool Close_() NLIB_NOEXCEPT NLIB_OVERRIDE { return true; }
141  virtual size_t Skip_(size_t nbytes) NLIB_NOEXCEPT NLIB_OVERRIDE;
142 };
143 
144 namespace detail {
145 
146 template<size_t N>
147 class MiniBufIn {
148  public:
149  NLIB_STATIC_ASSERT(N >= 16);
150  static NLIB_CEXPR const size_t buf_size = N;
151  NLIB_ALWAYS_INLINE MiniBufIn() NLIB_NOEXCEPT { cur_ = end_ = &buf_[0]; }
152  template<class IS>
153  NLIB_ALWAYS_INLINE bool Prefetch(IS* stream, size_t n) NLIB_NOEXCEPT {
154  if (cur_ + n > end_) {
155  NLIB_ASSERT(n <= N);
156  size_t rem = end_ - cur_;
157  nlib_memmove(static_cast<void*>(&buf_[0]), N,
158  cur_, rem);
159  size_t nread = stream->Read(&buf_[rem], N - rem);
160  cur_ = &buf_[0];
161  end_ = &buf_[0] + rem + nread;
162  return (nread + rem >= n);
163  }
164  return true;
165  }
166  template<class IS>
167  NLIB_ALWAYS_INLINE int Peek(IS* stream) NLIB_NOEXCEPT {
168  if (NLIB_UNLIKELY(cur_ == end_)) {
169  size_t nread = stream->Read(&buf_[0], N);
170  if (NLIB_UNLIKELY(nread == 0)) return -1;
171  cur_ = &buf_[0];
172  end_ = &buf_[0] + nread;
173  }
174  return *cur_;
175  }
176  template<class IS>
177  NLIB_ALWAYS_INLINE int Read(IS* stream) NLIB_NOEXCEPT {
178  if (NLIB_UNLIKELY(cur_ == end_)) {
179  size_t nread = stream->Read(&buf_[0], N);
180  if (NLIB_UNLIKELY(nread == 0)) return -1;
181  cur_ = &buf_[0] + 1;
182  end_ = &buf_[0] + nread;
183  return buf_[0];
184  } else {
185  int c = *cur_;
186  ++cur_;
187  return c;
188  }
189  }
190 
191  NLIB_ALWAYS_INLINE void Advance(size_t n) NLIB_NOEXCEPT {
192  // Prefetch(stream, n) must be successful beforehand
193  cur_ += n;
194  }
195  NLIB_ALWAYS_INLINE const uint8_t& operator[](size_t n) NLIB_NOEXCEPT {
196  // Prefetch(stream, n + 1) must be successful beforehand
197  return cur_[n];
198  }
199  template<class IS>
201  size_t ReadBytes(IS* stream, void* data, size_t nbytes) NLIB_NOEXCEPT {
202  if (cur_ + nbytes <= end_) {
203  nlib_memcpy(data, nbytes, cur_, nbytes);
204  cur_ += nbytes;
205  return nbytes;
206  }
207  uint8_t* p = static_cast<uint8_t*>(data);
208  size_t rem = end_ - cur_;
209  nlib_memcpy(static_cast<void*>(p), nbytes, cur_, rem);
210  cur_ = end_ = &buf_[0];
211  size_t nread = stream->Read(p + rem, nbytes - rem);
212  return nread + rem;
213  }
214  template<class IS, class T>
215  size_t Read(IS* stream, T* data, size_t count) NLIB_NOEXCEPT {
216  NLIB_STATIC_ASSERT(sizeof(*data) <= N);
217  NLIB_STATIC_ASSERT(IsPod<T>::value);
218  size_t nbytes = sizeof(*data) * count;
219  size_t nread = ReadBytes(stream, data, nbytes);
220  if (NLIB_LIKELY(nread == nbytes)) return count;
221  size_t mod = nread % sizeof(*data);
222  uint8_t* p = static_cast<uint8_t*>(static_cast<void*>(data));
223  nlib_memcpy(static_cast<void*>(&buf_[0]), N,
224  p + nread - mod, mod);
225  end_ = &buf_[mod];
226  return nread / sizeof(*data);
227  }
228  NLIB_ALWAYS_INLINE size_t size() const NLIB_NOEXCEPT { return end_ - cur_; }
229 
230  private:
231  uint8_t* cur_;
232  uint8_t* end_;
233  uint8_t buf_[N];
234 };
235 
236 } // namespace detail
237 NLIB_NAMESPACE_END
238 
239 #endif // INCLUDE_NN_NLIB_INPUTSTREAM_H_
#define NLIB_OVERRIDE
利用可能であればoverrideが定義されます。そうでない場合は空文字列です。
Definition: Config.h:244
size_t Read(void *ptr, size_t nbytes) noexcept
ptr で示されるメモリにnbytes 読み込みます。
Definition: InputStream.h:73
#define NLIB_ALWAYS_INLINE
コンパイラに関数をインライン展開するように強く示します。
Definition: Platform_unix.h:97
C++11の標準ヘッダとなるtype_traitsの代用定義です。 コンパイラや標準ライブラリによってサポートされてい...
uint64_t Pos64() const noexcept
ストリーム上の現在位置を64bit値で返します。
Definition: InputStream.h:47
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
Definition: Config.h:179
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
Definition: Config.h:194
errno_t GetErrorValue() const noexcept
エラー値を取得します。
Definition: InputStream.h:44
bool IsEos() noexcept
ストリームを最後まで読み終えている場合trueを返します。最後まで読み終えていない場合やエラーが発生して...
Definition: InputStream.h:48
#define NLIB_CHECK_RESULT
関数の呼び出し元が戻り値をチェックする必要があることを示します。
int Read() noexcept
ストリームから1バイトを読み込みます。
Definition: InputStream.h:56
#define NLIB_UNLIKELY(x)
条件xが偽になる傾向が高いことをコンパイラに示します。
#define RSIZE_MAX
size_tの最大値よりいくらか小さい値が定義されています。
Definition: Platform.h:224
void ResetBuffer(void *p, size_t nbytes) noexcept
InputStreamが持つバッファを設定します。
Definition: InputStream.h:97
#define NLIB_VIS_PUBLIC
関数やクラス等のシンボルをライブラリの外部に公開します。
Definition: Platform_unix.h:89
size_t Pos() const noexcept
ストリーム上の現在位置を返します。
Definition: InputStream.h:46
virtual ~InputStream() noexcept
デストラクタです。派生クラスから呼び出されます。
Definition: InputStream.h:37
#define NLIB_LIKELY(x)
条件xが真になる傾向が高いことをコンパイラに示します。
Definition: Platform_unix.h:99
constexpr InputStream() noexcept
コンストラクタです。派生クラスから呼び出されます。
Definition: InputStream.h:31
入力ストリームの基底クラスです。このクラスを実体化することはできません。
Definition: InputStream.h:29
errno_tをラップするクラスです。Visual Studioのデバッガ上での表示を改善します。
Definition: Config.h:406
static errno_t nlib_memcpy(void *s1, size_t s1max, const void *s2, size_t n)
N1078のmemcpy_sに相当する実装です。
Definition: Platform.h:2437
int Peek() noexcept
ストリームを消費せずに次の1バイトを読み込みます。
Definition: InputStream.h:64
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Config.h:105
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
Definition: Config.h:107
開発環境別の設定が書かれるファイルです。
void SetError(errno_t e) const noexcept
InputStreamにエラーを設定します。
Definition: InputStream.h:101
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
Definition: Config.h:245
#define NLIB_STATIC_ASSERT(exp)
静的アサートが定義されます。利用可能であればstatic_assertを利用します。
Definition: Config.h:170
bool Read(BinaryReader *r, T *x)
この関数テンプレートを特殊化することで、ユーザー定義クラスに読み込むことができます。 ...
Definition: BinaryReader.h:172
常に0を読み込むストリームです。
Definition: InputStream.h:132
unsigned char nlib_byte_t
C++17以降でstd::byteにtypedefされる型です。
Definition: Platform.h:319
static errno_t nlib_memmove(void *s1, size_t s1max, const void *s2, size_t n)
N1078のmemmove_sに相当する実装です。
Definition: Platform.h:2455
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:37