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