Apache Mesos
recordio.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_RECORDIO_HPP__
14 #define __STOUT_RECORDIO_HPP__
15 
16 #include <stdlib.h>
17 
18 #include <deque>
19 #include <functional>
20 #include <string>
21 
22 #include <stout/check.hpp>
23 #include <stout/foreach.hpp>
24 #include <stout/numify.hpp>
25 #include <stout/option.hpp>
26 #include <stout/stringify.hpp>
27 #include <stout/try.hpp>
28 
55 namespace recordio {
56 
63 inline std::string encode(const std::string& record)\
64 {
65  return stringify(record.size()) + "\n" + record;
66 }
67 
68 
72 class Decoder
73 {
74 public:
75  Decoder() : state(HEADER) {}
76 
89  Try<std::deque<std::string>> decode(const std::string& data)
90  {
91  if (state == FAILED) {
92  return Error("Decoder is in a FAILED state");
93  }
94 
95  std::deque<std::string> records;
96 
97  foreach (char c, data) {
98  if (state == HEADER) {
99  // Keep reading until we have the entire header.
100  if (c != '\n') {
101  buffer += c;
102  continue;
103  }
104 
105  Try<size_t> numify = ::numify<size_t>(buffer);
106 
107  // If we were unable to decode the length header, do not
108  // continue decoding since we cannot determine where to
109  // pick up the next length header!
110  if (numify.isError()) {
111  state = FAILED;
112  return Error("Failed to decode length '" + buffer + "': " +
113  numify.error());
114  }
115 
116  length = numify.get();
117  buffer.clear();
118  state = RECORD;
119 
120  // Note that for 0 length records, we immediately decode.
121  if (numify.get() <= 0) {
122  records.push_back(buffer);
123  state = HEADER;
124  }
125  } else if (state == RECORD) {
126  CHECK_SOME(length);
127  CHECK_LT(buffer.size(), length.get());
128 
129  buffer += c;
130 
131  if (buffer.size() == length.get()) {
132  records.push_back(std::move(buffer));
133  buffer.clear();
134  state = HEADER;
135  }
136  }
137  }
138 
139  return records;
140  }
141 
142 private:
143  enum
144  {
145  HEADER,
146  RECORD,
147  FAILED
148  } state;
149 
150  // TODO(bmahler): Avoid string here as it will not free
151  // its underlying memory allocation when we clear it.
152  std::string buffer;
153  Option<size_t> length;
154 };
155 
156 } // namespace recordio {
157 
158 #endif // __STOUT_RECORDIO_HPP__
Definition: errorbase.hpp:36
Provides facilities for "Record-IO" encoding of data.
Definition: recordio.hpp:55
T & get()&
Definition: try.hpp:80
Definition: check.hpp:33
std::string encode(const std::string &record)
Returns the "Record-IO" encoded record.
Definition: recordio.hpp:63
Try< std::deque< std::string > > decode(const std::string &data)
Decodes another chunk of data from the "Record-IO" stream and returns the attempted decoding of any a...
Definition: recordio.hpp:89
Try< T > numify(const std::string &s)
Definition: numify.hpp:29
#define CHECK_SOME(expression)
Definition: check.hpp:50
const T & get() const &
Definition: option.hpp:119
Decoder()
Definition: recordio.hpp:75
static Try error(const E &e)
Definition: try.hpp:43
bool isError() const
Definition: try.hpp:78
std::string stringify(int flags)
Decodes records from "Record-IO" data (see above).
Definition: recordio.hpp:72