-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LocalAddr, LocalAddrMAC: copy and remove templates
- Loading branch information
Showing
5 changed files
with
301 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/** | ||
* @file local_addr.hpp | ||
* @author Dávid Benko (davidbenko@davidbenko.dev) | ||
* @brief Local layer address container | ||
* | ||
* @copyright Copyright (c) 2024 | ||
* | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <cstdint> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace kvik | ||
{ | ||
/** | ||
* @brief Local layer address container | ||
* | ||
* Internal representation is decisive. Two addresses are the same if they | ||
* have the same internal representation. | ||
* | ||
* This is base for other local address types, like MAC. | ||
*/ | ||
struct LocalAddr | ||
{ | ||
std::vector<uint8_t> addr; //!< Internal address representation | ||
|
||
bool operator==(const LocalAddr &other) const | ||
{ | ||
return addr == other.addr; | ||
} | ||
|
||
bool operator!=(const LocalAddr &other) const | ||
{ | ||
return !this->operator==(other); | ||
} | ||
|
||
/** | ||
* @brief Checks whether the address is empty | ||
* | ||
* @return true Local address is empty | ||
* @return false Local address is not empty | ||
*/ | ||
inline bool empty() const | ||
{ | ||
return addr.empty(); | ||
} | ||
|
||
/** | ||
* @brief Converts internal representation into printable string | ||
* | ||
* This is also used during comunication with remote layer protocols | ||
* (like MQTT). | ||
* | ||
* Most generic approach used by base class is to convert `addr` to | ||
* hexdump. | ||
* | ||
* @return Printable string representation | ||
*/ | ||
std::string toString() const | ||
{ | ||
std::string str; | ||
char buf[3]; | ||
for (const auto ch : addr) | ||
{ | ||
sprintf(buf, "%02x", ch); | ||
str += buf; | ||
} | ||
return str; | ||
} | ||
}; | ||
} | ||
|
||
// Define hasher function | ||
template <> | ||
struct std::hash<kvik::LocalAddr> | ||
{ | ||
std::size_t operator()(kvik::LocalAddr const &addr) const noexcept | ||
{ | ||
// Convert internal representation to string | ||
std::string addrStr(addr.addr.begin(), addr.addr.end()); | ||
|
||
// Hash it | ||
return std::hash<std::string>{}(addrStr); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/** | ||
* @file local_addr_mac.hpp | ||
* @author Dávid Benko (davidbenko@davidbenko.dev) | ||
* @brief Local layer address container for MAC address | ||
* | ||
* @copyright Copyright (c) 2024 | ||
* | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
#include "kvik/local_addr.hpp" | ||
|
||
namespace kvik | ||
{ | ||
/** | ||
* @brief Local layer address container for MAC address | ||
*/ | ||
struct LocalAddrMAC : public LocalAddr | ||
{ | ||
/** | ||
* @brief Constructs a new object | ||
* | ||
* @param mac MAC address (00:00:00:00:00:00 if `nullptr`) | ||
*/ | ||
LocalAddrMAC(const uint8_t *mac = nullptr); | ||
|
||
/** | ||
* @brief Constructs a new object from 00:00:00:00:00:00 MAC address | ||
* | ||
* @return New `LocalAddrMAC` object | ||
*/ | ||
static LocalAddrMAC zeroes(); | ||
|
||
/** | ||
* @brief Constructs a new object from broadcast MAC address | ||
* | ||
* @return New `LocalAddrMAC` object | ||
*/ | ||
static LocalAddrMAC broadcast(); | ||
|
||
/** | ||
* @brief Converts `LocalAddrMAC` to array of bytes | ||
* | ||
* @param mac MAC address storage pointer | ||
*/ | ||
void toMAC(uint8_t *mac) const; | ||
}; | ||
} | ||
|
||
// Define hasher function | ||
template <> | ||
struct std::hash<kvik::LocalAddrMAC> | ||
{ | ||
std::size_t operator()(kvik::LocalAddrMAC const &addr) const noexcept | ||
{ | ||
return std::hash<kvik::LocalAddr>{}(addr); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/** | ||
* @file local_addr_mac.cpp | ||
* @author Dávid Benko (davidbenko@davidbenko.dev) | ||
* @brief Local layer address container for MAC address | ||
* | ||
* @copyright Copyright (c) 2024 | ||
* | ||
*/ | ||
|
||
#include <cstring> | ||
#include <memory> | ||
|
||
#include "kvik/local_addr_mac.hpp" | ||
|
||
namespace kvik | ||
{ | ||
/** | ||
* @brief Length of MAC address in bytes | ||
*/ | ||
static constexpr size_t MAC_LEN = 6; | ||
|
||
LocalAddrMAC::LocalAddrMAC(const uint8_t *mac) | ||
{ | ||
uint8_t macZeroes[MAC_LEN] = {}; | ||
if (mac == nullptr) | ||
{ | ||
mac = macZeroes; | ||
} | ||
|
||
// Internal representation | ||
addr = std::vector<uint8_t>(mac, mac + MAC_LEN); | ||
} | ||
|
||
LocalAddrMAC LocalAddrMAC::zeroes() | ||
{ | ||
return LocalAddrMAC(); | ||
} | ||
|
||
LocalAddrMAC LocalAddrMAC::broadcast() | ||
{ | ||
uint8_t mac[MAC_LEN]; | ||
memset(mac, 0xFF, MAC_LEN); | ||
return LocalAddrMAC(mac); | ||
} | ||
|
||
void LocalAddrMAC::toMAC(uint8_t *mac) const | ||
{ | ||
for (unsigned i = 0; i < addr.size(); i++) | ||
{ | ||
mac[i] = addr[i]; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#include <catch2/catch_test_macros.hpp> | ||
|
||
#include "kvik/local_addr.hpp" | ||
|
||
using namespace kvik; | ||
|
||
TEST_CASE("Empty", "[LocalAddr]") | ||
{ | ||
REQUIRE(LocalAddr().empty()); | ||
} | ||
|
||
TEST_CASE("Non-empty", "[LocalAddr]") | ||
{ | ||
REQUIRE(!LocalAddr({{0x00}}).empty()); | ||
} | ||
|
||
TEST_CASE("Comparison", "[LocalAddr]") | ||
{ | ||
auto addr1 = LocalAddr({{0x00}}); | ||
auto addr2 = LocalAddr({{0x01}}); | ||
auto addr3 = LocalAddr({{0x00}}); | ||
auto addr4 = LocalAddr({{0x00, 0x01}}); | ||
|
||
SECTION("Equality") | ||
{ | ||
REQUIRE(addr1 == addr3); | ||
} | ||
|
||
SECTION("Non-equality") | ||
{ | ||
REQUIRE(addr1 != addr2); | ||
} | ||
|
||
SECTION("Non-equality of with common prefix") | ||
{ | ||
REQUIRE(addr1 != addr4); | ||
} | ||
|
||
SECTION("Non-equality of with common suffix") | ||
{ | ||
REQUIRE(addr2 != addr4); | ||
} | ||
} | ||
|
||
TEST_CASE("String representation", "[LocalAddr]") | ||
{ | ||
REQUIRE(LocalAddr({{0x00, 0x11, 0xAB}}).toString() == "0011ab"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#include <catch2/catch_test_macros.hpp> | ||
|
||
#include "kvik/local_addr_mac.hpp" | ||
|
||
using namespace kvik; | ||
|
||
TEST_CASE("Zeroed MAC is not empty", "[LocalAddrMAC]") | ||
{ | ||
REQUIRE(!LocalAddrMAC().empty()); | ||
} | ||
|
||
TEST_CASE("Comparison", "[LocalAddrMAC]") | ||
{ | ||
uint8_t mac1[] = {0x00, 0x11, 0x23, 0x00, 0x55, 0xFF}; | ||
uint8_t mac2[] = {0x00, 0x11, 0x23, 0x00, 0x55, 0xAA}; | ||
uint8_t mac3[] = {0x00, 0x11, 0x23, 0x00, 0x55, 0xFF}; | ||
uint8_t macZero[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
uint8_t macBroadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | ||
|
||
SECTION("Equality") | ||
{ | ||
REQUIRE(LocalAddrMAC(mac1) == LocalAddrMAC(mac3)); | ||
} | ||
|
||
SECTION("Non-equality") | ||
{ | ||
REQUIRE(LocalAddrMAC(mac1) != LocalAddrMAC(mac2)); | ||
} | ||
|
||
SECTION("Default MAC is zeroed") | ||
{ | ||
REQUIRE(LocalAddrMAC::zeroes() == LocalAddrMAC()); | ||
} | ||
|
||
SECTION("Zeroed MAC equality") | ||
{ | ||
REQUIRE(LocalAddrMAC::zeroes() == LocalAddrMAC(macZero)); | ||
} | ||
|
||
SECTION("Broadcast MAC equality") | ||
{ | ||
REQUIRE(LocalAddrMAC::broadcast() == LocalAddrMAC(macBroadcast)); | ||
} | ||
} | ||
|
||
TEST_CASE("String representation", "[LocalAddrMAC]") | ||
{ | ||
uint8_t mac[] = {0x00, 0x11, 0x23, 0x00, 0x55, 0xFF}; | ||
REQUIRE(LocalAddrMAC(mac).toString() == "0011230055ff"); | ||
} |