/*
 * (sub-optimal) Platform independent encapsulation of network types and
 * addresses
 *
 *
 * Copyright (C) 2003  Enrico Zini <enrico@debian.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "nettypes.h"
#include <iomanip>
#include <sstream>

using namespace std;

/* Format an IPv4 address in a static char buffer */
string fmt(const IPAddress& addr) throw ()
{
	stringstream buf;
	for (int i = 0; i < 4; i++)
	{
		if (i > 0)
			buf << '.';
		buf << (int)(((const unsigned char*)(const in_addr*)addr)[i]);
	}
	return buf.str();
}

/* Format a MAC address in a static char buffer */
string fmt(const struct ether_addr& addr) throw ()
{
	stringstream buf;
	for (int i = 0; i < 6; i++)
	{
		if (i > 0)
			buf << ':';
		buf << hex << setfill('0') << setw(2) << (int)(((const unsigned char*)&addr)[i]);
	}
	return buf.str();
}

IPAddress::IPAddress(const std::string& str) throw (wibble::exception::Consistency)
{
	if (inet_aton(str.c_str(), &addr) == 0)
		// Not valid
		throw wibble::exception::Consistency("parsing IP address \"" + str + "\"", "not a valid IP address");
}

bool IPAddress::operator==(const IPAddress& ip) const
{
	return IPv4_MATCHES(&this->addr, &ip.addr);
}

bool IPAddress::operator!=(const IPAddress& ip) const
{
	return !IPv4_MATCHES(&this->addr, &ip.addr);
}


/* Parse a MAC address from its canonical string representation */
bool parse_mac(struct ether_addr* target, const string& str) throw ()
{
	unsigned int a, b, c, d, e, f;
	if (sscanf(str.c_str(), "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f) == 6)
	{
		((unsigned char*)target)[0] = a;
		((unsigned char*)target)[1] = b;
		((unsigned char*)target)[2] = c;
		((unsigned char*)target)[3] = d;
		((unsigned char*)target)[4] = e;
		((unsigned char*)target)[5] = f;
		return true;
	} else
		return false;
}


#ifdef COMPILE_TESTSUITE

#include <tests/test-utils.h>

namespace tut {
using namespace tut_guessnet;

struct guessnet_nettypes_shar {
};
TESTGRP(guessnet_nettypes);

template<> template<>
void to::test<1>()
{
	IPAddress zero("0.0.0.0");
	IPAddress host("1.2.3.4");

	gen_ensure(zero == IPAddress("0.0.0.0"));
	gen_ensure(zero != IPAddress("1.2.3.4"));
	//ensure_equals(zero, IPAddress("0.0.0.0"));
	gen_ensure(host == IPAddress("1.2.3.4"));
	gen_ensure(host != IPAddress("0.0.0.0"));
	//ensure_equals(host, IPAddress("1.2.3.4"));

	gen_ensure(zero == zero);
	gen_ensure(host == host);
	gen_ensure(zero != host);

	gen_ensure(fmt(zero) == "0.0.0.0");
	gen_ensure(fmt(host) == "1.2.3.4");
}

}

#endif

// vim:set ts=4 sw=4:
