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