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