diff --git a/.gitignore b/.gitignore index 094c4537..666b134c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ .dirstamp /Doxyfile /install-sh +/ip.cpp /json.cpp /libgim-*.tar.* .libs diff --git a/Makefile.am b/Makefile.am index 32049414..317ce6b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,6 +13,7 @@ UTIL_INCLUDE = \ except.hpp \ float.hpp \ io.hpp \ + ip.hpp \ json.hpp \ maths.hpp \ matrix.hpp \ @@ -30,6 +31,7 @@ UTIL_FILES = \ except.cpp \ float.cpp \ io.cpp \ + ip.cpp \ json.cpp \ maths.cpp \ matrix.cpp \ @@ -40,8 +42,8 @@ UTIL_FILES = \ vector.cpp \ version.cpp -CLEANFILES = json.cpp version.cpp -EXTRA_DIST = json.cpp.rl version.cpp.rl +CLEANFILES = json.cpp version.cpp ip.cpp +EXTRA_DIST = json.cpp.rl version.cpp.rl ip.cpp.rl RAGELFLAGS = -F1 SUFFIXES = .cpp .cpp.rl diff --git a/ip.cpp.rl b/ip.cpp.rl new file mode 100644 index 00000000..b1a8995b --- /dev/null +++ b/ip.cpp.rl @@ -0,0 +1,107 @@ +/* + * This file is part of libgim. + * + * libgim 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 3 of the License, or (at your option) any later + * version. + * + * libgim 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 libgim. If not, see . + * + * Copyright 2011 Danny Robson + */ + + +#include "ip.hpp" + +#include +#include + + +using namespace std; + + +ipv4::ip::ip (uint8_t a, uint8_t b, uint8_t c, uint8_t d): + m_octets ({ a, b, c, d }) +{ ; } + + +ipv4::ip& +ipv4::ip::operator = (const ipv4::ip &rhs) { + m_octets[0] = rhs.m_octets[0]; + m_octets[1] = rhs.m_octets[1]; + m_octets[2] = rhs.m_octets[2]; + m_octets[3] = rhs.m_octets[3]; + + return *this; +} + + +bool +ipv4::ip::operator == (const ipv4::ip &rhs) const { + return m_octets[0] == rhs.m_octets[0] && + m_octets[1] == rhs.m_octets[1] && + m_octets[2] == rhs.m_octets[2] && + m_octets[3] == rhs.m_octets[3]; +} + + +// RFC 3986 +%%{ + machine ipv4; + octet = ( [0-9][0-9]? | + '1'[0-9][0-9] | + '2'[0-4][0-9] | + '25'[0-5]) + > { + octetstart = fpc; + } + % { + octetend = fpc; + __octet = 0; + + for (auto i = octetstart; i < octetend; ++i) + __octet = __octet * 10 + *i - '0'; + }; + + ipv4 := (octet %{ __octets[0] = __octet; } '.' + octet %{ __octets[1] = __octet; } '.' + octet %{ __octets[2] = __octet; } '.' + octet %{ __octets[3] = __octet; }) + > { __success = false; } + % { __success = true; } + $!{ __success = false; }; +}%% + +%%write data; + + +ipv4::ip +ipv4::ip::parse (const string &data) { + bool __success = true; + uint8_t __octets[4]; + const char *octetstart, *octetend; + uint8_t __octet; + + int cs = 0; + const char *p = data.data (), + *pe = p + data.size (), + *eof = pe; + + %%write init; + %%write exec; + + if (!__success) + throw invalid_argument(data); + + return ipv4::ip(__octets[0], + __octets[1], + __octets[2], + __octets[3]); +} diff --git a/ip.hpp b/ip.hpp new file mode 100644 index 00000000..4829a5eb --- /dev/null +++ b/ip.hpp @@ -0,0 +1,44 @@ +/* + * This file is part of libgim. + * + * libgim 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 3 of the License, or (at your option) any later + * version. + * + * libgim 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 libgim. If not, see . + * + * Copyright 2011 Danny Robson + */ + +#ifndef __UTIL_IP_HPP +#define __UTIL_IP_HPP + +#include +#include + + +namespace ipv4 { + struct ip { + uint8_t m_octets[4]; + + ip (uint8_t a, uint8_t b, uint8_t c, uint8_t d); + + ip& operator = (const ip &); + bool operator == (const ip &) const; + + static ip parse (const std::string &); + }; + + + typedef uint16_t port_t; +} + + +#endif // __UTIL_IP_HPP diff --git a/test/.gitignore b/test/.gitignore index 5bb89202..5a6e99aa 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,7 +1,8 @@ /backtrace /float -/range +/ip +/json-check /maths /matrix +/range /version -/json-check diff --git a/test/Makefile.am b/test/Makefile.am index 02ffb6e8..f641d486 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -7,7 +7,7 @@ AM_CPPFLAGS = \ AM_LDFLAGS = $(COMMON_LDFLAGS) -TEST_BIN = backtrace float range maths matrix version +TEST_BIN = backtrace float range maths matrix version ip TESTS = $(TEST_BIN) json.pl check_PROGRAMS = $(TEST_BIN) json-check EXTRA_DIST = json.pl @@ -31,5 +31,8 @@ matrix_LDADD = $(builddir)/../libutil.la $(BOOST_SYSTEM_LIB) version_SOURCES = version.cpp version_LDADD = $(builddir)/../libutil.la $(BOOST_SYSTEM_LIB) +ip_SOURCES = ip.cpp +ip_LDADD = $(builddir)/../libutil.la $(BOOST_SYSTEM_LIB) + json_check_SOURCES = json-check.cpp json_check_LDADD = $(builddir)/../libutil.la $(BOOST_FILESYSTEM_LIB) diff --git a/test/ip.cpp b/test/ip.cpp new file mode 100644 index 00000000..78eab909 --- /dev/null +++ b/test/ip.cpp @@ -0,0 +1,28 @@ + +#include "../ip.hpp" + +#include "../debug.hpp" +#include "../types.hpp" + +#include + + +using namespace std; + + +int +main (int argc, char **argv) { + struct ip_test { + const char *str; + const ipv4::ip ip; + } data [] = { + { "0.0.0.0", { 0, 0, 0, 0 } }, + { "255.255.255.255", { 255, 255, 255, 255 } }, + { "127.0.0.1", { 127, 0, 0, 1 } } + }; + + for (unsigned int i = 0; i < elems (data); ++i) + check_hard (ipv4::ip::parse (data[i].str) == data[i].ip); + + return EXIT_SUCCESS; +}