This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/sensors/MACAddress.h
kazu 06e0e0a5aa fixed some potential issues with MAC addresses
added corresponding test-cases
switched to newer version of tinyxml due to some issues
adjusted affected code-parts accordingly
for better re-use, moved ceiling-calculation to a new class
some minor fixes
new helper methods
worked on wifi-opt
2017-03-20 11:19:57 +01:00

155 lines
3.6 KiB
C++

#ifndef MACADDRESS_H
#define MACADDRESS_H
#include <cstdint>
#include <string>
#include "../Exception.h"
/**
* describes a MAC-Address as 64-bit integer.
* provides 8-bit access to all 6 values
*/
union MACAddress {
private:
/** fieldwise access */
struct {
uint8_t h5;
uint8_t h4;
uint8_t h3;
uint8_t h2;
uint8_t h1;
uint8_t h0;
} fields;
/** store as 64-bit integer */
uint64_t mac = 0;
public:
/** empty ctor */
MACAddress() {
;
}
/** copy ctor */
MACAddress(const MACAddress& o) : mac(o.mac) {
;
}
/** ctor form long */
MACAddress(const uint64_t mac) : mac(mac) {
;
}
/** ctor form string (e.g. "xx:xx:xx:xx:xx:xx") */
MACAddress(const std::string& str) {
// sanity check
if (str.size() == 17 ){
mac = 0; // all zeros
fields.h5 = hexWordToInt(str[ 0], str[ 1]);
fields.h4 = hexWordToInt(str[ 3], str[ 4]);
fields.h3 = hexWordToInt(str[ 6], str[ 7]);
fields.h2 = hexWordToInt(str[ 9], str[10]);
fields.h1 = hexWordToInt(str[12], str[13]);
fields.h0 = hexWordToInt(str[15], str[16]);
}
else if (str.size() == 12){
mac = 0; // all zeros
fields.h5 = hexWordToInt(str[ 0], str[ 1]);
fields.h4 = hexWordToInt(str[ 2], str[ 3]);
fields.h3 = hexWordToInt(str[ 4], str[ 5]);
fields.h2 = hexWordToInt(str[ 6], str[ 7]);
fields.h1 = hexWordToInt(str[ 8], str[ 9]);
fields.h0 = hexWordToInt(str[10], str[11]);
}
else{
throw Exception("invalid hex string length. must be 17 or 12 (without :)");
}
}
/** convert to lower-case hex-string ("xx:xx:xx:xx:xx:xx") */
std::string asString() const {
std::string str = ":::::::::::::::::";
intToHexStr(fields.h5, &str[ 0]);
intToHexStr(fields.h4, &str[ 3]);
intToHexStr(fields.h3, &str[ 6]);
intToHexStr(fields.h2, &str[ 9]);
intToHexStr(fields.h1, &str[12]);
intToHexStr(fields.h0, &str[15]);
return str;
}
/** get the mac address as a long-int value */
uint64_t asLong() const {
// even if we initialized all 8 bytes with zero
// we mask the 2 unsued bytes to be absolutely safe
return mac & 0x0000FFFFFFFFFFFF;
}
/** equal? */
bool operator == (const MACAddress& o) const {
return o.asLong() == asLong();
}
/** not equal? */
bool operator != (const MACAddress& o) const {
return o.asLong() != asLong();
}
private:
/** convert the given hex char [0-F] to an integer [0-15] */
static uint8_t hexCharToInt(const char hex) {
// convert
if (hex >= '0' && hex <= '9') { // digits
return (hex - '0');
} else if (hex >= 'a' && hex <= 'f') { // lower case
return (hex - 'a' + 10);
} else if (hex >= 'A' && hex <= 'F') { // upper case
return (hex - 'A' + 10);
}
// found an invalid character
throw Exception("invalid character within MAC address");
}
/** convert the given hex-word to an integer */
static uint8_t hexWordToInt(const char hi, const char lo) {
return hexCharToInt(hi) << 4 | hexCharToInt(lo);
}
/** conver the given integer [0-15] to a hex char [0-F] */
static char intToHexChar(const uint8_t val) {
return (val < 10) ? ('0' + val) : ('A' - 10 + val);
}
/** insert two hex chars into the provided string buffer */
static void intToHexStr(const uint8_t val, char* dst) {
dst[0] = intToHexChar((val >> 4) & 0xF);
dst[1] = intToHexChar((val >> 0) & 0xF);
}
};
/** hash-method for MAC-Addresses */
namespace std {
template <> struct hash<MACAddress> {
std::size_t operator() (const MACAddress& mac) const {
return std::hash<uint64_t>()(mac.asLong());
}
};
}
#endif // MACADDRESS_H