1 /* 2 ** 3 ** Copyright 2017, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #ifndef CONFIRMATIONUI_1_0_DEFAULT_CBOR_H_ 19 #define CONFIRMATIONUI_1_0_DEFAULT_CBOR_H_ 20 21 #include <stddef.h> 22 #include <stdint.h> 23 #include <type_traits> 24 25 namespace android { 26 namespace hardware { 27 namespace confirmationui { 28 namespace support { 29 30 template <typename In, typename Out> 31 Out copy(In begin, In end, Out out) { 32 while (begin != end) { 33 *out++ = *begin++; 34 } 35 return out; 36 } 37 38 enum class Type : uint8_t { 39 NUMBER = 0, 40 NEGATIVE = 1, 41 BYTE_STRING = 2, 42 TEXT_STRING = 3, 43 ARRAY = 4, 44 MAP = 5, 45 TAG = 6, 46 FLOAT = 7, 47 }; 48 49 enum class Error : uint32_t { 50 OK = 0, 51 OUT_OF_DATA = 1, 52 MALFORMED = 2, 53 MALFORMED_UTF8 = 3, 54 }; 55 56 template <typename Key, typename Value> 57 struct MapElement { 58 const Key& key_; 59 const Value& value_; 60 MapElement(const Key& key, const Value& value) : key_(key), value_(value) {} 61 }; 62 63 template <typename... Elems> 64 struct Array; 65 66 template <typename Head, typename... Tail> 67 struct Array<Head, Tail...> { 68 const Head& head_; 69 Array<Tail...> tail_; 70 Array(const Head& head, const Tail&... tail) : head_(head), tail_(tail...) {} 71 constexpr size_t size() const { return sizeof...(Tail) + 1; }; 72 }; 73 74 template <> 75 struct Array<> {}; 76 77 struct TextStr {}; 78 struct ByteStr {}; 79 80 template <typename T, typename Variant> 81 struct StringBuffer { 82 const T* data_; 83 size_t size_; 84 StringBuffer(const T* data, size_t size) : data_(data), size_(size) { 85 static_assert(sizeof(T) == 1, "elements too large"); 86 } 87 const T* data() const { return data_; } 88 size_t size() const { return size_; } 89 }; 90 91 /** 92 * Takes a char array turns it into a StringBuffer of TextStr type. The length of the resulting 93 * StringBuffer is size - 1, effectively stripping the 0 character from the region being considered. 94 * If the terminating 0 shall not be stripped use text_keep_last. 95 */ 96 template <size_t size> 97 StringBuffer<char, TextStr> text(const char (&str)[size]) { 98 if (size > 0) return StringBuffer<char, TextStr>(str, size - 1); 99 return StringBuffer<char, TextStr>(str, size); 100 } 101 102 /** 103 * As opposed to text(const char (&str)[size] this function does not strips the last character. 104 */ 105 template <size_t size> 106 StringBuffer<char, TextStr> text_keep_last(const char (&str)[size]) { 107 return StringBuffer<char, TextStr>(str, size); 108 } 109 110 template <typename T> 111 auto getData(const T& v) -> decltype(v.data()) { 112 return v.data(); 113 } 114 115 template <typename T> 116 auto getData(const T& v) -> decltype(v.c_str()) { 117 return v.c_str(); 118 } 119 120 template <typename T> 121 auto text(const T& str) -> StringBuffer<std::decay_t<decltype(*getData(str))>, TextStr> { 122 return StringBuffer<std::decay_t<decltype(*getData(str))>, TextStr>(getData(str), str.size()); 123 } 124 125 inline StringBuffer<char, TextStr> text(const char* str, size_t size) { 126 return StringBuffer<char, TextStr>(str, size); 127 } 128 129 template <typename T, size_t size> 130 StringBuffer<T, ByteStr> bytes(const T (&str)[size]) { 131 return StringBuffer<T, ByteStr>(str, size); 132 } 133 134 template <typename T> 135 StringBuffer<T, ByteStr> bytes(const T* str, size_t size) { 136 return StringBuffer<T, ByteStr>(str, size); 137 } 138 139 template <typename T> 140 auto bytes(const T& str) -> StringBuffer<std::decay_t<decltype(*getData(str))>, ByteStr> { 141 return StringBuffer<std::decay_t<decltype(*getData(str))>, ByteStr>(getData(str), str.size()); 142 } 143 144 template <typename... Elems> 145 struct Map; 146 147 template <typename HeadKey, typename HeadValue, typename... Tail> 148 struct Map<MapElement<HeadKey, HeadValue>, Tail...> { 149 const MapElement<HeadKey, HeadValue>& head_; 150 Map<Tail...> tail_; 151 Map(const MapElement<HeadKey, HeadValue>& head, const Tail&... tail) 152 : head_(head), tail_(tail...) {} 153 constexpr size_t size() const { return sizeof...(Tail) + 1; }; 154 }; 155 156 template <> 157 struct Map<> {}; 158 159 template <typename... Keys, typename... Values> 160 Map<MapElement<Keys, Values>...> map(const MapElement<Keys, Values>&... elements) { 161 return Map<MapElement<Keys, Values>...>(elements...); 162 } 163 164 template <typename... Elements> 165 Array<Elements...> arr(const Elements&... elements) { 166 return Array<Elements...>(elements...); 167 } 168 169 template <typename Key, typename Value> 170 MapElement<Key, Value> pair(const Key& k, const Value& v) { 171 return MapElement<Key, Value>(k, v); 172 } 173 174 template <size_t size> 175 struct getUnsignedType; 176 177 template <> 178 struct getUnsignedType<sizeof(uint8_t)> { 179 typedef uint8_t type; 180 }; 181 template <> 182 struct getUnsignedType<sizeof(uint16_t)> { 183 typedef uint16_t type; 184 }; 185 template <> 186 struct getUnsignedType<sizeof(uint32_t)> { 187 typedef uint32_t type; 188 }; 189 template <> 190 struct getUnsignedType<sizeof(uint64_t)> { 191 typedef uint64_t type; 192 }; 193 194 template <size_t size> 195 using Unsigned = typename getUnsignedType<size>::type; 196 197 class WriteState { 198 public: 199 WriteState() : data_(nullptr), size_(0), error_(Error::OK) {} 200 WriteState(uint8_t* buffer, size_t size) : data_(buffer), size_(size), error_(Error::OK) {} 201 WriteState(uint8_t* buffer, size_t size, Error error) 202 : data_(buffer), size_(size), error_(error) {} 203 template <size_t size> 204 WriteState(uint8_t (&buffer)[size]) : data_(buffer), size_(size), error_(Error::OK) {} 205 206 WriteState& operator++() { 207 if (size_) { 208 ++data_; 209 --size_; 210 } else { 211 error_ = Error::OUT_OF_DATA; 212 } 213 return *this; 214 } 215 WriteState& operator+=(size_t offset) { 216 if (offset > size_) { 217 error_ = Error::OUT_OF_DATA; 218 } else { 219 data_ += offset; 220 size_ -= offset; 221 } 222 return *this; 223 } 224 operator bool() const { return error_ == Error::OK; } 225 226 uint8_t* data_; 227 size_t size_; 228 Error error_; 229 }; 230 231 WriteState writeHeader(WriteState wState, Type type, const uint64_t value); 232 bool checkUTF8Copy(const char* begin, const char* const end, uint8_t* out); 233 234 template <typename T> 235 WriteState writeNumber(WriteState wState, const T& v) { 236 if (!wState) return wState; 237 if (v >= 0) { 238 return writeHeader(wState, Type::NUMBER, v); 239 } else { 240 return writeHeader(wState, Type::NEGATIVE, UINT64_C(-1) - v); 241 } 242 } 243 244 inline WriteState write(const WriteState& wState, const uint8_t& v) { 245 return writeNumber(wState, v); 246 } 247 inline WriteState write(const WriteState& wState, const int8_t& v) { 248 return writeNumber(wState, v); 249 } 250 inline WriteState write(const WriteState& wState, const uint16_t& v) { 251 return writeNumber(wState, v); 252 } 253 inline WriteState write(const WriteState& wState, const int16_t& v) { 254 return writeNumber(wState, v); 255 } 256 inline WriteState write(const WriteState& wState, const uint32_t& v) { 257 return writeNumber(wState, v); 258 } 259 inline WriteState write(const WriteState& wState, const int32_t& v) { 260 return writeNumber(wState, v); 261 } 262 inline WriteState write(const WriteState& wState, const uint64_t& v) { 263 return writeNumber(wState, v); 264 } 265 inline WriteState write(const WriteState& wState, const int64_t& v) { 266 return writeNumber(wState, v); 267 } 268 269 template <typename T> 270 WriteState write(WriteState wState, const StringBuffer<T, TextStr>& v) { 271 wState = writeHeader(wState, Type::TEXT_STRING, v.size()); 272 uint8_t* buffer = wState.data_; 273 wState += v.size(); 274 if (!wState) return wState; 275 if (!checkUTF8Copy(v.data(), v.data() + v.size(), buffer)) { 276 wState.error_ = Error::MALFORMED_UTF8; 277 } 278 return wState; 279 } 280 281 template <typename T> 282 WriteState write(WriteState wState, const StringBuffer<T, ByteStr>& v) { 283 wState = writeHeader(wState, Type::BYTE_STRING, v.size()); 284 uint8_t* buffer = wState.data_; 285 wState += v.size(); 286 if (!wState) return wState; 287 static_assert(sizeof(*v.data()) == 1, "elements too large"); 288 copy(v.data(), v.data() + v.size(), buffer); 289 return wState; 290 } 291 292 template <template <typename...> class Arr> 293 WriteState writeArrayHelper(WriteState wState, const Arr<>&) { 294 return wState; 295 } 296 297 template <template <typename...> class Arr, typename Head, typename... Tail> 298 WriteState writeArrayHelper(WriteState wState, const Arr<Head, Tail...>& arr) { 299 wState = write(wState, arr.head_); 300 return writeArrayHelper(wState, arr.tail_); 301 } 302 303 template <typename... Elems> 304 WriteState write(WriteState wState, const Map<Elems...>& map) { 305 if (!wState) return wState; 306 wState = writeHeader(wState, Type::MAP, map.size()); 307 return writeArrayHelper(wState, map); 308 } 309 310 template <typename... Elems> 311 WriteState write(WriteState wState, const Array<Elems...>& arr) { 312 if (!wState) return wState; 313 wState = writeHeader(wState, Type::ARRAY, arr.size()); 314 return writeArrayHelper(wState, arr); 315 } 316 317 template <typename Key, typename Value> 318 WriteState write(WriteState wState, const MapElement<Key, Value>& element) { 319 if (!wState) return wState; 320 wState = write(wState, element.key_); 321 return write(wState, element.value_); 322 } 323 324 template <typename Head, typename... Tail> 325 WriteState write(WriteState wState, const Head& head, const Tail&... tail) { 326 wState = write(wState, head); 327 return write(wState, tail...); 328 } 329 330 } // namespace support 331 } // namespace confirmationui 332 } // namespace hardware 333 } // namespace android 334 335 #endif // CONFIRMATIONUI_1_0_DEFAULT_CBOR_H_ 336