nlib
InputStream.h
[詳解]
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 
8 NLIB_NAMESPACE_BEGIN
9 
10 // code snippets:
11 // InputStream& stream = 'stream that inherits InputStream';
12 // if (!stream.Read(dataptr, nbyte)) { error = stream.GetErrorValue(); ..... }
13 // while ((c = stream.Read()) >= 0) { c is [0x00 - 0xFF] }
14 // if (!stream) { error = stream.GetErrorValue(); ..... }
16  public:
18  m_Cur(0),
19  m_End(0),
20  m_Buf(NULL),
21  m_BufSize(0),
22  m_ErrorId(0) {}
24  // NOTE:
25  // cannot call Close_() from this destructor.
26  // the destructor of the derived class has to call Close_() if needed.
27  }
28  // returns true if there has been no errors
29  // you can also write the codes such that 'if (!!stream) { ... }'
30  bool IsOk() const NLIB_NOEXCEPT { return m_ErrorId == 0; }
31  errno_t GetErrorValue() const NLIB_NOEXCEPT { return m_ErrorId; }
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 m_Pos + m_Cur; }
36  if (this->IsOk() && m_Cur == m_End) {
37  CheckBuffer();
38  return this->IsOk() && m_Cur == m_End;
39  }
40  return false;
41  }
42  // < 0 if EOS or error, otherwise returns a byte and ++pos
44  if (NLIB_UNLIKELY(m_Cur == m_End)) {
45  CheckBuffer();
46  if (NLIB_UNLIKELY(m_Cur == m_End)) return -1;
47  }
48  return m_Buf[m_Cur++];
49  }
50  // < 0 if EOS or error, otherwise returns a byte and pos is unchanged
52  if (NLIB_UNLIKELY(m_Cur == m_End)) {
53  CheckBuffer();
54  if (NLIB_UNLIKELY(m_Cur == m_End)) return -1;
55  }
56  return m_Buf[m_Cur];
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 (m_Cur + nBytes <= m_End) {
72  nlib_memcpy(ptr, nBytes, &m_Buf[m_Cur], nBytes);
73  m_Cur += nBytes;
74  return nBytes;
75  }
76  return this->Read_(ptr, nBytes);
77  }
78  bool Close() NLIB_NOEXCEPT;
80 
81  protected:
82  void ResetBuffer(void* p, size_t nBytes) NLIB_NOEXCEPT {
83  m_Buf = reinterpret_cast<unsigned char*>(p);
84  m_BufSize = static_cast<int>(nBytes);
85  }
86  void SetError(errno_t e) const NLIB_NOEXCEPT {
87  if (m_ErrorId == 0) m_ErrorId = 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 m_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 m_Pos;
106  size_t m_Cur;
107  size_t m_End;
108  unsigned char* m_Buf;
109  size_t m_BufSize;
110  mutable errno_t m_ErrorId;
111  // m_ErrorId is changed only from derived classes.
112  // FillBuffer_() or Close_() changes m_ErrorId in other words.
113 
115 };
116 
117 class NLIB_VIS_PUBLIC NullInputStream NLIB_FINAL : public InputStream {
118  public:
120  virtual ~NullInputStream() NLIB_NOEXCEPT {}
121 
122  private:
123  char m_DummyBuf[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 NLIB_NAMESPACE_END
130 
131 #endif // INCLUDE_NN_NLIB_INPUTSTREAM_H_
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Platform.h:2151
#define NLIB_UNLIKELY(x)
条件xが偽になる傾向が高いことをコンパイラに示します。
Definition: Platform_unix.h:62
uint64_t Pos64() const noexcept
ストリーム上の現在位置を64bit値で返します。
Definition: InputStream.h:34
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
#define NLIB_NONNULL
全ての引数にNULLを指定することができないことを示します。
Definition: Platform_unix.h:66
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
Definition: Config.h:126
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
Definition: Config.h:141
bool IsEos() noexcept
ストリームを最後まで読み終えている場合trueを返します。最後まで読み終えていない場合やエラーが発生して...
Definition: InputStream.h:35
#define NLIB_OVERRIDE
利用可能であればoverrideが定義されます。そうでない場合は空文字列です。
int Read() noexcept
ストリームから1バイトを読み込みます。
Definition: InputStream.h:43
size_t Read(void *ptr, size_t nBytes) noexcept
ptr で示されるメモリにnBytes 読み込みます。
Definition: InputStream.h:60
size_t Pos() const noexcept
ストリーム上の現在位置を返します。
Definition: InputStream.h:33
void SetError(errno_t e) const noexcept
InputStreamにエラーを設定します。
Definition: InputStream.h:86
errno_t GetErrorValue() const noexcept
エラー値を取得します。
Definition: InputStream.h:31
#define RSIZE_MAX
size_tの最大値よりいくらか小さい値が定義されています。
Definition: Platform.h:295
bool IsOk() const noexcept
エラーが発生していないかどうかを調べます。
Definition: InputStream.h:30
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
virtual ~InputStream() noexcept
デストラクタです。派生クラスから呼び出されます。
Definition: InputStream.h:23
constexpr InputStream() noexcept
コンストラクタです。派生クラスから呼び出されます。
Definition: InputStream.h:17
入力ストリームの基底クラスです。このクラスを実体化することはできません。
Definition: InputStream.h:15
NLIB_CHECK_RESULT int Peek() noexcept
ストリームを消費せずに次の1バイトを読み込みます。
Definition: InputStream.h:51
開発環境別の設定が書かれるファイルです。
#define NLIB_VIS_PUBLIC
関数やクラス等のシンボルをライブラリの外部に公開します。
Definition: Platform_unix.h:51
常に0を読み込むストリームです。
Definition: InputStream.h:117
errno_t nlib_memcpy(void *s1, size_t s1max, const void *s2, size_t n)
N1078のmemcpy_sに相当する実装です。
Definition: Platform.h:2095
#define NLIB_CHECK_RESULT
関数の呼び出し元が戻り値をチェックする必要があることを示します。
Definition: Platform_unix.h:64
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:24