• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2022 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 "hci/address.h"
20 
21 #include <algorithm>
22 #include <cstdint>
23 #include <cstdio>
24 #include <iomanip>
25 #include <sstream>
26 
27 namespace bluetooth {
28 namespace hci {
29 
30 const Address Address::kAny{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
31 const Address Address::kEmpty{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
32 
33 // Address cannot initialize member variables as it is a POD type
34 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
Address(std::array<uint8_t,kLength> const & address)35 constexpr Address::Address(std::array<uint8_t, kLength> const& address)
36     : address(address) {}
37 
Address(const uint8_t (& address)[kLength])38 Address::Address(const uint8_t (&address)[kLength]) {
39   std::copy(address, address + kLength, this->address.begin());
40 }
41 
Address(std::initializer_list<uint8_t> l)42 Address::Address(std::initializer_list<uint8_t> l) {
43   std::copy(l.begin(), std::min(l.begin() + kLength, l.end()), data());
44 }
45 
ToString() const46 std::string Address::ToString() const {
47   std::stringstream ss;
48   for (auto it = address.rbegin(); it != address.rend(); it++) {
49     ss << std::nouppercase << std::hex << std::setw(2) << std::setfill('0')
50        << +*it;
51     if (std::next(it) != address.rend()) {
52       ss << ':';
53     }
54   }
55   return ss.str();
56 }
57 
FromString(const std::string & from)58 std::optional<Address> Address::FromString(const std::string& from) {
59   if (from.length() != 17) {
60     return std::nullopt;
61   }
62 
63   Address addr{};
64   std::istringstream stream(from);
65   std::string token;
66   int index = 0;
67   while (getline(stream, token, ':')) {
68     if (index >= 6) {
69       return std::nullopt;
70     }
71 
72     if (token.length() != 2) {
73       return std::nullopt;
74     }
75 
76     char* temp = nullptr;
77     addr.address.at(5 - index) = std::strtol(token.c_str(), &temp, 16);
78     if (temp == token.c_str()) {
79       // string token is empty or has wrong format
80       return std::nullopt;
81     }
82     if (temp != (token.c_str() + token.size())) {
83       // cannot parse whole string
84       return std::nullopt;
85     }
86 
87     index++;
88   }
89 
90   if (index != 6) {
91     return std::nullopt;
92   }
93 
94   return addr;
95 }
96 
FromString(const std::string & from,Address & to)97 bool Address::FromString(const std::string& from, Address& to) {
98   auto addr = FromString(from);
99   if (!addr) {
100     to = {};
101     return false;
102   }
103   to = std::move(*addr);
104   return true;
105 }
106 
FromOctets(const uint8_t * from)107 size_t Address::FromOctets(const uint8_t* from) {
108   std::copy(from, from + kLength, data());
109   return kLength;
110 };
111 
IsValidAddress(const std::string & address)112 bool Address::IsValidAddress(const std::string& address) {
113   return Address::FromString(address).has_value();
114 }
115 
116 }  // namespace hci
117 }  // namespace bluetooth
118