• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 #include <cpp-string/string_printf.h>
17 
18 #include <algorithm>
19 #include <array>
20 #include <iostream>
21 #include <type_traits>
22 
23 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
24 
25 namespace bt {
26 
27 template <class InputIt>
ByteContainerToString(InputIt begin,InputIt end)28 std::string ByteContainerToString(InputIt begin, InputIt end) {
29   std::string bytes_string;
30   for (InputIt iter = begin; iter != end; ++iter) {
31     bytes_string += bt_lib_cpp_string::StringPrintf("0x%.2x ", *iter);
32   }
33   return bytes_string;
34 }
35 
36 template <class Container>
ByteContainerToString(const Container & c)37 std::string ByteContainerToString(const Container& c) {
38   return ByteContainerToString(c.begin(), c.end());
39 }
40 
41 template <class InputIt>
PrintByteContainer(InputIt begin,InputIt end)42 void PrintByteContainer(InputIt begin, InputIt end) {
43   std::cout << ByteContainerToString(begin, end);
44 }
45 
46 // Prints the contents of a container as a string.
47 template <class Container>
PrintByteContainer(const Container & c)48 void PrintByteContainer(const Container& c) {
49   PrintByteContainer(c.begin(), c.end());
50 }
51 
52 // Function-template for comparing contents of two iterable byte containers for
53 // equality. If the contents are not equal, this logs a GTEST-style error
54 // message to stdout. Meant to be used from unit tests.
55 template <class InputIt1, class InputIt2>
ContainersEqual(InputIt1 expected_begin,InputIt1 expected_end,InputIt2 actual_begin,InputIt2 actual_end)56 bool ContainersEqual(InputIt1 expected_begin,
57                      InputIt1 expected_end,
58                      InputIt2 actual_begin,
59                      InputIt2 actual_end) {
60   if (std::equal(expected_begin, expected_end, actual_begin, actual_end))
61     return true;
62   std::cout << "Expected: (" << (expected_end - expected_begin) << " bytes) { ";
63   PrintByteContainer(expected_begin, expected_end);
64   std::cout << "}\n   Found: (" << (actual_end - actual_begin) << " bytes) { ";
65   PrintByteContainer(actual_begin, actual_end);
66   std::cout << "}" << std::endl;
67   return false;
68 }
69 
70 template <class Container1, class Container2>
ContainersEqual(const Container1 & expected,const Container2 & actual)71 bool ContainersEqual(const Container1& expected, const Container2& actual) {
72   return ContainersEqual(
73       expected.begin(), expected.end(), actual.begin(), actual.end());
74 }
75 
76 template <class Container1>
ContainersEqual(const Container1 & expected,const uint8_t * actual_bytes,size_t actual_num_bytes)77 bool ContainersEqual(const Container1& expected,
78                      const uint8_t* actual_bytes,
79                      size_t actual_num_bytes) {
80   return ContainersEqual(expected.begin(),
81                          expected.end(),
82                          actual_bytes,
83                          actual_bytes + actual_num_bytes);
84 }
85 
86 // Returns a managed pointer to a heap allocated MutableByteBuffer.
87 template <typename... T>
NewBuffer(T...bytes)88 MutableByteBufferPtr NewBuffer(T... bytes) {
89   return std::make_unique<StaticByteBuffer<sizeof...(T)>>(
90       std::forward<T>(bytes)...);
91 }
92 
93 // Returns the value of |x| as a little-endian array, i.e. the first byte of the
94 // array has the value of the least significant byte of |x|.
95 template <typename T>
ToBytes(T x)96 constexpr std::array<uint8_t, sizeof(T)> ToBytes(T x) {
97   static_assert(std::is_integral_v<T>,
98                 "Must use integral types for safe bytewise access");
99   std::array<uint8_t, sizeof(T)> bytes;
100   for (auto& byte : bytes) {
101     byte = static_cast<uint8_t>(x);
102     x >>= 8;
103   }
104   return bytes;
105 }
106 
107 // Returns the Upper/Lower bits of a uint16_t
UpperBits(const uint16_t x)108 constexpr uint8_t UpperBits(const uint16_t x) { return ToBytes(x).back(); }
LowerBits(const uint16_t x)109 constexpr uint8_t LowerBits(const uint16_t x) { return ToBytes(x).front(); }
110 
111 }  // namespace bt
112