177 lines
4.1 KiB
C++
177 lines
4.1 KiB
C++
/*
|
||
* © Copyright 2014 – Urheberrechtshinweis
|
||
* Alle Rechte vorbehalten / All Rights Reserved
|
||
*
|
||
* Programmcode ist urheberrechtlich geschuetzt.
|
||
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
|
||
* Keine Verwendung ohne explizite Genehmigung.
|
||
* (vgl. § 106 ff UrhG / § 97 UrhG)
|
||
*/
|
||
|
||
#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 :)");
|
||
}
|
||
|
||
}
|
||
|
||
uint8_t getField(const int idx) const {
|
||
switch(idx) {
|
||
case 0: return fields.h0;
|
||
case 1: return fields.h1;
|
||
case 2: return fields.h2;
|
||
case 3: return fields.h3;
|
||
case 4: return fields.h4;
|
||
case 5: return fields.h5;
|
||
}
|
||
throw Exception("field-idx out of bounds");
|
||
}
|
||
|
||
/** 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
|