1 /******************************************************************************
2 *
3 * Copyright (C) 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
19 #include "uuid.h"
20
21 #include <base/rand_util.h>
22 #include <base/strings/stringprintf.h>
23 #include <string.h>
24 #include <algorithm>
25
26 namespace bluetooth {
27
28 static_assert(sizeof(Uuid) == 16, "Uuid must be 16 bytes long!");
29
30 using UUID128Bit = Uuid::UUID128Bit;
31
32 const Uuid Uuid::kEmpty = Uuid::From128BitBE(UUID128Bit{{0x00}});
33
34 namespace {
35 constexpr Uuid kBase = Uuid::From128BitBE(
36 UUID128Bit{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
37 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}});
38 } // namespace
39
GetShortestRepresentationSize() const40 size_t Uuid::GetShortestRepresentationSize() const {
41 if (memcmp(uu.data() + kNumBytes32, kBase.uu.data() + kNumBytes32,
42 kNumBytes128 - kNumBytes32) != 0) {
43 return kNumBytes128;
44 }
45
46 if (uu[0] == 0 && uu[1] == 0) return kNumBytes16;
47
48 return kNumBytes32;
49 }
50
Is16Bit() const51 bool Uuid::Is16Bit() const {
52 return GetShortestRepresentationSize() == kNumBytes16;
53 }
54
As16Bit() const55 uint16_t Uuid::As16Bit() const { return (((uint16_t)uu[2]) << 8) + uu[3]; }
56
As32Bit() const57 uint32_t Uuid::As32Bit() const {
58 return (((uint32_t)uu[0]) << 24) + (((uint32_t)uu[1]) << 16) +
59 (((uint32_t)uu[2]) << 8) + uu[3];
60 }
61
FromString(const std::string & uuid,bool * is_valid)62 Uuid Uuid::FromString(const std::string& uuid, bool* is_valid) {
63 if (is_valid) *is_valid = false;
64 Uuid ret = kBase;
65
66 if (uuid.empty()) return ret;
67
68 uint8_t* p = ret.uu.data();
69 if (uuid.size() == kString128BitLen) {
70 if (uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' ||
71 uuid[23] != '-') {
72 return ret;
73 }
74
75 int c;
76 int rc =
77 sscanf(uuid.c_str(),
78 "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx"
79 "-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%n",
80 &p[0], &p[1], &p[2], &p[3], &p[4], &p[5], &p[6], &p[7], &p[8],
81 &p[9], &p[10], &p[11], &p[12], &p[13], &p[14], &p[15], &c);
82 if (rc != 16) return ret;
83 if (c != kString128BitLen) return ret;
84
85 if (is_valid) *is_valid = true;
86 } else if (uuid.size() == 8) {
87 int c;
88 int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%02hhx%02hhx%n", &p[0], &p[1],
89 &p[2], &p[3], &c);
90 if (rc != 4) return ret;
91 if (c != 8) return ret;
92
93 if (is_valid) *is_valid = true;
94 } else if (uuid.size() == 4) {
95 int c;
96 int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%n", &p[2], &p[3], &c);
97 if (rc != 2) return ret;
98 if (c != 4) return ret;
99
100 if (is_valid) *is_valid = true;
101 }
102
103 return ret;
104 }
105
From16Bit(uint16_t uuid16)106 Uuid Uuid::From16Bit(uint16_t uuid16) {
107 Uuid u = kBase;
108
109 u.uu[2] = (uint8_t)((0xFF00 & uuid16) >> 8);
110 u.uu[3] = (uint8_t)(0x00FF & uuid16);
111 return u;
112 }
113
From32Bit(uint32_t uuid32)114 Uuid Uuid::From32Bit(uint32_t uuid32) {
115 Uuid u = kBase;
116
117 u.uu[0] = (uint8_t)((0xFF000000 & uuid32) >> 24);
118 u.uu[1] = (uint8_t)((0x00FF0000 & uuid32) >> 16);
119 u.uu[2] = (uint8_t)((0x0000FF00 & uuid32) >> 8);
120 u.uu[3] = (uint8_t)(0x000000FF & uuid32);
121 return u;
122 }
123
From128BitBE(const uint8_t * uuid)124 Uuid Uuid::From128BitBE(const uint8_t* uuid) {
125 UUID128Bit tmp;
126 memcpy(tmp.data(), uuid, kNumBytes128);
127 return From128BitBE(tmp);
128 }
129
From128BitLE(const UUID128Bit & uuid)130 Uuid Uuid::From128BitLE(const UUID128Bit& uuid) {
131 Uuid u;
132 std::reverse_copy(uuid.data(), uuid.data() + kNumBytes128, u.uu.begin());
133 return u;
134 }
135
From128BitLE(const uint8_t * uuid)136 Uuid Uuid::From128BitLE(const uint8_t* uuid) {
137 UUID128Bit tmp;
138 memcpy(tmp.data(), uuid, kNumBytes128);
139 return From128BitLE(tmp);
140 }
141
To128BitLE() const142 const UUID128Bit Uuid::To128BitLE() const {
143 UUID128Bit le;
144 std::reverse_copy(uu.data(), uu.data() + kNumBytes128, le.begin());
145 return le;
146 }
147
To128BitBE() const148 const UUID128Bit& Uuid::To128BitBE() const { return uu; }
149
GetRandom()150 Uuid Uuid::GetRandom() {
151 Uuid uuid;
152 base::RandBytes(uuid.uu.data(), uuid.uu.size());
153 return uuid;
154 }
155
IsEmpty() const156 bool Uuid::IsEmpty() const { return *this == kEmpty; }
157
UpdateUuid(const Uuid & uuid)158 void Uuid::UpdateUuid(const Uuid& uuid) {
159 uu = uuid.uu;
160 }
161
operator <(const Uuid & rhs) const162 bool Uuid::operator<(const Uuid& rhs) const {
163 return std::lexicographical_compare(uu.begin(), uu.end(), rhs.uu.begin(),
164 rhs.uu.end());
165 }
166
operator ==(const Uuid & rhs) const167 bool Uuid::operator==(const Uuid& rhs) const { return uu == rhs.uu; }
168
operator !=(const Uuid & rhs) const169 bool Uuid::operator!=(const Uuid& rhs) const { return uu != rhs.uu; }
170
ToString() const171 std::string Uuid::ToString() const {
172 return base::StringPrintf(
173 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
174 uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], uu[8], uu[9],
175 uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
176 }
177 } // namespace bluetooth
178