nlib
OutputStream.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_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  kBufferingModeBlockBuffered = 0, // default
34  kBufferingModeLineBuffered, // if console output
36  BUFFERINGMODE_BLOCKBUFFERED = kBufferingModeBlockBuffered,
37  BUFFERINGMODE_LINEBUFFERED = kBufferingModeLineBuffered,
38  BUFFERINGMODE_UNBUFFERED = kBufferingModeUnbuffered
39  };
40 
41  public:
43  os_buf_curidx_(0),
44  os_buf_(NULL),
45  os_bufsize_(0),
46  errno_(0),
47  m_BufferingMode(kBufferingModeBlockBuffered) {}
49  // NOTE:
50  // cannot call Close_() from this destructor.
51  // the destructor of the derived class has to call Close_() if needed.
52  }
53  // use Pos64() if you need a 64bit value on 32bit arch
54  size_t Pos() const NLIB_NOEXCEPT { return static_cast<size_t>(Pos64()); }
55  uint64_t Pos64() const NLIB_NOEXCEPT { return pos_ + os_buf_curidx_; }
56  bool Write(int b) NLIB_NOEXCEPT {
57  // NOTE:
58  // if the stream is closed,
59  // Write() will succeed before the internal buffer becomes full.
60  if (NLIB_UNLIKELY(os_buf_curidx_ == os_bufsize_)) {
61  if (NLIB_UNLIKELY(!this->Flush_(false))) return false;
62  if (NLIB_UNLIKELY(os_bufsize_ == 0)) {
63  this->SetError(EIO);
64  return false;
65  }
66  }
67  os_buf_[os_buf_curidx_++] = static_cast<unsigned char>(b & 0xff);
68  return true;
69  }
70  bool Write(const void* p, size_t n) NLIB_NOEXCEPT NLIB_NONNULL {
71 #ifndef NLIB_NONNULL_ENABLED
72  if (!p) {
73  this->SetError(EINVAL);
74  return false;
75  }
76 #endif
77  if (n > RSIZE_MAX) {
78  this->SetError(EINVAL);
79  return false;
80  }
81  if (os_buf_curidx_ + n <= os_bufsize_) {
82  nlib_memcpy(&os_buf_[os_buf_curidx_], n, p, n);
83  os_buf_curidx_ += n;
84  return true;
85  }
86  return this->Write_(p, n);
87  }
88  bool WriteGather(const nlib_fd_iovec* iov, int iovcnt) NLIB_NOEXCEPT NLIB_NONNULL {
89 #ifndef NLIB_NONNULL_ENABLED
90  if (!iov) {
91  this->SetError(EINVAL);
92  return false;
93  }
94 #endif
95  if (iovcnt < 0) {
96  this->SetError(EINVAL);
97  return false;
98  }
99  return this->WriteGather_(iov, iovcnt);
100  }
101  bool Flush() NLIB_NOEXCEPT { return Flush_(true); }
102  bool Close() NLIB_NOEXCEPT;
103  errno_t GetErrorValue() const NLIB_NOEXCEPT { return errno_; }
104  // returns true if there has been no errors
105  // you can also write the codes such that 'if (!!stream) { ... }'
106  BufferingMode GetBufferingMode() const NLIB_NOEXCEPT { return m_BufferingMode; }
107  NLIB_SAFE_BOOL(OutputStream, errno_ == 0)
108 
109  protected:
110  void ResetBuffer(void* p, size_t nbytes) NLIB_NOEXCEPT {
111  os_buf_ = reinterpret_cast<unsigned char*>(p);
112  os_bufsize_ = static_cast<int>(nbytes);
113  }
114  void SetError(errno_t e) const NLIB_NOEXCEPT {
115  if (errno_ == 0) errno_ = e;
116  }
117 
118  private:
119  virtual bool PushBuffer_(const void* p, size_t nbytes, bool do_flush) NLIB_NOEXCEPT = 0;
120  virtual bool Close_() NLIB_NOEXCEPT = 0;
121  virtual void* GetWorkBuffer_(size_t* nbytes) NLIB_NOEXCEPT;
122  virtual bool WriteGather_(const nlib_fd_iovec* iov, int iovcnt) NLIB_NOEXCEPT;
123  bool Write_(const void* p, size_t n) NLIB_NOEXCEPT;
124 
125  private:
126  bool Flush_(bool flush_device) NLIB_NOEXCEPT;
127  bool GetWorkBuffer_() NLIB_NOEXCEPT;
128 
129  private:
130  uint64_t pos_;
131  size_t os_buf_curidx_;
132  unsigned char* os_buf_;
133  size_t os_bufsize_;
134  mutable ErrnoT errno_;
135 
136  protected:
137  // NOTE:
138  // BufferingMode is for the codes which use OutputStream.
139  // OutputStream only shows the buffering mode which the user specified.
140  // for example, TextWriter (the user of OutputStream) has to decide
141  // when to call Flush() looking at GetBufferingMode().
143 
144  private:
146 };
147 
149  public:
152 
153  private:
154  unsigned char dummy_buf_[256];
155  virtual bool PushBuffer_(const void* p, size_t, bool do_flush) NLIB_NOEXCEPT NLIB_OVERRIDE;
156  virtual bool Close_() NLIB_NOEXCEPT NLIB_OVERRIDE { return true; }
157 };
158 
159 namespace detail {
160 
161 template<size_t N>
162 class MiniBufOut {
163  public:
164  static NLIB_CEXPR const size_t buf_size = N;
165  NLIB_ALWAYS_INLINE MiniBufOut() NLIB_NOEXCEPT { cur_ = &buf_[0]; }
166  template<class OS>
167  NLIB_ALWAYS_INLINE bool Flush(OS* stream) NLIB_NOEXCEPT {
168  size_t n = cur_ - &buf_[0];
169  cur_ = &buf_[0];
170  return stream->Write(&buf_[0], n);
171  }
172  template<class OS>
173  NLIB_ALWAYS_INLINE bool CheckAndFlush(OS* stream, size_t n) NLIB_NOEXCEPT {
174  if (cur_ + n > &buf_[0] + N) {
175  NLIB_ASSERT(n <= N);
176  return Flush(stream);
177  }
178  return true;
179  }
180  NLIB_ALWAYS_INLINE void Advance(size_t n) NLIB_NOEXCEPT {
181  // CheckAndFlush(stream, n) must be successful beforehand.
182  cur_ += n;
183  }
184  NLIB_ALWAYS_INLINE uint8_t& operator[](size_t n) NLIB_NOEXCEPT {
185  // CheckAndFlush(stream, n + 1) must be successful beforehand.
186  return cur_[n];
187  }
188  template<class OS>
189  NLIB_ALWAYS_INLINE bool WriteAndAdvance(OS* stream, uint8_t data) NLIB_NOEXCEPT {
190  if (NLIB_LIKELY(CheckAndFlush(stream, 1))) {
191  *cur_ = data;
192  ++cur_;
193  return true;
194  }
195  return false;
196  }
197  template<class OS>
198  NLIB_ALWAYS_INLINE bool WriteAndAdvance(OS* stream,
199  const void* data, size_t n) NLIB_NOEXCEPT {
200  if (NLIB_LIKELY(CheckAndFlush(stream, n))) {
201  (void)nlib_memcpy(cur_, n, data, n);
202  cur_ += n;
203  return true;
204  }
205  return false;
206  }
207 
208  private:
209  uint8_t* cur_;
210  uint8_t buf_[N];
211  NLIB_DISALLOW_COPY_AND_ASSIGN(MiniBufOut);
212 };
213 
214 template<class T>
215 class MiniReallocOut {
216  public:
217  NLIB_ALWAYS_INLINE MiniReallocOut(T** mem, uint32_t* cur, uint32_t* memsize) NLIB_NOEXCEPT
218  : mem_(mem), cur_(cur), memsize_(memsize) {}
219  NLIB_ALWAYS_INLINE ~MiniReallocOut() NLIB_NOEXCEPT {}
220  NLIB_ALWAYS_INLINE bool Resize(uint32_t n) NLIB_NOEXCEPT {
221  if (n <= *memsize_) {
222  *cur_ = n;
223  } else {
224  void* p = nlib_realloc(*mem_, n * sizeof(**mem_));
225  if (!p) return false;
226  *mem_ = reinterpret_cast<T*>(p);
227  *memsize_ = n;
228  *cur_ = n;
229  }
230  return true;
231  }
232  NLIB_ALWAYS_INLINE bool Prepare(uint32_t n) NLIB_NOEXCEPT {
233  // T must be int, uint32_t, ... etc. for example
234  if (NLIB_UNLIKELY(*cur_ + n > *memsize_)) {
235  uint32_t newsize;
236  const uint32_t t = 4096 / sizeof(**mem_);
237  if (*cur_ + n >= t) {
238  newsize = ((*cur_ + n) + t - 1) & ~(t - 1);
239  } else {
240  newsize = 1 << (32 - nlib_clz32(*cur_ + n - 1));
241  }
242  void* p = nlib_realloc(*mem_, newsize * sizeof(**mem_));
243  if (!p) return false;
244  *mem_ = reinterpret_cast<T*>(p);
245  *memsize_ = newsize;
246  }
247  return true;
248  }
249  NLIB_ALWAYS_INLINE T& operator[](uint32_t n) NLIB_NOEXCEPT {
250  // Prepare(n + 1) must be successful beforehand.
251  return (*mem_)[*cur_ + n];
252  }
253  NLIB_ALWAYS_INLINE void Append(const T& v) NLIB_NOEXCEPT {
254  // Prepare(1) must be successful beforehand.
255  (*mem_)[*cur_] = v;
256  ++(*cur_);
257  }
258  NLIB_ALWAYS_INLINE void Advance(uint32_t n) NLIB_NOEXCEPT {
259  // Prepare(n) must be successful beforehand.
260  *cur_ += n;
261  }
262 
263  private:
264  T** mem_;
265  uint32_t* cur_;
266  uint32_t* memsize_; // sizeof(*mem) * memsize_ bytes
267  NLIB_DISALLOW_COPY_AND_ASSIGN(MiniReallocOut);
268 };
269 
270 } // namespace detail
271 
272 NLIB_NAMESPACE_END
273 
274 #endif // INCLUDE_NN_NLIB_OUTPUTSTREAM_H_
bool Flush() noexcept
Flushes the stream.
Definition: OutputStream.h:101
#define NLIB_OVERRIDE
Defines override if it is available for use. If not, holds an empty string.
Definition: Config.h:228
#define NLIB_ALWAYS_INLINE
Indicates that the compiler is forced to perform inline expansion of functions.
Definition: Platform_unix.h:97
uint64_t Pos64() const noexcept
Returns the current position in the stream as a 64-bit integer.
Definition: OutputStream.h:55
void SetError(errno_t e) const noexcept
Sets an error to OutputStream.
Definition: OutputStream.h:114
#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
The output is line buffered. This mode is set when data is output to the console. ...
Definition: OutputStream.h:34
size_t Pos() const noexcept
Returns the current position in the stream.
Definition: OutputStream.h:54
#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
static int nlib_clz32(uint32_t x)
Returns the number of consecutive zero bits, with respect to the most significant bit (MSB)...
Definition: Platform.h:2535
#define NLIB_VIS_PUBLIC
Symbols for functions and classes are made available outside of the library.
Definition: Platform_unix.h:89
constexpr OutputStream() noexcept
Instantiates the object with default parameters (default constructor).
Definition: OutputStream.h:42
The class for OutputStream objects for which no actual writing takes place.
Definition: OutputStream.h:148
bool Write(int b) noexcept
Writes one byte of data to the stream.
Definition: OutputStream.h:56
#define NLIB_LIKELY(x)
Indicates to the compiler that condition x is likely to be true.
Definition: Platform_unix.h:99
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
#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:48
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:106
BufferingMode m_BufferingMode
Stores the buffering mode.
Definition: OutputStream.h:142
void ResetBuffer(void *p, size_t nbytes) noexcept
Sets the buffer held by OutputStream.
Definition: OutputStream.h:110
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:229
errno_t GetErrorValue() const noexcept
Gets the error value.
Definition: OutputStream.h:103
bool Write(const void *p, size_t n) noexcept
Writes n bytes of data to the stream.
Definition: OutputStream.h:70
#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:88
int errno_t
Indicates with an int-type typedef that a POSIX error value is returned as the return value...
Definition: NMalloc.h:37