proxygen
StructuredHeadersEncoder.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
10 
12 #include <typeinfo>
13 #include <boost/lexical_cast.hpp>
14 #include <boost/variant.hpp>
15 #include <glog/logging.h>
16 #include "StructuredHeadersUtilities.h" // @manual=:utils
17 
18 namespace proxygen {
19 
20 using namespace StructuredHeaders;
21 
23  const std::vector<StructuredHeaderItem>& input) {
24 
25  if (input.empty()) {
26  return handleEncodeError(EncodeError::EMPTY_DATA_STRUCTURE);
27  }
28 
29  for (auto it = input.begin(); it != input.end(); it++) {
30  auto err = encodeItem(*it);
31  if (err != EncodeError::OK) {
32  return err;
33  }
34 
35  if (std::next(it, 1)!= input.end()) {
36  outputStream_ << ", ";
37  }
38  }
39 
40  return EncodeError::OK;
41 }
42 
44  const Dictionary& input) {
45 
46  if (input.empty()) {
47  return handleEncodeError(EncodeError::EMPTY_DATA_STRUCTURE);
48  }
49 
50  for (auto it = input.begin(); it != input.end(); it++) {
51  auto err = encodeIdentifier(it->first);
52  if (err != EncodeError::OK) {
53  return err;
54  }
55 
56  outputStream_ << "=";
57 
58  err = encodeItem(it->second);
59  if (err != EncodeError::OK) {
60  return err;
61  }
62 
63  if (std::next(it, 1) != input.end()) {
64  outputStream_ << ", ";
65  }
66  }
67 
68  return EncodeError::OK;
69 }
70 
72  const ParameterisedList& input) {
73 
74  if (input.empty()) {
75  return handleEncodeError(EncodeError::EMPTY_DATA_STRUCTURE);
76  }
77 
78  for (auto it1 = input.begin(); it1 != input.end(); it1++) {
79  auto err = encodeIdentifier(it1->identifier);
80  if (err != EncodeError::OK) {
81  return err;
82  }
83 
84  for (auto it2 = it1->parameterMap.begin();
85  it2 != it1->parameterMap.end(); it2++) {
86 
87  outputStream_ << "; ";
88 
89  err = encodeIdentifier(it2->first);
90  if (err != EncodeError::OK) {
91  return err;
92  }
93 
94  if (it2->second.tag != StructuredHeaderItem::Type::NONE) {
95  outputStream_ << "=";
96  err = encodeItem(it2->second);
97  if (err != EncodeError::OK) {
98  return err;
99  }
100  }
101  }
102 
103  if (std::next(it1, 1) != input.end()) {
104  outputStream_ << ", ";
105  }
106  }
107 
108  return EncodeError::OK;
109 }
110 
112  output_(),
113  buf_(output_),
114  outputStream_(&buf_) {
115  outputStream_.precision(kMaxValidFloatLength - 1);
116 }
117 
119  const StructuredHeaderItem& input) {
120 
121  if (!itemTypeMatchesContent(input)) {
122  return handleEncodeError(EncodeError::ITEM_TYPE_MISMATCH);
123  }
124 
125  switch (input.tag) {
127  return encodeString(boost::get<std::string>(input.value));
128  case StructuredHeaderItem::Type::INT64:
129  return encodeInteger(boost::get<int64_t>(input.value));
130  case StructuredHeaderItem::Type::DOUBLE:
131  return encodeFloat(boost::get<double>(input.value));
132  case StructuredHeaderItem::Type::BINARYCONTENT:
133  return encodeBinaryContent(
134  boost::get<std::string>(input.value));
135  default:
136  return handleEncodeError(EncodeError::ENCODING_NULL_ITEM);
137  }
138 
139  return EncodeError::OK;
140 }
141 
143  const std::string& input) {
144 
145  outputStream_ << "*";
146  outputStream_ << encodeBase64(input);
147  outputStream_ << "*";
148 
149  return EncodeError::OK;
150 }
151 
153 
154  if (!isValidString(input)) {
155  return handleEncodeError(EncodeError::BAD_STRING, input);
156  }
157 
158  outputStream_ << "\"";
159  for (char c : input) {
160  if (c == '"' || c == '\\') {
161  outputStream_ << "\\";
162  }
163  outputStream_ << c;
164  }
165 
166  outputStream_ << "\"";
167 
168  return EncodeError::OK;
169 }
170 
172 
173  outputStream_ << input;
174 
175  return EncodeError::OK;
176 }
177 
179 
180  outputStream_ << input;
181 
182  return EncodeError::OK;
183 }
184 
186  const std::string &input) {
187 
188  if (!isValidIdentifier(input)) {
189  return handleEncodeError(EncodeError::BAD_IDENTIFIER, input);
190  }
191  outputStream_ << input;
192  return EncodeError::OK;
193 }
194 
195 // Used to print an error when a string type (eg: a string or binary content)
196 // was involved in the error
198  const std::string &culprit) {
199 
200  LOG_EVERY_N(ERROR, 1000) << "Error message: " <<
201  encodeErrorDescription.at(err) << " .The culprit was: " << culprit;
202  return err;
203 }
204 
205 // Used to print more general error messages (eg: empty data structure)
207  LOG_EVERY_N(ERROR, 1000) << "Error message: " <<
208  encodeErrorDescription.at(err);
209  return err;
210 }
211 
213  outputStream_.flush();
214  return std::move(output_);
215 }
216 
217 }
EncodeError encodeItem(const StructuredHeaderItem &input)
EncodeError encodeIdentifier(const std::string &input)
EncodeError encodeDictionary(const Dictionary &input)
std::vector< StructuredHeaders::ParameterisedIdentifier > ParameterisedList
bool isValidIdentifier(const std::string &s)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
bool itemTypeMatchesContent(const StructuredHeaderItem &input)
#define STRING
EncodeError encodeList(const std::vector< StructuredHeaderItem > &input)
std::string encodeBase64(const std::string &input)
boost::variant< int64_t, double, std::string > value
std::unordered_map< std::string, StructuredHeaderItem > Dictionary
EncodeError handleEncodeError(EncodeError err, const std::string &badContent)
const char * string
Definition: Conv.cpp:212
EncodeError encodeString(const std::string &input)
EncodeError encodeBinaryContent(const std::string &input)
bool isValidString(const std::string &s)
char c
EncodeError encodeParameterisedList(const ParameterisedList &input)
def next(obj)
Definition: ast.py:58
static const std::map< EncodeError, std::string > encodeErrorDescription