proxygen
folly::gen::StreamSplitter< Callback > Class Template Reference

#include <String.h>

Public Member Functions

 StreamSplitter (char delimiter, Callback &&pieceCb, uint64_t maxLength=0, uint64_t initialCapacity=0)
 
bool flush ()
 
bool operator() (StringPiece in)
 

Private Attributes

IOBuf buffer_
 
char delimiter_
 
uint64_t maxLength_
 
Callback pieceCb_
 

Detailed Description

template<class Callback>
class folly::gen::StreamSplitter< Callback >

Outputs exactly the same bytes as the input stream, in different chunks. A chunk boundary occurs after each delimiter, or, if maxLength is non-zero, after maxLength bytes, whichever comes first. Your callback can return false to stop consuming the stream at any time.

The splitter buffers the last incomplete chunk, so you must call flush() to consume the piece of the stream after the final delimiter. This piece may be empty. After a flush(), the splitter can be re-used for a new stream.

operator() and flush() return false iff your callback returns false. The internal buffer is not flushed, so reusing such a splitter will have indeterminate results. Same goes if your callback throws. Feel free to fix these corner cases if needed.

Tips:

  • Create via streamSplitter() to take advantage of template deduction.
  • If your callback needs an end-of-stream signal, test for "no trailing delimiter **and** shorter than maxLength".
  • You can fine-tune the initial capacity of the internal IOBuf.

Definition at line 196 of file String.h.

Constructor & Destructor Documentation

template<class Callback>
folly::gen::StreamSplitter< Callback >::StreamSplitter ( char  delimiter,
Callback &&  pieceCb,
uint64_t  maxLength = 0,
uint64_t  initialCapacity = 0 
)
inline

Definition at line 198 of file String.h.

203  : buffer_(IOBuf::CREATE, initialCapacity),
204  delimiter_(delimiter),
205  maxLength_(maxLength),
206  pieceCb_(std::move(pieceCb)) {}
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567

Member Function Documentation

template<class Callback >
bool folly::gen::StreamSplitter< Callback >::flush ( )

Consume any incomplete last line (may be empty). Do this before destroying the StreamSplitter, or you will fail to consume part of the input.

After flush() you may proceed to consume the next stream via ().

Returns false if the callback wants no more data, true otherwise. A return value of false means that this splitter must no longer be used.

Definition at line 128 of file String-inl.h.

References buffer_, and folly::gen::detail::ch().

128  {
129  CHECK(maxLength_ == 0 || buffer_.length() < maxLength_);
131  return false;
132  }
133  // We are ready to handle another stream now.
134  buffer_.clear();
135  return true;
136 }
const char * ch(const unsigned char *p)
Definition: String-inl.h:91
const uint8_t * data() const
Definition: IOBuf.h:499
std::size_t length() const
Definition: IOBuf.h:533
void clear()
Definition: IOBuf.h:728
Range< const char * > StringPiece
template<class Callback >
bool folly::gen::StreamSplitter< Callback >::operator() ( StringPiece  in)

Consume another piece of the input stream.

Returns false only if your callback refuses to consume more data by returning false (true otherwise). A return value of false means that this splitter must no longer be used.

Definition at line 139 of file String-inl.h.

References folly::Range< Iter >::advance(), folly::Range< Iter >::begin(), buffer_, folly::gen::detail::consumeBufferPlus(), folly::gen::detail::consumeFixedSizeChunks(), folly::Range< Iter >::data(), folly::Range< Iter >::empty(), min, prefix(), folly::Range< Iter >::size(), folly::gen::detail::splitPrefix(), and uint64_t.

139  {
141  // NB This code assumes a 1-byte delimiter. It's not too hard to support
142  // multibyte delimiters, just remember that maxLength_ chunks can end up
143  // falling in the middle of a delimiter.
144  bool found = detail::splitPrefix(in, prefix, delimiter_);
145  if (buffer_.length() != 0) {
146  if (found) {
147  uint64_t num_to_add = prefix.size();
148  if (maxLength_) {
149  CHECK(buffer_.length() < maxLength_);
150  // Consume as much of prefix as possible without exceeding maxLength_
151  num_to_add = std::min(maxLength_ - buffer_.length(), num_to_add);
152  }
153 
154  // Append part of the prefix to the buffer, and send it to the callback
155  if (!detail::consumeBufferPlus(pieceCb_, buffer_, prefix, num_to_add)) {
156  return false;
157  }
158 
160  return false;
161  }
162 
163  found = detail::splitPrefix(in, prefix, delimiter_);
164  // Post-conditions:
165  // - we consumed all of buffer_ and all of the first prefix.
166  // - found, in, and prefix reflect the second delimiter_ search
167  } else if (maxLength_ && buffer_.length() + in.size() >= maxLength_) {
168  // Send all of buffer_, plus a bit of in, to the callback
171  return false;
172  }
173  // Post-conditions:
174  // - we consumed all of buffer, and the minimal # of bytes from in
175  // - found is false
176  } // Otherwise: found is false & we cannot invoke the callback this turn
177  }
178  // Post-condition: buffer_ is nonempty only if found is false **and**
179  // len(buffer + in) < maxLength_.
180 
181  // Send lines to callback directly from input (no buffer)
182  while (found) { // Buffer guaranteed to be empty
184  return false;
185  }
186  found = detail::splitPrefix(in, prefix, delimiter_);
187  }
188 
189  // No more delimiters left; consume 'in' until it is shorter than maxLength_
190  if (maxLength_) {
191  while (in.size() >= maxLength_) { // Buffer is guaranteed to be empty
192  if (!pieceCb_(StringPiece(in.begin(), maxLength_))) {
193  return false;
194  }
195  in.advance(maxLength_);
196  }
197  }
198 
199  if (!in.empty()) { // Buffer may be nonempty
200  // Incomplete line left, append to buffer
201  buffer_.reserve(0, in.size());
202  memcpy(buffer_.writableTail(), in.data(), in.size());
203  buffer_.append(in.size());
204  }
205  CHECK(maxLength_ == 0 || buffer_.length() < maxLength_);
206  return true;
207 }
bool consumeBufferPlus(Callback &cb, IOBuf &buf, StringPiece &s, uint64_t n)
Definition: String-inl.h:113
void reserve(std::size_t minHeadroom, std::size_t minTailroom)
Definition: IOBuf.h:741
bool prefix(Cursor &c, uint32_t expected)
size_t splitPrefix(StringPiece &in, StringPiece &prefix, char delimiter)
Definition: String-inl.h:38
uint8_t * writableTail()
Definition: IOBuf.h:526
LogLevel min
Definition: LogLevel.cpp:30
std::size_t length() const
Definition: IOBuf.h:533
Range< const char * > StringPiece
bool consumeFixedSizeChunks(Callback &cb, StringPiece &s, uint64_t maxLength)
Definition: String-inl.h:97
void append(std::size_t amount)
Definition: IOBuf.h:689

Member Data Documentation

template<class Callback>
IOBuf folly::gen::StreamSplitter< Callback >::buffer_
private

Definition at line 231 of file String.h.

template<class Callback>
char folly::gen::StreamSplitter< Callback >::delimiter_
private

Definition at line 232 of file String.h.

template<class Callback>
uint64_t folly::gen::StreamSplitter< Callback >::maxLength_
private

Definition at line 233 of file String.h.

template<class Callback>
Callback folly::gen::StreamSplitter< Callback >::pieceCb_
private

Definition at line 234 of file String.h.


The documentation for this class was generated from the following files: