Home | History | Annotate | Download | only in support
      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