File:  [Isaki's NoNo m68k/m88k emulator] / nono / lib / macaddr.h
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:57 2026 UTC (3 months ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2021 nono project
// Licensed under nono-license.txt
//

//
// MAC アドレス
//

#pragma once

#include "header.h"

// MAC アドレス格納用のクラス
class MacAddr
{
	// addr.b[] をアクセスするためのヘルパー。
	static inline std::size_t IDX(std::size_t n)
	{
#if BYTE_ORDER == LITTLE_ENDIAN
		return n;
#else
		return 7 - n;
#endif
	}

 public:
	// コンストラクタ
	MacAddr()
	{
	}

	// コンストラクタ
	explicit MacAddr(uint64 addr_)
	{
		addr.q = addr_;
	}

	// コンストラクタ
	explicit MacAddr(const uint8 *src)
		: MacAddr(src[0], src[1], src[2], src[3], src[4], src[5])
	{
	}

	// コンストラクタ
	MacAddr(uint s0, uint s1, uint s2, uint s3, uint s4, uint s5)
	{
		addr.q = ((uint64)s0 <<  0)
		       | ((uint64)s1 <<  8)
		       | ((uint64)s2 << 16)
		       | ((uint64)s3 << 24)
		       | ((uint64)s4 << 32)
		       | ((uint64)s5 << 40);
	}

	// コピーコンストラクタ
	MacAddr(const MacAddr& src)
	{
		addr.q = src.addr.q;
	}

	// コピー代入演算子
	MacAddr& operator=(const MacAddr& src)
	{
		addr.q = src.addr.q;
		return *this;
	}

	// [] 演算子
	const uint8& operator[](std::size_t n) const
	{
		return addr.b[IDX(n)];
	}

	// [] 演算子
	uint8& operator[](std::size_t n)
	{
		return addr.b[IDX(n)];
	}

	// MAC アドレスのバイト数を返す。
	std::size_t size() const noexcept { return 6; }

	// この MAC アドレスが 00:00:00:00:00:00 なら true
	bool Empty() const noexcept { return (addr.q == 0); }

	// MAC アドレスを適当に生成する。
	void Generate();

	// 文字列から MAC アドレスを作成する。"HH:HH:HH:HH:HH:HH" 形式のみ。
	// 成功すれば true を返す。
	bool FromString(const std::string& src);

	// この MAC アドレスを dst に書き出す。
	void ExportTo(uint8 *dst) const
	{
		for (std::size_t i = 0; i < size(); i++) {
			dst[i] = (*this)[i];
		}
	}

	// このアドレスがユニキャストアドレスなら true を返す。
	bool IsUnicast() const noexcept
	{
		return ((addr.q & 0x01ULL) == 0);
	}

	// このアドレスがブロードキャストアドレスなら true を返す。
	bool IsBroadcast() const noexcept
	{
		return (addr.q == 0x0000'ffff'ffff'ffffULL);
	}

	// 区切り文字なしの文字列形式を返す。主に ROM 埋め込み用で英字は大文字。
	// 01:23:AB なら "0123AB" のような感じ。
	std::string ToString() const;

	// sep を区切り文字とする文字列形式を返す。主に表示用で英字は小文字。
	// 01:23:AB で sep = ":" なら "01:23:ab" のような感じ。
	std::string ToString(char sep) const;

	// 内部の 64 ビット数をそのまま取得する。operator==() で必要なのと
	// パフォーマンスのため EthernetDevice::CRC32() から使っている。
	uint64 Get() const noexcept { return addr.q; }

 private:
	// AA:BB:CC:DD:EE:FF を .q = 0x0000FFEEDDCCBBAA として格納する。
	// .b[] はエンディアンの影響を受けるので直接アクセスしないこと。
	// 代わりに (*this)[] 演算子を使う。
	union {
		uint64 q {};
		uint8 b[8];
	} addr;
};

inline bool operator==(const MacAddr& lhs, const MacAddr& rhs)
{
	return (lhs.Get() == rhs.Get());
}

inline bool operator!=(const MacAddr& lhs, const MacAddr& rhs)
{
	return !(lhs == rhs);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.