e7ea164d915b400416824c902f3ff17b4d0d3634
[android/platform-hardware-interfaces.git] / confirmationui / support / src / cbor.cpp
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 */
18 #include <android/hardware/confirmationui/support/cbor.h>
20 namespace android {
21 namespace hardware {
22 namespace confirmationui {
23 namespace support {
24 namespace {
26 inline uint8_t getByte(const uint64_t& v, const uint8_t index) {
27     return v >> (index * 8);
28 }
30 WriteState writeBytes(WriteState state, uint64_t value, uint8_t size) {
31     auto pos = state.data_;
32     if (!(state += size)) return state;
33     switch (size) {
34         case 8:
35             *pos++ = getByte(value, 7);
36             *pos++ = getByte(value, 6);
37             *pos++ = getByte(value, 5);
38             *pos++ = getByte(value, 4);
39         case 4:
40             *pos++ = getByte(value, 3);
41             *pos++ = getByte(value, 2);
42         case 2:
43             *pos++ = getByte(value, 1);
44         case 1:
45             *pos++ = value;
46             break;
47         default:
48             state.error_ = Error::MALFORMED;
49     }
50     return state;
51 }
53 }  // anonymous namespace
55 WriteState writeHeader(WriteState wState, Type type, const uint64_t value) {
56     if (!wState) return wState;
57     uint8_t& header = *wState.data_;
58     if (!++wState) return wState;
59     header = static_cast<uint8_t>(type) << 5;
60     if (value < 24) {
61         header |= static_cast<uint8_t>(value);
62     } else if (value < 0x100) {
63         header |= 24;
64         wState = writeBytes(wState, value, 1);
65     } else if (value < 0x10000) {
66         header |= 25;
67         wState = writeBytes(wState, value, 2);
68     } else if (value < 0x100000000) {
69         header |= 26;
70         wState = writeBytes(wState, value, 4);
71     } else {
72         header |= 27;
73         wState = writeBytes(wState, value, 8);
74     }
75     return wState;
76 }
78 bool checkUTF8Copy(const char* begin, const char* const end, uint8_t* out) {
79     uint32_t multi_byte_length = 0;
80     while (begin != end) {
81         if (multi_byte_length) {
82             // parsing multi byte character - must start with 10xxxxxx
83             --multi_byte_length;
84             if ((*begin & 0xc0) != 0x80) return false;
85         } else if (!((*begin) & 0x80)) {
86             // 7bit character -> nothing to be done
87         } else {
88             // msb is set and we were not parsing a multi byte character
89             // so this must be a header byte
90             char c = *begin << 1;
91             while (c & 0x80) {
92                 ++multi_byte_length;
93                 c <<= 1;
94             }
95             // headers of the form 10xxxxxx are not allowed
96             if (multi_byte_length < 1) return false;
97             // chars longer than 4 bytes are not allowed (multi_byte_length does not count the
98             // header thus > 3
99             if (multi_byte_length > 3) return false;
100         }
101         if (out) *out++ = *reinterpret_cast<const uint8_t*>(begin++);
102     }
103     // if the string ends in the middle of a multi byte char it is invalid
104     if (multi_byte_length) return false;
105     return true;
108 }  // namespace support
109 }  // namespace confirmationui
110 }  // namespace hardware
111 }  // namespace android