GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
charstream.hpp
1 /**
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 
24 #ifndef GRAPHLAB_CHARSTREAM
25 #define GRAPHLAB_CHARSTREAM
26 
27 #include <boost/iostreams/stream.hpp>
28 #include <boost/iostreams/categories.hpp>
29 
30 namespace graphlab {
31 
32  /// \ingroup util_internal
33  namespace charstream_impl {
34  /// \ingroup util_internal
35  template <bool self_deleting>
36  struct resizing_array_sink {
37 
38 
39  resizing_array_sink(size_t initial = 0) : str(NULL) {
40  if(initial > 0) {
41  str = (char*)(malloc(initial));
42  assert(str != NULL);
43  }
44  len = 0;
45  buffer_size = initial;
46  }
47 
48  resizing_array_sink(const resizing_array_sink& other) :
49  len(other.len), buffer_size(other.buffer_size) {
50  if(self_deleting) {
51  str = (char*)(malloc(other.buffer_size));
52  assert(str != NULL);
53  memcpy(str, other.str, len);
54  } else {
55  str = other.str;
56  }
57  }
58 
59  ~resizing_array_sink() {
60  if( self_deleting && str != NULL) {
61  free((void*)str);
62  }
63  }
64 
65  /** Gives up the underlying pointer without
66  * freeing it */
67  void relinquish() {
68  str = NULL;
69  len = 0;
70  buffer_size = 0;
71  }
72 
73  size_t size() const { return len; }
74  char* c_str() { return str; }
75  const char* c_str() const { return str; }
76 
77  void clear() {
78  len = 0;
79  }
80 
81  void clear(size_t new_buffer_size) {
82  len = 0;
83  str = (char*)realloc(str, new_buffer_size);
84  buffer_size = new_buffer_size;
85  }
86 
87  void reserve(size_t new_buffer_size) {
88  if (new_buffer_size > buffer_size) {
89  str = (char*)realloc(str, new_buffer_size);
90  buffer_size = new_buffer_size;
91  }
92  }
93 
94  char *str;
95  size_t len;
96  size_t buffer_size;
97  typedef char char_type;
98  struct category: public boost::iostreams::device_tag,
99  public boost::iostreams::output,
100  public boost::iostreams::multichar_tag { };
101 
102  /** the optimal buffer size is 0. */
103  inline std::streamsize optimal_buffer_size() const { return 0; }
104 
105  inline std::streamsize advance(std::streamsize n) {
106  if (len + n > buffer_size) {
107  // double in length if we need more buffer
108  buffer_size = 2 * (len + n);
109  str = (char*)realloc(str, buffer_size);
110  assert(str != NULL);
111  }
112  len += n;
113  return n;
114  }
115 
116  inline std::streamsize write(const char* s, std::streamsize n) {
117  if (len + n > buffer_size) {
118  // double in length if we need more buffer
119  buffer_size = 2 * (len + n);
120  str = (char*)realloc(str, buffer_size);
121  assert(str != NULL);
122  }
123  memcpy(str + len, s, n);
124  len += n;
125  return n;
126  }
127 
128  inline void swap(resizing_array_sink<self_deleting> &other) {
129  std::swap(str, other.str);
130  std::swap(len, other.len);
131  std::swap(buffer_size, other.buffer_size);
132  }
133 
134  };
135 
136  }; // end of impl;
137 
138 
139  /**
140  * \ingroup util
141  * A stream object which stores all streamed output in memory.
142  * It can be used like any other stream object.
143  * For instance:
144  * \code
145  * charstream cstrm;
146  * cstrm << 123 << 10.0 << "hello world" << std::endl;
147  * \endcode
148  *
149  * stream->size() will return the current length of output
150  * and stream->c_str() will return a mutable pointer to the string.
151  */
152  typedef boost::iostreams::stream< charstream_impl::resizing_array_sink<true> >
153  charstream;
154 
155 
156 }; // end of namespace graphlab
157 #endif
158