Turi Create  4.0
charstream.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_CHARSTREAM
7 #define TURI_CHARSTREAM
8 
9 #include <boost/iostreams/stream.hpp>
10 #include <boost/iostreams/categories.hpp>
11 
12 namespace turi {
13 
14  /// \ingroup util_internal
15  namespace charstream_impl {
16  /// \ingroup util_internal
17  template <bool self_deleting>
18  struct resizing_array_sink {
19 
20 
21  resizing_array_sink(size_t initial = 0) : str(NULL) {
22  if(initial > 0) {
23  str = (char*)(malloc(initial));
24  assert(str != NULL);
25  }
26  len = 0;
27  buffer_size = initial;
28  }
29 
30  resizing_array_sink(const resizing_array_sink& other) :
31  len(other.len), buffer_size(other.buffer_size) {
32  if(self_deleting) {
33  str = (char*)(malloc(other.buffer_size));
34  assert(str != NULL);
35  memcpy(str, other.str, len);
36  } else {
37  str = other.str;
38  }
39  }
40 
41  ~resizing_array_sink() {
42  if( self_deleting && str != NULL) {
43  free((void*)str);
44  }
45  }
46 
47  /** Gives up the underlying pointer without
48  * freeing it */
49  void relinquish() {
50  str = NULL;
51  len = 0;
52  buffer_size = 0;
53  }
54 
55  size_t size() const { return len; }
56  char* c_str() { return str; }
57  const char* c_str() const { return str; }
58 
59  void clear() {
60  len = 0;
61  }
62 
63  void clear(size_t new_buffer_size) {
64  len = 0;
65  str = (char*)realloc(str, new_buffer_size);
66  buffer_size = new_buffer_size;
67  }
68 
69  void reserve(size_t new_buffer_size) {
70  if (new_buffer_size > buffer_size) {
71  str = (char*)realloc(str, new_buffer_size);
72  buffer_size = new_buffer_size;
73  }
74  }
75 
76  char *str;
77  size_t len;
78  size_t buffer_size;
79  typedef char char_type;
80  struct category: public boost::iostreams::device_tag,
81  public boost::iostreams::output,
82  public boost::iostreams::multichar_tag { };
83 
84  /** the optimal buffer size is 0. */
85  inline std::streamsize optimal_buffer_size() const { return 0; }
86 
87  inline std::streamsize advance(std::streamsize n) {
88  if (len + n > buffer_size) {
89  // double in length if we need more buffer
90  buffer_size = 2 * (len + n);
91  str = (char*)realloc(str, buffer_size);
92  assert(str != NULL);
93  }
94  len += n;
95  return n;
96  }
97 
98  inline std::streamsize write(const char* s, std::streamsize n) {
99  if (len + n > buffer_size) {
100  // double in length if we need more buffer
101  buffer_size = 2 * (len + n);
102  str = (char*)realloc(str, buffer_size);
103  assert(str != NULL);
104  }
105  memcpy(str + len, s, n);
106  len += n;
107  return n;
108  }
109 
110  inline void swap(resizing_array_sink<self_deleting> &other) {
111  std::swap(str, other.str);
112  std::swap(len, other.len);
113  std::swap(buffer_size, other.buffer_size);
114  }
115 
116  };
117 
118  }; // end of impl;
119 
120 
121  /**
122  * \ingroup util
123  * A stream object which stores all streamed output in memory.
124  * It can be used like any other stream object.
125  * For instance:
126  * \code
127  * charstream cstrm;
128  * cstrm << 123 << 10.0 << "hello world" << std::endl;
129  * \endcode
130  *
131  * stream->size() will return the current length of output
132  * and stream->c_str() will return a mutable pointer to the string.
133  */
134  typedef boost::iostreams::stream< charstream_impl::resizing_array_sink<true> >
135  charstream;
136 
137 
138 }; // end of namespace turi
139 #endif
boost::iostreams::stream< charstream_impl::resizing_array_sink< true > > charstream
Definition: charstream.hpp:118