LLVM  8.0.1
MsgPackTypes.cpp
Go to the documentation of this file.
1 //===- MsgPackTypes.cpp - MsgPack Types -------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file
11 /// Implementation of types representing MessagePack "documents".
12 //
13 //===----------------------------------------------------------------------===//
14 
16 #include "llvm/Support/Error.h"
17 
18 using namespace llvm;
19 using namespace msgpack;
20 
21 namespace llvm {
22 namespace msgpack {
23 void ScalarNode::anchor() {}
24 void ArrayNode::anchor() {}
25 void MapNode::anchor() {}
26 }
27 }
28 
29 Expected<OptNodePtr> Node::readArray(Reader &MPReader, size_t Length) {
30  auto A = std::make_shared<ArrayNode>();
31  for (size_t I = 0; I < Length; ++I) {
32  auto OptNodeOrErr = Node::read(MPReader);
33  if (auto Err = OptNodeOrErr.takeError())
34  return std::move(Err);
35  if (!*OptNodeOrErr)
36  return make_error<StringError>(
37  "Insufficient array elements",
38  std::make_error_code(std::errc::invalid_argument));
39  A->push_back(std::move(**OptNodeOrErr));
40  }
41  return OptNodePtr(std::move(A));
42 }
43 
44 Expected<OptNodePtr> Node::readMap(Reader &MPReader, size_t Length) {
45  auto M = std::make_shared<MapNode>();
46  for (size_t I = 0; I < Length; ++I) {
47  auto OptKeyOrErr = Node::read(MPReader);
48  if (auto Err = OptKeyOrErr.takeError())
49  return std::move(Err);
50  if (!*OptKeyOrErr)
51  return make_error<StringError>(
52  "Insufficient map elements",
53  std::make_error_code(std::errc::invalid_argument));
54  auto OptValOrErr = Node::read(MPReader);
55  if (auto Err = OptValOrErr.takeError())
56  return std::move(Err);
57  if (!*OptValOrErr)
58  return make_error<StringError>(
59  "Insufficient map elements",
60  std::make_error_code(std::errc::invalid_argument));
61  auto *Key = dyn_cast<ScalarNode>((*OptKeyOrErr)->get());
62  if (!Key)
63  return make_error<StringError>(
64  "Only string map keys are supported",
65  std::make_error_code(std::errc::invalid_argument));
66  if (Key->getScalarKind() != ScalarNode::SK_String)
67  return make_error<StringError>(
68  "Only string map keys are supported",
69  std::make_error_code(std::errc::invalid_argument));
70  M->try_emplace(Key->getString(), std::move(**OptValOrErr));
71  }
72  return OptNodePtr(std::move(M));
73 }
74 
76  Object Obj;
77 
78  auto ContinueOrErr = MPReader.read(Obj);
79  if (auto Err = ContinueOrErr.takeError())
80  return std::move(Err);
81  if (!*ContinueOrErr)
82  return None;
83 
84  switch (Obj.Kind) {
85  case Type::Int:
86  return OptNodePtr(std::make_shared<ScalarNode>(Obj.Int));
87  case Type::UInt:
88  return OptNodePtr(std::make_shared<ScalarNode>(Obj.UInt));
89  case Type::Nil:
90  return OptNodePtr(std::make_shared<ScalarNode>());
91  case Type::Boolean:
92  return OptNodePtr(std::make_shared<ScalarNode>(Obj.Bool));
93  case Type::Float:
94  return OptNodePtr(std::make_shared<ScalarNode>(Obj.Float));
95  case Type::String:
96  return OptNodePtr(std::make_shared<ScalarNode>(Obj.Raw));
97  case Type::Binary:
98  return OptNodePtr(std::make_shared<ScalarNode>(Obj.Raw));
99  case Type::Array:
100  return Node::readArray(MPReader, Obj.Length);
101  case Type::Map:
102  return Node::readMap(MPReader, Obj.Length);
103  case Type::Extension:
104  return make_error<StringError>(
105  "Extension types are not supported",
106  std::make_error_code(std::errc::invalid_argument));
107  }
108  llvm_unreachable("msgpack::Type not handled");
109 }
110 
111 void ScalarNode::destroy() {
112  switch (SKind) {
113  case SK_String:
114  case SK_Binary:
115  StringValue.~basic_string();
116  break;
117  default:
118  // POD types do not require destruction
119  break;
120  }
121 }
122 
123 ScalarNode::ScalarNode(int64_t IntValue)
124  : Node(NK_Scalar), SKind(SK_Int), IntValue(IntValue) {}
125 
127  : ScalarNode(static_cast<int64_t>(IntValue)) {}
128 
130  : Node(NK_Scalar), SKind(SK_UInt), UIntValue(UIntValue) {}
131 
133  : ScalarNode(static_cast<uint64_t>(IntValue)) {}
134 
136 
138  : Node(NK_Scalar), SKind(SK_Boolean), BoolValue(BoolValue) {}
139 
141  : Node(NK_Scalar), SKind(SK_Float), BoolValue(FloatValue) {}
142 
144  : Node(NK_Scalar), SKind(SK_String) {
145  new (&this->StringValue) std::string(StringValue);
146 }
147 
149  : ScalarNode(StringRef(StringValue)) {}
150 
152  : Node(NK_Scalar), SKind(SK_String) {
153  new (&this->StringValue) std::string(StringValue);
154 }
155 
157  : Node(NK_Scalar), SKind(SK_Binary) {
158  new (&StringValue) std::string(BinaryValue.getBuffer());
159 }
160 
161 ScalarNode::~ScalarNode() { destroy(); }
162 
164  destroy();
165  switch (SKind = RHS.SKind) {
166  case SK_Int:
167  IntValue = RHS.IntValue;
168  break;
169  case SK_UInt:
170  UIntValue = RHS.UIntValue;
171  break;
172  case SK_Boolean:
173  BoolValue = RHS.BoolValue;
174  break;
175  case SK_Float:
176  FloatValue = RHS.FloatValue;
177  break;
178  case SK_String:
179  case SK_Binary:
180  new (&StringValue) std::string(std::move(RHS.StringValue));
181  break;
182  case SK_Nil:
183  // pass
184  break;
185  }
186  return *this;
187 }
188 
190  switch (SKind) {
191  case SK_Int:
192  return yaml::ScalarTraits<int64_t>::input(ScalarStr, nullptr, IntValue);
193  case SK_UInt:
194  return yaml::ScalarTraits<uint64_t>::input(ScalarStr, nullptr, UIntValue);
195  case SK_Nil:
196  return StringRef();
197  case SK_Boolean:
198  return yaml::ScalarTraits<bool>::input(ScalarStr, nullptr, BoolValue);
199  case SK_Float:
200  return yaml::ScalarTraits<double>::input(ScalarStr, nullptr, FloatValue);
201  case SK_Binary:
202  case SK_String:
203  return yaml::ScalarTraits<std::string>::input(ScalarStr, nullptr,
204  StringValue);
205  }
206  llvm_unreachable("unrecognized ScalarKind");
207 }
208 
210  switch (SKind) {
211  case SK_Int:
212  yaml::ScalarTraits<int64_t>::output(IntValue, nullptr, OS);
213  break;
214  case SK_UInt:
215  yaml::ScalarTraits<uint64_t>::output(UIntValue, nullptr, OS);
216  break;
217  case SK_Nil:
218  yaml::ScalarTraits<StringRef>::output("", nullptr, OS);
219  break;
220  case SK_Boolean:
221  yaml::ScalarTraits<bool>::output(BoolValue, nullptr, OS);
222  break;
223  case SK_Float:
224  yaml::ScalarTraits<double>::output(FloatValue, nullptr, OS);
225  break;
226  case SK_Binary:
227  case SK_String:
228  yaml::ScalarTraits<std::string>::output(StringValue, nullptr, OS);
229  break;
230  }
231 }
232 
233 yaml::QuotingType ScalarNode::mustQuoteYAML(StringRef ScalarStr) const {
234  switch (SKind) {
235  case SK_Int:
236  return yaml::ScalarTraits<int64_t>::mustQuote(ScalarStr);
237  case SK_UInt:
238  return yaml::ScalarTraits<uint64_t>::mustQuote(ScalarStr);
239  case SK_Nil:
240  return yaml::ScalarTraits<StringRef>::mustQuote(ScalarStr);
241  case SK_Boolean:
242  return yaml::ScalarTraits<bool>::mustQuote(ScalarStr);
243  case SK_Float:
244  return yaml::ScalarTraits<double>::mustQuote(ScalarStr);
245  case SK_Binary:
246  case SK_String:
247  return yaml::ScalarTraits<std::string>::mustQuote(ScalarStr);
248  }
249  llvm_unreachable("unrecognized ScalarKind");
250 }
251 
252 const char *ScalarNode::IntTag = "!int";
253 const char *ScalarNode::NilTag = "!nil";
254 const char *ScalarNode::BooleanTag = "!bool";
255 const char *ScalarNode::FloatTag = "!float";
256 const char *ScalarNode::StringTag = "!str";
257 const char *ScalarNode::BinaryTag = "!bin";
258 
260  switch (SKind) {
261  case SK_Int:
262  return IntTag;
263  case SK_UInt:
264  return IntTag;
265  case SK_Nil:
266  return NilTag;
267  case SK_Boolean:
268  return BooleanTag;
269  case SK_Float:
270  return FloatTag;
271  case SK_String:
272  return StringTag;
273  case SK_Binary:
274  return BinaryTag;
275  }
276  llvm_unreachable("unrecognized ScalarKind");
277 }
278 
279 void ScalarNode::write(Writer &MPWriter) {
280  switch (SKind) {
281  case SK_Int:
282  MPWriter.write(IntValue);
283  break;
284  case SK_UInt:
285  MPWriter.write(UIntValue);
286  break;
287  case SK_Nil:
288  MPWriter.writeNil();
289  break;
290  case SK_Boolean:
291  MPWriter.write(BoolValue);
292  break;
293  case SK_Float:
294  MPWriter.write(FloatValue);
295  break;
296  case SK_String:
297  MPWriter.write(StringValue);
298  break;
299  case SK_Binary:
300  MPWriter.write(MemoryBufferRef(StringValue, ""));
301  break;
302  }
303 }
const NoneType None
Definition: None.h:24
static const char * FloatTag
Definition: MsgPackTypes.h:241
Expected< bool > read(Object &Obj)
Read one object from the input buffer, advancing past it.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
StringRef getYAMLTag() const
Get the YAML tag for the current ScalarKind.
yaml::QuotingType mustQuoteYAML(StringRef ScalarStr) const
Determine which YAML quoting type the current value would need when output.
StringRef getBuffer() const
Definition: MemoryBuffer.h:273
Writes MessagePack objects to an output stream, one at a time.
Definition: MsgPackWriter.h:41
std::error_code make_error_code(BitcodeError E)
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
ScalarNode()
Construct a Nil ScalarNode.
static const char * BinaryTag
Definition: MsgPackTypes.h:243
void outputYAML(raw_ostream &OS) const
Output a YAML scalar of the current ScalarKind into OS.
Key
PAL metadata keys.
static const char * IntTag
Definition: MsgPackTypes.h:238
static Expected< OptNodePtr > read(Reader &MPReader)
Read from a MessagePack reader MPReader, returning an error if one is encountered, or None if MPReader is at the end of stream, or some Node pointer if some type is read.
MessagePack object, represented as a tagged union of C++ types.
Definition: MsgPackReader.h:76
This is a data structure for representing MessagePack "documents", with methods to go to and from Mes...
static const char * BooleanTag
Definition: MsgPackTypes.h:240
void writeNil()
Write a Nil to the output stream.
Reads MessagePack objects from memory, one at a time.
Definition: MsgPackReader.h:99
Abstract base-class which can be any MessagePack type.
Definition: MsgPackTypes.h:39
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
double Float
Value for Type::Float.
Definition: MsgPackReader.h:86
void write(Writer &MPWriter) override
Write to a MessagePack writer MPWriter.
static const char * NilTag
Definition: MsgPackTypes.h:239
void write(bool b)
Write a Boolean to the output stream.
StringRef Raw
Value for Type::String and Type::Binary.
Definition: MsgPackReader.h:88
ScalarNode & operator=(const ScalarNode &RHS)=delete
#define I(x, y, z)
Definition: MD5.cpp:58
int64_t Int
Value for Type::Int.
Definition: MsgPackReader.h:80
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
bool Bool
Value for Type::Boolean.
Definition: MsgPackReader.h:84
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
A MessagePack scalar.
Definition: MsgPackTypes.h:72
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
uint64_t UInt
Value for Type::Uint.
Definition: MsgPackReader.h:82
Optional< NodePtr > OptNodePtr
Short-hand for an Optional Node pointer.
Definition: MsgPackTypes.h:36
size_t Length
Value for Type::Array and Type::Map.
Definition: MsgPackReader.h:90
static const char * StringTag
Definition: MsgPackTypes.h:242
StringRef inputYAML(StringRef ScalarStr)
Parse a YAML scalar of the current ScalarKind from ScalarStr.