Line data Source code
1 : //===- MsgPackReader.h - Simple MsgPack reader ------------------*- 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 : /// This is a MessagePack reader.
12 : ///
13 : /// See https://github.com/msgpack/msgpack/blob/master/spec.md for the full
14 : /// standard.
15 : ///
16 : /// Typical usage:
17 : /// \code
18 : /// StringRef input = GetInput();
19 : /// msgpack::Reader MPReader(input);
20 : /// msgpack::Object Obj;
21 : ///
22 : /// while (MPReader.read(Obj)) {
23 : /// switch (Obj.Kind) {
24 : /// case msgpack::Type::Int:
25 : // // Use Obj.Int
26 : /// break;
27 : /// // ...
28 : /// }
29 : /// }
30 : /// \endcode
31 : ///
32 : //===----------------------------------------------------------------------===//
33 :
34 : #ifndef LLVM_SUPPORT_MSGPACKREADER_H
35 : #define LLVM_SUPPORT_MSGPACKREADER_H
36 :
37 : #include "llvm/Support/MemoryBuffer.h"
38 : #include "llvm/Support/raw_ostream.h"
39 : #include <cstdint>
40 :
41 : namespace llvm {
42 : namespace msgpack {
43 :
44 : /// MessagePack types as defined in the standard, with the exception of Integer
45 : /// being divided into a signed Int and unsigned UInt variant in order to map
46 : /// directly to C++ types.
47 : ///
48 : /// The types map onto corresponding union members of the \c Object struct.
49 : enum class Type : uint8_t {
50 : Int,
51 : UInt,
52 : Nil,
53 : Boolean,
54 : Float,
55 : String,
56 : Binary,
57 : Array,
58 : Map,
59 : Extension,
60 : };
61 :
62 : /// Extension types are composed of a user-defined type ID and an uninterpreted
63 : /// sequence of bytes.
64 : struct ExtensionType {
65 : /// User-defined extension type.
66 : int8_t Type;
67 : /// Raw bytes of the extension object.
68 : StringRef Bytes;
69 : };
70 :
71 : /// MessagePack object, represented as a tagged union of C++ types.
72 : ///
73 : /// All types except \c Type::Nil (which has only one value, and so is
74 : /// completely represented by the \c Kind itself) map to a exactly one union
75 : /// member.
76 : struct Object {
77 : Type Kind;
78 : union {
79 : /// Value for \c Type::Int.
80 : int64_t Int;
81 : /// Value for \c Type::Uint.
82 : uint64_t UInt;
83 : /// Value for \c Type::Boolean.
84 : bool Bool;
85 : /// Value for \c Type::Float.
86 : double Float;
87 : /// Value for \c Type::String and \c Type::Binary.
88 : StringRef Raw;
89 : /// Value for \c Type::Array and \c Type::Map.
90 : size_t Length;
91 : /// Value for \c Type::Extension.
92 : ExtensionType Extension;
93 : };
94 :
95 81 : Object() : Kind(Type::Int), Int(0) {}
96 : };
97 :
98 : /// Reads MessagePack objects from memory, one at a time.
99 : class Reader {
100 : public:
101 : /// Construct a reader, keeping a reference to the \p InputBuffer.
102 : Reader(MemoryBufferRef InputBuffer);
103 : /// Construct a reader, keeping a reference to the \p Input.
104 : Reader(StringRef Input);
105 :
106 : Reader(const Reader &) = delete;
107 : Reader &operator=(const Reader &) = delete;
108 :
109 : /// Read one object from the input buffer, advancing past it.
110 : ///
111 : /// The \p Obj is updated with the kind of the object read, and the
112 : /// corresponding union member is updated.
113 : ///
114 : /// For the collection objects (Array and Map), only the length is read, and
115 : /// the caller must make and additional \c N calls (in the case of Array) or
116 : /// \c N*2 calls (in the case of Map) to \c Read to retrieve the collection
117 : /// elements.
118 : ///
119 : /// \param [out] Obj filled with next object on success.
120 : ///
121 : /// \returns true when object successfully read, false when at end of
122 : /// input (and so \p Obj was not updated), otherwise an error.
123 : Expected<bool> read(Object &Obj);
124 :
125 : private:
126 : MemoryBufferRef InputBuffer;
127 : StringRef::iterator Current;
128 : StringRef::iterator End;
129 :
130 0 : size_t remainingSpace() {
131 : // The rest of the code maintains the invariant that End >= Current, so
132 : // that this cast is always defined behavior.
133 78 : return static_cast<size_t>(End - Current);
134 : }
135 :
136 : template <class T> Expected<bool> readRaw(Object &Obj);
137 : template <class T> Expected<bool> readInt(Object &Obj);
138 : template <class T> Expected<bool> readUInt(Object &Obj);
139 : template <class T> Expected<bool> readLength(Object &Obj);
140 : template <class T> Expected<bool> readExt(Object &Obj);
141 : Expected<bool> createRaw(Object &Obj, uint32_t Size);
142 : Expected<bool> createExt(Object &Obj, uint32_t Size);
143 : };
144 :
145 : } // end namespace msgpack
146 : } // end namespace llvm
147 :
148 : #endif // LLVM_SUPPORT_MSGPACKREADER_H
|