nlib
OutputStream.h
Go to the documentation of this file.
1 
2 /*---------------------------------------------------------------------------*
3 
4  Project: CrossRoad
5  Copyright (C)2012-2016 Nintendo. All rights reserved.
6 
7  These coded instructions, statements, and computer programs contain
8  proprietary information of Nintendo of America Inc. and/or Nintendo
9  Company Ltd., and are protected by Federal copyright law. They may
10  not be disclosed to third parties or copied or duplicated in any form,
11  in whole or in part, without the prior written consent of Nintendo.
12 
13  *---------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_OUTPUTSTREAM_H_
17 #define INCLUDE_NN_NLIB_OUTPUTSTREAM_H_
18 
19 #include "nn/nlib/Config.h"
20 
21 NLIB_NAMESPACE_BEGIN
22 
23 // code snippets:
24 // OutputStream& stream = 'stream that inherits OutputStream';
25 // if (!stream.Write(dataptr, nbyte)) { error = stream.GetErrorValue(); .... }
26 // for (.....) { if (!stream.Write(byte)) { error = stream.GetErrorValue(); .... } }
27 // # you should Flush() and Close() explicitly
28 // if (!stream.Flush()) { error = stream.GetErrorValue(); .... } }
29 // if (!stream.Close()) { error = stream.GetErrorValue(); .... } }
31  public:
33  BUFFERINGMODE_BLOCKBUFFERED = 0, // default
34  BUFFERINGMODE_LINEBUFFERED, // if console output
35  BUFFERINGMODE_UNBUFFERED
36  };
37 
38  public:
40  os_buf_curidx_(0),
41  os_buf_(NULL),
42  os_bufsize_(0),
43  errno_(0),
44  m_BufferingMode(BUFFERINGMODE_BLOCKBUFFERED) {}
46  // NOTE:
47  // cannot call Close_() from this destructor.
48  // the destructor of the derived class has to call Close_() if needed.
49  }
50  // use Pos64() if you need a 64bit value on 32bit arch
51  size_t Pos() const NLIB_NOEXCEPT { return static_cast<size_t>(Pos64()); }
52  uint64_t Pos64() const NLIB_NOEXCEPT { return pos_ + os_buf_curidx_; }
53  bool Write(int b) NLIB_NOEXCEPT {
54  // NOTE:
55  // if the stream is closed,
56  // Write() will succeed before the internal buffer becomes full.
57  if (NLIB_UNLIKELY(os_buf_curidx_ == os_bufsize_)) {
58  if (NLIB_UNLIKELY(!this->Flush_(false))) return false;
59  if (NLIB_UNLIKELY(os_bufsize_ == 0)) {
60  this->SetError(EIO);
61  return false;
62  }
63  }
64  os_buf_[os_buf_curidx_++] = static_cast<unsigned char>(b & 0xff);
65  return true;
66  }
67  bool Write(const void* p, size_t n) NLIB_NOEXCEPT NLIB_NONNULL {
68 #ifndef NLIB_NONNULL_ENABLED
69  if (!p) {
70  this->SetError(EINVAL);
71  return false;
72  }
73 #endif
74  if (n > RSIZE_MAX) {
75  this->SetError(EINVAL);
76  return false;
77  }
78  if (os_buf_curidx_ + n <= os_bufsize_) {
79  nlib_memcpy(&os_buf_[os_buf_curidx_], n, p, n);
80  os_buf_curidx_ += n;
81  return true;
82  }
83  return this->Write_(p, n);
84  }
85  bool WriteGather(const nlib_fd_iovec* iov, int iovcnt) NLIB_NOEXCEPT NLIB_NONNULL {
86 #ifndef NLIB_NONNULL_ENABLED
87  if (!iov) {
88  this->SetError(EINVAL);
89  return false;
90  }
91 #endif
92  if (iovcnt < 0) {
93  this->SetError(EINVAL);
94  return false;
95  }
96  return this->WriteGather_(iov, iovcnt);
97  }
98  bool Flush() NLIB_NOEXCEPT { return Flush_(true); }
99  bool Close() NLIB_NOEXCEPT;
100  errno_t GetErrorValue() const NLIB_NOEXCEPT { return errno_; }
101  // returns true if there has been no errors
102  // you can also write the codes such that 'if (!!stream) { ... }'
103  BufferingMode GetBufferingMode() const NLIB_NOEXCEPT { return m_BufferingMode; }
104  NLIB_SAFE_BOOL(OutputStream, errno_ == 0)
105 
106  protected:
107  void ResetBuffer(void* p, size_t nbytes) NLIB_NOEXCEPT {
108  os_buf_ = reinterpret_cast<unsigned char*>(p);
109  os_bufsize_ = static_cast<int>(nbytes);
110  }
111  void SetError(errno_t e) const NLIB_NOEXCEPT {
112  if (errno_ == 0) errno_ = e;
113  }
114 
115  private:
116  virtual bool PushBuffer_(const void* p, size_t nbytes, bool do_flush) NLIB_NOEXCEPT = 0;
117  virtual bool Close_() NLIB_NOEXCEPT = 0;
118  virtual void* GetWorkBuffer_(size_t* nbytes) NLIB_NOEXCEPT;
119  virtual bool WriteGather_(const nlib_fd_iovec* iov, int iovcnt) NLIB_NOEXCEPT;
120  bool Write_(const void* p, size_t n) NLIB_NOEXCEPT;
121 
122  private:
123  bool Flush_(bool flush_device) NLIB_NOEXCEPT;
124  bool GetWorkBuffer_() NLIB_NOEXCEPT;
125 
126  private:
127  uint64_t pos_;
128  size_t os_buf_curidx_;
129  unsigned char* os_buf_;
130  size_t os_bufsize_;
131  mutable ErrnoT errno_;
132 
133  protected:
134  // NOTE:
135  // BufferingMode is for the codes which use OutputStream.
136  // OutputStream only shows the buffering mode which the user specified.
137  // for example, TextWriter (the user of OutputStream) has to decide
138  // when to call Flush() looking at GetBufferingMode().
140 
141  private:
143 };
144 
146  public:
149 
150  private:
151  unsigned char dummy_buf_[256];
152  virtual bool PushBuffer_(const void* p, size_t, bool do_flush) NLIB_NOEXCEPT NLIB_OVERRIDE;
153  virtual bool Close_() NLIB_NOEXCEPT NLIB_OVERRIDE { return true; }
154 };
155 
156 namespace detail {
157 
158 template<size_t N>
159 class MiniBufOut {
160  public:
161  static NLIB_CEXPR const size_t buf_size = N;
162  NLIB_ALWAYS_INLINE MiniBufOut() NLIB_NOEXCEPT { cur_ = &buf_[0]; }
163  template<class OS>
164  NLIB_ALWAYS_INLINE bool Flush(OS* stream) NLIB_NOEXCEPT {
165  size_t n = cur_ - &buf_[0];
166  cur_ = &buf_[0];
167  return stream->Write(&buf_[0], n);
168  }
169  template<class OS>
170  NLIB_ALWAYS_INLINE bool CheckAndFlush(OS* stream, size_t n) NLIB_NOEXCEPT {
171  if (cur_ + n > &buf_[0] + N) {
172  NLIB_ASSERT(n <= N);
173  return Flush(stream);
174  }
175  return true;
176  }
177  NLIB_ALWAYS_INLINE void Advance(size_t n) NLIB_NOEXCEPT {
178  // CheckAndFlush(stream, n) must be successful beforehand.
179  cur_ += n;
180  }
181  NLIB_ALWAYS_INLINE uint8_t& operator[](size_t n) NLIB_NOEXCEPT {
182  // CheckAndFlush(stream, n + 1) must be successful beforehand.
183  return cur_[n];
184  }
185  template<class OS>
186  NLIB_ALWAYS_INLINE bool WriteAndAdvance(OS* stream, uint8_t data) NLIB_NOEXCEPT {
187  if (NLIB_LIKELY(CheckAndFlush(stream, 1))) {
188  *cur_ = data;
189  ++cur_;
190  return true;
191  }
192  return false;
193  }
194  template<class OS>
195  NLIB_ALWAYS_INLINE bool WriteAndAdvance(OS* stream,
196  const void* data, size_t n) NLIB_NOEXCEPT {
197  if (NLIB_LIKELY(CheckAndFlush(stream, n))) {
198  (void)nlib_memcpy(cur_, n, data, n);
199  cur_ += n;
200  return true;
201  }
202  return false;
203  }
204 
205  private:
206  uint8_t* cur_;
207  uint8_t buf_[N];
208  NLIB_DISALLOW_COPY_AND_ASSIGN(MiniBufOut);
209 };
210 
211 template<class T>
212 class MiniReallocOut {
213  public:
214  NLIB_ALWAYS_INLINE MiniReallocOut(T** mem, uint32_t* cur, uint32_t* memsize) NLIB_NOEXCEPT
215  : mem_(mem), cur_(cur), memsize_(memsize) {}
216  NLIB_ALWAYS_INLINE ~MiniReallocOut() NLIB_NOEXCEPT {}
217  NLIB_ALWAYS_INLINE bool Resize(uint32_t n) NLIB_NOEXCEPT {
218  if (n <= *memsize_) {
219  *cur_ = n;
220  } else {
221  void* p = nlib_realloc(*mem_, n * sizeof(**mem_));
222  if (!p) return false;
223  *mem_ = reinterpret_cast<T*>(p);
224  *memsize_ = n;
225  *cur_ = n;
226  }
227  return true;
228  }
229  NLIB_ALWAYS_INLINE bool Prepare(uint32_t n) NLIB_NOEXCEPT {
230  // T must be int, uint32_t, ... etc. for example
231  if (NLIB_UNLIKELY(*cur_ + n > *memsize_)) {
232  uint32_t newsize;
233  const uint32_t t = 4096 / sizeof(**mem_);
234  if (*cur_ + n >= t) {
235  newsize = ((*cur_ + n) + t - 1) & ~(t - 1);
236  } else {
237  newsize = 1 << (32 - nlib_clz(*cur_ + n - 1));
238  }
239  void* p = nlib_realloc(*mem_, newsize * sizeof(**mem_));
240  if (!p) return false;
241  *mem_ = reinterpret_cast<T*>(p);
242  *memsize_ = newsize;
243  }
244  return true;
245  }
246  NLIB_ALWAYS_INLINE T& operator[](uint32_t n) NLIB_NOEXCEPT {
247  // Prepare(n + 1) must be successful beforehand.
248  return (*mem_)[*cur_ + n];
249  }
250  NLIB_ALWAYS_INLINE void Append(const T& v) NLIB_NOEXCEPT {
251  // Prepare(1) must be successful beforehand.
252  (*mem_)[*cur_] = v;
253  ++(*cur_);
254  }
255  NLIB_ALWAYS_INLINE void Advance(uint32_t n) NLIB_NOEXCEPT {
256  // Prepare(n) must be successful beforehand.
257  *cur_ += n;
258  }
259 
260  private:
261  T** mem_;
262  uint32_t* cur_;
263  uint32_t* memsize_; // sizeof(*mem) * memsize_ bytes
264  NLIB_DISALLOW_COPY_AND_ASSIGN(MiniReallocOut);
265 };
266 
267 } // namespace detail
268 
269 NLIB_NAMESPACE_END
270 
271 #endif // INCLUDE_NN_NLIB_OUTPUTSTREAM_H_
bool Flush() noexcept
Flushes the stream.
Definition: OutputStream.h:98
#define NLIB_OVERRIDE
Defines override if it is available for use. If not, holds an empty string.
Definition: Config.h:223
#define NLIB_ALWAYS_INLINE
Indicates that the compiler is forced to perform inline expansion of functions.
Definition: Platform_unix.h:95
uint64_t Pos64() const noexcept
Returns the current position in the stream as a 64-bit integer.
Definition: OutputStream.h:52
void SetError(errno_t e) const noexcept
Sets an error to OutputStream.
Definition: OutputStream.h:111
#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:158
#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:173
size_t Pos() const noexcept
Returns the current position in the stream.
Definition: OutputStream.h:51
#define NLIB_UNLIKELY(x)
Indicates to the compiler that condition x is likely to be false.
Definition: Platform_unix.h:98
#define RSIZE_MAX
Defines a value somewhat smaller than the maximum value of size_t.
Definition: Platform.h:553
#define NLIB_VIS_PUBLIC
Symbols for functions and classes are made available outside of the library.
Definition: Platform_unix.h:87
constexpr OutputStream() noexcept
Instantiates the object with default parameters (default constructor).
Definition: OutputStream.h:39
The class for OutputStream objects for which no actual writing takes place.
Definition: OutputStream.h:145
bool Write(int b) noexcept
Writes one byte of data to the stream.
Definition: OutputStream.h:53
#define NLIB_LIKELY(x)
Indicates to the compiler that condition x is likely to be true.
Definition: Platform_unix.h:97
Class that wraps errno_t. This class improves visual representations in the Visual Studio debugger...
Definition: Config.h:487
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:3251
#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
virtual ~OutputStream() noexcept
Destructor. Does not do anything.
Definition: OutputStream.h:45
A file that contains the configuration information for each development environment.
NLIB_CHECK_RESULT void * nlib_realloc(void *ptr, size_t size)
A weak function that calls the C standard function realloc. nlib calls realloc via this function...
BufferingMode GetBufferingMode() const noexcept
Gets the buffering mode.
Definition: OutputStream.h:103
The output is line buffered. This mode is set when data is output to the console. ...
Definition: OutputStream.h:34
BufferingMode m_BufferingMode
Stores the buffering mode.
Definition: OutputStream.h:139
void ResetBuffer(void *p, size_t nbytes) noexcept
Sets the buffer held by OutputStream.
Definition: OutputStream.h:107
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:224
errno_t GetErrorValue() const noexcept
Gets the error value.
Definition: OutputStream.h:100
bool Write(const void *p, size_t n) noexcept
Writes n bytes of data to the stream.
Definition: OutputStream.h:67
#define NLIB_NONNULL
Indicates that you cannot specify NULL for all arguments.
BufferingMode
The buffering mode for OutputStream.
Definition: OutputStream.h:32
The base class for output streams. This class cannot be instantiated.
Definition: OutputStream.h:30
bool WriteGather(const nlib_fd_iovec *iov, int iovcnt) noexcept
Writes data from multiple non-continuous buffers to a stream.
Definition: OutputStream.h:85
int errno_t
Indicates with an int-type typedef that a POSIX error value is returned as the return value...
Definition: NMalloc.h:37