Skip to content

Rewrite IPAddress without union #225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Rewrite IPAddress from std::array to C-style array.
  • Loading branch information
safocl committed Nov 28, 2023
commit d85523f1cb389210432f1e279528cf22a7d916c8
19 changes: 9 additions & 10 deletions api/IPAddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@

#include "IPAddress.h"
#include "Print.h"
#include <algorithm>
#include <cstdint>

using namespace arduino;

Expand Down Expand Up @@ -58,9 +56,9 @@ IPAddress::IPAddress(const uint8_t *address) : IPAddress(IPv4, address) {}
IPAddress::IPAddress(IPType ip_type, const uint8_t *address) : _type(ip_type)
{
if (ip_type == IPv4) {
std::copy(address, address + 4, &_address[IPADDRESS_V4_BYTES_INDEX]);
memcpy(&_address[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t));
} else {
std::copy(address, address + _address.size(), _address.begin());
memcpy(_address, address, sizeof(_address));
}
}

Expand Down Expand Up @@ -110,7 +108,7 @@ bool IPAddress::fromString4(const char *address)
int16_t acc = -1; // Accumulator
uint8_t dots = 0;

_address.fill(0);
memset(_address, 0, sizeof(_address));
while (*address)
{
char c = *address++;
Expand Down Expand Up @@ -228,8 +226,8 @@ IPAddress& IPAddress::operator=(const uint8_t *address)
// IPv4 only conversion from byte pointer
_type = IPv4;

_address.fill(0);
std::copy(address, address + 4, &_address[IPADDRESS_V4_BYTES_INDEX]);
memset(_address, 0, sizeof(_address));
memcpy(&_address[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t));

return *this;
}
Expand All @@ -245,21 +243,22 @@ IPAddress& IPAddress::operator=(uint32_t address)
// IPv4 conversion
// See note on conversion/comparison and uint32_t
_type = IPv4;
_address.fill(0);
memset(_address, 0, sizeof(_address));
uint32_t& addressRef = reinterpret_cast<uint32_t&>(_address[IPADDRESS_V4_BYTES_INDEX]);
addressRef = address;
return *this;
}

bool IPAddress::operator==(const IPAddress& addr) const {
return addr._type == _type && std::equal(addr._address.begin(), addr._address.end(), _address.begin());
return (addr._type == _type)
&& (memcmp(addr._address, _address, sizeof(_address)) == 0);
}

bool IPAddress::operator==(const uint8_t* addr) const
{
// IPv4 only comparison to byte pointer
// Can't support IPv6 as we know our type, but not the length of the pointer
return _type == IPv4 && std::equal(_address.begin() + IPADDRESS_V4_BYTES_INDEX, _address.end(), addr);
return _type == IPv4 && memcmp(addr, &_address[IPADDRESS_V4_BYTES_INDEX], sizeof(uint32_t)) == 0;
}

uint8_t IPAddress::operator[](int index) const {
Expand Down
5 changes: 2 additions & 3 deletions api/IPAddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

#pragma once

#include <array>
#include <stdint.h>
#include "Printable.h"
#include "String.h"
Expand All @@ -42,14 +41,14 @@ enum IPType {

class IPAddress : public Printable {
private:
alignas(alignof(uint32_t)) std::array<uint8_t, 16> _address{};
alignas(alignof(uint32_t)) uint8_t _address[16]{};
IPType _type{IPv4};

// Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not
// stored.
uint8_t* raw_address() { return _type == IPv4 ? &_address[IPADDRESS_V4_BYTES_INDEX] : _address.data(); }
uint8_t* raw_address() { return _type == IPv4 ? &_address[IPADDRESS_V4_BYTES_INDEX] : _address; }

public:
// Constructors
Expand Down