- code cleanup

Thu, 11 Dec 2014 05:58:55 +0200

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Thu, 11 Dec 2014 05:58:55 +0200
changeset 5
146825d63b9a
parent 4
ec5387e121fa
child 6
c709bb1a08e4

- code cleanup
- added network-related classes (bytestream, ipaddress, udp socket)

CMakeLists.txt file | annotate | diff | comparison | revisions
sources/basics.h file | annotate | diff | comparison | revisions
sources/filesystem.cpp file | annotate | diff | comparison | revisions
sources/filesystem.h file | annotate | diff | comparison | revisions
sources/format.cpp file | annotate | diff | comparison | revisions
sources/format.h file | annotate | diff | comparison | revisions
sources/list.h file | annotate | diff | comparison | revisions
sources/main.cpp file | annotate | diff | comparison | revisions
sources/main.h file | annotate | diff | comparison | revisions
sources/mystring.cpp file | annotate | diff | comparison | revisions
sources/mystring.h file | annotate | diff | comparison | revisions
sources/network/bytestream.cpp file | annotate | diff | comparison | revisions
sources/network/bytestream.h file | annotate | diff | comparison | revisions
sources/network/ipaddress.cpp file | annotate | diff | comparison | revisions
sources/network/ipaddress.h file | annotate | diff | comparison | revisions
sources/network/udp.cpp file | annotate | diff | comparison | revisions
sources/network/udp.h file | annotate | diff | comparison | revisions
sources/range.h file | annotate | diff | comparison | revisions
sources/version.cpp file | annotate | diff | comparison | revisions
sources/version.h file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Wed Dec 10 19:26:13 2014 +0200
+++ b/CMakeLists.txt	Thu Dec 11 05:58:55 2014 +0200
@@ -7,6 +7,9 @@
 	sources/main.cpp
 	sources/mystring.cpp
 	sources/version.cpp
+	sources/network/bytestream.cpp
+	sources/network/ipaddress.cpp
+	sources/network/udp.cpp
 )
 
 set (CURSES_NEED_NCURSES, True)
--- a/sources/basics.h	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/basics.h	Thu Dec 11 05:58:55 2014 +0200
@@ -33,11 +33,14 @@
 #include <functional>
 
 #define FUNCTION auto
+#define STATIC
 #define METHOD auto
 #define MACRO_TO_STRING_2(A) #A
 #define MACRO_TO_STRING(A) MACRO_TO_STRING_2(A)
 
 using std::swap;
+using std::min;
+using std::max;
 
 enum Color
 {
--- a/sources/filesystem.cpp	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/filesystem.cpp	Thu Dec 11 05:58:55 2014 +0200
@@ -37,7 +37,7 @@
 #endif
 
 // -------------------------------------------------------------------------------------------------
-
+//
 FUNCTION
 dirname (String const& path) -> String
 {
@@ -55,7 +55,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 FUNCTION
 basename (String const& path) -> String
 {
--- a/sources/filesystem.h	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/filesystem.h	Thu Dec 11 05:58:55 2014 +0200
@@ -31,5 +31,9 @@
 #pragma once
 #include "main.h"
 
+// -------------------------------------------------------------------------------------------------
+// A variant of basename() which operates with Strings
 FUNCTION basename (String const& path) -> String;
+
+// A variant of dirname() which operates with Strings
 FUNCTION dirname (String const& path) -> String;
--- a/sources/format.cpp	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/format.cpp	Thu Dec 11 05:58:55 2014 +0200
@@ -31,7 +31,7 @@
 #include <cstdio>
 #include "format.h"
 
-//
+// -------------------------------------------------------------------------------------------------
 // Throws an error while formatting the string
 //
 static auto format_error (String fmtstr, const String errdescribe, int pos) -> void
@@ -44,14 +44,11 @@
 		errmsg += "-";
 
 	errmsg += "^\n" + errdescribe;
-	// throw std::logic_error (errmsg.stdString());
-	std::fprintf (stderr, "%s", errmsg.chars());
-	std::exit (EXIT_FAILURE);
+	throw std::logic_error (errmsg.std_string());
 }
 
-//
-// Main formatter algorithm autoion. Processes @fmtstr with @args and returns
-// the result.
+// -------------------------------------------------------------------------------------------------
+// Main formatter algorithm.
 //
 auto format_args (const String& fmtstr, const Vector<String>& args) -> String
 {
--- a/sources/format.h	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/format.h	Thu Dec 11 05:58:55 2014 +0200
@@ -105,29 +105,24 @@
 	return result;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 // Formats the given string with the given args.
 //
-auto format_args (const String& fmtstr, const Vector<String>& args) -> String;
+FUNCTION format_args (const String& fmtstr, const Vector<String>& args) -> String;
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 // Expands the given arguments into a vector of strings.
 //
-template<typename T, typename... RestTypes>
-auto expand_format_arguments (Vector<String>& data, const T& arg, const RestTypes& ... rest) -> void
+template<typename T, typename... RestTypes> FUNCTION
+expand_format_arguments (Vector<String>& data, const T& arg, const RestTypes& ... rest) -> void
 {
 	data.append (make_format_argument (arg).text());
 	expand_format_arguments (data, rest...);
 }
 
-static void expand_format_arguments (Vector<String>&) __attribute__( (unused));
+static void expand_format_arguments (Vector<String>&) __attribute__((unused));
 static void expand_format_arguments (Vector<String>&) {}
 
-//
 // -------------------------------------------------------------------------------------------------
 //
 // Formats the given formatter string and args and returns the string.
@@ -153,40 +148,37 @@
 //      argument did not expand into a number in the first place, 0 is used
 //      and 0x0 is printed.
 //
-template<typename... argtypes>
-String format (const String& fmtstr, const argtypes&... raw_args)
+template<typename... argtypes> FUNCTION
+format (const String& fmtstr, const argtypes&... raw_args) -> String
 {
 	Vector<String> args;
 	expand_format_arguments (args, raw_args...);
 	return format_args (fmtstr, args);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 // This is an overload of format() where no arguments are supplied.
 // It returns the formatter string as-is.
 //
 static String format (const String& fmtstr) __attribute__ ((unused));
-static String format (const String& fmtstr)
+static String // FUNCTION
+format (const String& fmtstr) // -> String
 {
 	return fmtstr;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
+// Prints the formatting result to the given file handle
 //
-
-template<typename... Args>
-void print_to (FILE* fp, const String& fmtstr, Args const& ...args)
+template<typename... Args> FUNCTION
+print_to (FILE* fp, const String& fmtstr, Args const& ...args) -> void
 {
 	std::fprintf (fp, "%s", format (fmtstr, args...).chars());
 }
 
+// -------------------------------------------------------------------------------------------------
+// Appends the formatting result to the given filename, if opening it succeeds
 //
-// -------------------------------------------------------------------------------------------------
-//
-
 template<typename... argtypes>
 void print_to (const String& filename, const String& fmtstr, const argtypes&... args)
 {
@@ -199,18 +191,11 @@
 	}
 }
 
+// -------------------------------------------------------------------------------------------------
+// Prints the formatting result to stdout
 //
-// -------------------------------------------------------------------------------------------------
-//
-
 template<typename... argtypes>
 void print (const String& fmtstr, const argtypes&... args)
 {
 	print_to (stdout, fmtstr, args...);
 }
-
-#define PRINT_TO_LOG(...) \
-{ \
-	print_to (LOGFILE, "%1:%2: ", __PRETTY_FUNCTION__, __LINE__); \
-	print_to (LOGFILE, __VA_ARGS__); \
-}
--- a/sources/list.h	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/list.h	Thu Dec 11 05:58:55 2014 +0200
@@ -37,10 +37,8 @@
 #include <cassert>
 #include "range.h"
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 class Container
 {
@@ -141,114 +139,90 @@
 template<typename T, typename C>
 Container<T, C>::Container() {}
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 Container<T, C>::Container (const C& other) :
 	m_container (other) {}
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 Container<T, C>::Container (std::initializer_list<T> && a) :
 	m_container (a) {}
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 Container<T, C>::Container (int numvalues) :
 	m_container (numvalues) {}
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::begin() -> Iterator
 {
 	return m_container.begin();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::begin() const -> ConstIterator
 {
 	return m_container.cbegin();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::end() -> Iterator
 {
 	return m_container.end();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::end() const -> ConstIterator
 {
 	return m_container.cend();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::rbegin() -> ReverseIterator
 {
 	return m_container.rbegin();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::crbegin() const -> ConstReverseIterator
 {
 	return m_container.crbegin();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::rend() -> ReverseIterator
 {
 	return m_container.rend();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::crend() const -> ConstReverseIterator
 {
 	return m_container.crend();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::remove_at (int pos) -> void
 {
@@ -256,10 +230,8 @@
 	m_container.erase (m_container.begin() + pos);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::prepend (const T& value) -> T&
 {
@@ -267,10 +239,8 @@
 	return m_container[0];
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::append (const T& value) -> T&
 {
@@ -278,10 +248,8 @@
 	return m_container[m_container.size() - 1];
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::merge (const Self& other) -> void
 {
@@ -290,10 +258,8 @@
 	std::copy (other.begin(), other.end(), begin() + oldsize);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::pop (T& val) -> bool
 {
@@ -305,10 +271,8 @@
 	return true;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::operator<< (const T& value) -> Self&
 {
@@ -316,10 +280,8 @@
 	return *this;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::operator<< (const Self& vals) -> Self&
 {
@@ -327,10 +289,8 @@
 	return *this;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::reverse() const -> Self
 {
@@ -339,30 +299,24 @@
 	return rev;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::clear() -> void
 {
 	m_container.clear();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::insert (int pos, const T& value) -> void
 {
 	m_container.insert (m_container.begin() + pos, value);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::remove_duplicates() -> void
 {
@@ -370,20 +324,16 @@
 	resize (std::distance (begin(), std::unique (begin(), end())));
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::size() const -> int
 {
 	return m_container.size();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::operator[] (int n) -> T&
 {
@@ -391,10 +341,8 @@
 	return m_container[n];
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::operator[] (int n) const -> const T&
 {
@@ -402,40 +350,32 @@
 	return m_container[n];
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::operator[] (const Range<int>& n) const -> Self
 {
 	return splice (n);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::resize (int size) -> void
 {
 	m_container.resize (size);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::sort() -> void
 {
 	std::sort (begin(), end());
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::find (const T& needle) -> Iterator
 {
@@ -447,10 +387,8 @@
 	return it;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::find (const T& needle) const -> ConstIterator
 {
@@ -462,10 +400,8 @@
 	return it;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::find (Function<bool (T const&)> func) -> Iterator
 {
@@ -478,10 +414,8 @@
 	return end();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::find (Function<bool (T const&)> func) const -> ConstIterator
 {
@@ -494,10 +428,8 @@
 	return end();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::remove_one (const T& a) -> void
 {
@@ -507,20 +439,16 @@
 		m_container.erase (it);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::is_empty() const -> bool
 {
 	return size() == 0;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::splice (int a, int b) const -> Self
 {
@@ -535,60 +463,48 @@
 	return result;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::splice (const Range<int>& a) const -> Self
 {
 	return splice (a.min(), a.max());
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::container() const -> const C&
 {
 	return m_container;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::first() const -> const T&
 {
 	return *m_container.cbegin();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::last() const -> const T&
 {
 	return *(m_container.cend() - 1);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::contains (const T& a) const -> bool
 {
 	return std::find (m_container.cbegin(), m_container.cend(), a) != m_container.end();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto Container<T, C>::operator+ (const Self& other) const -> Self
 {
@@ -597,10 +513,8 @@
 	return out;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T, typename C>
 auto operator>> (const T& value, Container<T, C>& haystack) -> Container<T, C>&
 {
--- a/sources/main.cpp	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/main.cpp	Thu Dec 11 05:58:55 2014 +0200
@@ -29,7 +29,10 @@
 */
 
 #include "main.h"
+#include "network/bytestream.h"
 
+// -------------------------------------------------------------------------------------------------
+//
 FUNCTION
 main (int argc, char* argv[]) -> int
 {
--- a/sources/main.h	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/main.h	Thu Dec 11 05:58:55 2014 +0200
@@ -19,7 +19,7 @@
 	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 	TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 	PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
-	OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE=CIAL,
 	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--- a/sources/mystring.cpp	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/mystring.cpp	Thu Dec 11 05:58:55 2014 +0200
@@ -34,7 +34,7 @@
 #include "format.h"
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::compare (const String& other) const -> int
 {
@@ -42,7 +42,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::trim (int n) -> void
 {
@@ -53,7 +53,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::strip (const List<char>& unwanted) -> String
 {
@@ -69,7 +69,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::to_uppercase() const -> String
 {
@@ -85,7 +85,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::to_lowercase() const -> String
 {
@@ -101,7 +101,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::split (char del) const -> StringList
 {
@@ -111,7 +111,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::split (const String& del) const -> StringList
 {
@@ -138,7 +138,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::replace (const char* a, const char* b) -> void
 {
@@ -149,7 +149,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::count (char needle) const -> int
 {
@@ -163,7 +163,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::mid (long a, long b) const -> String
 {
@@ -188,7 +188,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::word_position (int n) const -> int
 {
@@ -196,10 +196,7 @@
 
 	for (int i = 0; i < length(); ++i)
 	{
-		if (m_string[i] != ' ')
-			continue;
-
-		if (++count < n)
+		if (not isspace (m_string[i]) or ++count < n)
 			continue;
 
 		return i;
@@ -209,7 +206,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::find (const char* c, int a) const -> int
 {
@@ -222,7 +219,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::find_last (const char* c, int a) const -> int
 {
@@ -237,7 +234,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::to_int (bool* ok, int base) const -> long
 {
@@ -252,7 +249,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::to_float (bool* ok) const -> float
 {
@@ -267,7 +264,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::to_double (bool* ok) const -> double
 {
@@ -282,7 +279,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::operator+ (const String& data) const -> String
 {
@@ -292,7 +289,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::operator+ (const char* data) const -> String
 {
@@ -302,7 +299,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::is_numeric() const -> bool
 {
@@ -333,7 +330,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::ends_with (const String& other) -> bool
 {
@@ -345,7 +342,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::starts_with (const String& other) -> bool
 {
@@ -356,7 +353,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::sprintf (const char* fmtstr, ...) -> void
 {
@@ -375,7 +372,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 StringList::join (const String& delim) -> String
 {
@@ -393,7 +390,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::mask_against (const String& pattern) const -> bool
 {
@@ -442,7 +439,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::from_number (int a) -> String
 {
@@ -452,7 +449,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::from_number (long a) -> String
 {
@@ -462,7 +459,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::from_number (unsigned long a) -> String
 {
@@ -472,7 +469,7 @@
 }
 
 // -------------------------------------------------------------------------------------------------
-
+//
 METHOD
 String::from_number (double a) -> String
 {
--- a/sources/mystring.h	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/mystring.h	Thu Dec 11 05:58:55 2014 +0200
@@ -38,6 +38,8 @@
 class String;
 class StringList;
 
+// -------------------------------------------------------------------------------------------------
+
 class String
 {
 public:
@@ -125,6 +127,8 @@
 	std::string m_string;
 };
 
+// -------------------------------------------------------------------------------------------------
+
 class StringList : public List<String>
 {
 public:
@@ -135,14 +139,12 @@
 	METHOD join (const String& delim) -> String;
 };
 
+// -------------------------------------------------------------------------------------------------
+
 inline FUNCTION operator== (const char* a, const String& b) -> bool;
 inline FUNCTION operator+ (const char* a, const String& b) -> String;
 
-//
 // -------------------------------------------------------------------------------------------------
-//
-// IMPLEMENTATIONS
-//
 
 inline METHOD
 String::is_empty() const -> bool
@@ -150,9 +152,7 @@
 	return m_string[0] == '\0';
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::append (const char* data) -> void
@@ -160,9 +160,7 @@
 	m_string.append (data);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::append (char data) -> void
@@ -170,9 +168,7 @@
 	m_string.push_back (data);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::append (const String& data) -> void
@@ -180,9 +176,7 @@
 	m_string.append (data.chars());
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::begin() -> std::string::iterator
@@ -190,9 +184,7 @@
 	return m_string.begin();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::begin() const -> std::string::const_iterator
@@ -200,18 +192,14 @@
 	return m_string.cbegin();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline const char* String::chars() const
 {
 	return m_string.c_str();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::end() -> std::string::iterator
@@ -219,9 +207,7 @@
 	return m_string.end();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::end() const -> std::string::const_iterator
@@ -229,9 +215,7 @@
 	return m_string.end();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::clear() -> void
@@ -239,9 +223,7 @@
 	m_string.clear();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::remove (int pos) -> void
@@ -249,9 +231,7 @@
 	m_string.erase (m_string.begin() + pos);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::insert (int pos, char c) -> void
@@ -259,9 +239,7 @@
 	m_string.insert (m_string.begin() + pos, c);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::length() const -> int
@@ -269,9 +247,7 @@
 	return m_string.length();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::remove (int pos, int len) -> void
@@ -279,9 +255,7 @@
 	m_string.replace (pos, len, "");
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::remove_from_start (int len) -> void
@@ -289,9 +263,7 @@
 	remove (0, len);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::remove_from_end (int len) -> void
@@ -299,9 +271,7 @@
 	remove (length() - len, len);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::replace (int pos, int n, const String& a) -> void
@@ -309,9 +279,7 @@
 	m_string.replace (pos, n, a.chars());
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::shrink_to_fit() -> void
@@ -319,18 +287,14 @@
 	m_string.shrink_to_fit();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline const std::string& String::std_string() const
 {
 	return m_string;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::strip (char unwanted) -> String
@@ -338,9 +302,7 @@
 	return strip ({unwanted});
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator+ (int num) const -> String
@@ -348,9 +310,7 @@
 	return *this + String::from_number (num);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator+= (const String& data) -> String&
@@ -359,9 +319,7 @@
 	return *this;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator+= (const char* data) -> String&
@@ -370,9 +328,7 @@
 	return *this;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator+= (int num) -> String&
@@ -380,9 +336,7 @@
 	return operator+= (String::from_number (num));
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::prepend (String a) -> void
@@ -390,9 +344,7 @@
 	m_string = (a + m_string).std_string();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator+= (char data) -> String&
@@ -401,9 +353,7 @@
 	return *this;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator== (const String& other) const -> bool
@@ -411,9 +361,7 @@
 	return std_string() == other.std_string();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator== (const char* other) const -> bool
@@ -421,9 +369,7 @@
 	return operator== (String (other));
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator!= (const String& other) const -> bool
@@ -431,9 +377,7 @@
 	return std_string() != other.std_string();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator!= (const char* other) const -> bool
@@ -441,9 +385,7 @@
 	return operator!= (String (other));
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator> (const String& other) const -> bool
@@ -451,9 +393,7 @@
 	return std_string() > other.std_string();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::operator< (const String& other) const -> bool
@@ -461,27 +401,21 @@
 	return std_string() < other.std_string();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline String::operator const char*() const
 {
 	return chars();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline String::operator const std::string&() const
 {
 	return std_string();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::modify_index (int& a) -> void
@@ -490,9 +424,7 @@
 		a = length() - a;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline METHOD
 String::index_difference (int a, int b) -> int
@@ -502,9 +434,7 @@
 	return b - a;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline FUNCTION
 operator== (const char* a, const String& b) -> bool
@@ -512,9 +442,7 @@
 	return b == a;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
-//
 
 inline FUNCTION
 operator+ (const char* a, const String& b) -> String
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/network/bytestream.cpp	Thu Dec 11 05:58:55 2014 +0200
@@ -0,0 +1,266 @@
+#include "bytestream.h"
+#include <string.h>
+
+bool Bytestream::sink;
+
+// -------------------------------------------------------------------------------------------------
+//
+Bytestream::Bytestream (unsigned long length) :
+	m_data (nullptr)
+{
+	resize (length);
+	clear();
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+Bytestream::Bytestream (const unsigned char* data, unsigned long length) :
+	m_data (nullptr)
+{
+	m_data = nullptr;
+	init (data, length);
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+Bytestream::Bytestream (const Vector<unsigned char>& bytes) :
+	m_data (nullptr)
+{
+	init (bytes.data(), bytes.size());
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+Bytestream::~Bytestream()
+{
+	delete m_data;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::resize (unsigned long newsize)
+{
+	Vector<unsigned char> olddata;
+	unsigned long oldsize = 0L;
+
+	if (m_data != nullptr)
+	{
+		oldsize = allocated_size();
+		olddata.resize (oldsize);
+		memcpy (olddata.data(), m_data, oldsize);
+	}
+
+	delete[] m_data;
+	m_allocatedSize = newsize;
+	m_data = new unsigned char[newsize];
+
+	if (olddata > 0L)
+		memcpy (m_data, olddata, min (oldsize, newsize));
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::init (const unsigned char* data, unsigned long length)
+{
+	resize (length);
+	memcpy (m_data, data, length);
+	m_cursor = &m_data[0];
+	m_writtenLength = length;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::clear()
+{
+	m_cursor = &m_data[0];
+	m_writtenLength = 0;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+char Bytestream::read_byte (bool* ok)
+{
+	*ok = bytes_left() > 0;
+	return *ok ? *m_cursor++ : -1;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+short int Bytestream::read_short (bool* ok)
+{
+	if (bytes_left() < 2)
+	{
+		*ok = false;
+		return false;
+	}
+
+	short int val = 0;
+
+	for (int i = 0; i < 2; ++i)
+		val |= *m_cursor++ << (i * 8);
+
+	*ok = true;
+	return true;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+long int Bytestream::read_long (bool* ok)
+{
+	if (bytes_left() < 4)
+	{
+		*ok = false;
+		return -1;
+	}
+
+	long int val = 0;
+
+	for (int i = 0; i < 4; ++i)
+		val |= *m_cursor++ << (i * 8);
+
+	*ok = true;
+	return val;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+float Bytestream::read_float (bool* ok)
+{
+	int value = read_long (ok);
+
+	if (*ok == false)
+		return -1.0f;
+
+	return reinterpret_cast<float&> (value);
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+String Bytestream::read_string (bool* ok)
+{
+	// Zandronum sends strings of maximum 2048 characters, though it only
+	// reads 2047-character long ones so I guess we can follow up and do
+	// the same :-)
+	static char buffer[MAX_NETWORK_STRING];
+	unsigned char* stringEnd;
+	unsigned char* stringBegin = m_cursor;
+	unsigned char* end = m_data + allocated_size();
+
+	// where's the end of the string?
+	for (stringEnd = m_cursor; *stringEnd != '\0'; ++stringEnd)
+	{
+		if (stringEnd == end)
+		{
+			// past the end of the buffer! Argh!
+			*ok = false;
+			return "";
+		}
+	}
+
+	m_cursor = stringEnd + 1;
+	*ok = true;
+	unsigned int length = stringEnd - m_cursor;
+
+	// ensure we won't write past the buffer (note: we still moved
+	// past the excess bytes in the above statement, those are ignored)
+	if (length >= MAX_NETWORK_STRING)
+		length = MAX_NETWORK_STRING - 1;
+
+	memcpy (buffer, stringBegin, length);
+	buffer[length] = '\0';
+	return String (buffer);
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+METHOD
+Bytestream::read (unsigned char* buffer, unsigned long length, bool* ok) -> void
+{
+	if (bytes_left() < length)
+	{
+		*ok = false;
+		return;
+	}
+
+	memcpy (buffer, m_cursor, length);
+	m_cursor += length;
+	*ok = true;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::write (unsigned char val)
+{
+	*m_cursor++ = val;
+	m_writtenLength++;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::write (const unsigned char* val, unsigned int length)
+{
+	grow_to_fit (length);
+	memcpy (m_cursor, val, length);
+	m_cursor += length;
+	m_writtenLength += length;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::grow_to_fit (unsigned long bytes)
+{
+	if (space_left() < bytes)
+		resize (allocated_size() + bytes + 128);
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::write_byte (char val)
+{
+	grow_to_fit (1);
+	write (val);
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::write_short (short int val)
+{
+	grow_to_fit (2);
+
+	for (int i = 0; i < 2; ++i)
+		write ((val >> (i * 8)) & 0xFF);
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::write_long (long int val)
+{
+	grow_to_fit (4);
+
+	for (int i = 0; i < 4; ++i)
+		write ((val >> (i * 8)) & 0xFF);
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::write_float (float val)
+{
+	// I know this is probably dangerous but this is what Zandronum does so yeah
+	write_long (reinterpret_cast<int&> (val));
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::write_string (const String& val)
+{
+	grow_to_fit (val.length() + 1);
+	write (reinterpret_cast<const unsigned char*> (val.chars()), val.length());
+	write (0);
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+void Bytestream::write_buffer (const Bytestream& other)
+{
+	write (other.data(), other.written_length());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/network/bytestream.h	Thu Dec 11 05:58:55 2014 +0200
@@ -0,0 +1,146 @@
+#pragma once
+#include "../main.h"
+
+class String;
+
+enum { MAX_NETWORK_STRING = 0x800 };
+
+// TODO: Make able to handle big-endian too
+class Bytestream
+{
+public:
+	static bool sink;
+
+	Bytestream (unsigned long length = 0x800);
+	Bytestream (const unsigned char* data, unsigned long length);
+	Bytestream (const Vector<unsigned char>& bytes);
+	~Bytestream();
+
+	inline METHOD allocated_size() const -> unsigned long;
+	inline METHOD bytes_left() const -> unsigned long;
+	       METHOD clear() -> void;
+	inline METHOD data() -> unsigned char*;
+	inline METHOD data() const -> const unsigned char*;
+	       METHOD grow_to_fit (unsigned long bytes) -> void;
+	inline METHOD position() const -> unsigned long;
+	       METHOD read (unsigned char* buffer, unsigned long length, bool* ok = &sink) -> void;
+	       METHOD read_byte (bool* ok = &sink) -> char;
+	       METHOD read_short (bool* ok = &sink) -> short int;
+	       METHOD read_long (bool* ok = &sink) -> long int;
+	       METHOD read_string (bool* ok = &sink) -> String;
+	       METHOD read_float (bool* ok = &sink) -> float;
+	       METHOD resize (unsigned long length) -> void;
+	inline METHOD rewind() -> void;
+	inline METHOD seek (unsigned long pos) -> void;
+	       METHOD write (const unsigned char* val, unsigned int length) -> void;
+	       METHOD write_buffer (const Bytestream& other) -> void;
+	       METHOD write_buffer (const Vector<unsigned char>& other) -> void;
+	       METHOD write_byte (char val) -> void;
+	       METHOD write_double (double val) -> void;
+	       METHOD write_float (float val) -> void;
+	       METHOD write_long (long int val) -> void;
+	       METHOD write_short (short int val) -> void;
+	       METHOD write_string (const String& val) -> void;
+	inline METHOD written_length() const -> unsigned long;
+
+	inline METHOD operator[] (unsigned long idx) -> unsigned char&;
+	inline METHOD operator[] (unsigned long idx) const -> unsigned char;
+
+private:
+	unsigned char* m_data;
+	unsigned char* m_cursor;
+	unsigned long m_allocatedSize;
+	unsigned long m_writtenLength;
+
+	METHOD init (const unsigned char* data, unsigned long length) -> void;
+	METHOD write (unsigned char val) -> void;
+	inline METHOD space_left() const -> unsigned long;
+};
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::allocated_size() const -> unsigned long
+{
+	return m_allocatedSize;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::written_length() const -> unsigned long
+{
+	return m_writtenLength;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::operator[] (unsigned long idx) -> unsigned char&
+{
+	return m_data[idx];
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::operator[] (unsigned long idx) const -> unsigned char
+{
+	return m_data[idx];
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::position() const -> unsigned long
+{
+	return m_cursor - m_data;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::seek (unsigned long pos) -> void
+{
+	m_cursor = m_data + pos;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::rewind() -> void
+{
+	m_cursor = m_data;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::bytes_left() const -> unsigned long
+{
+	return (m_writtenLength - (m_cursor - &m_data[0]));
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::space_left() const -> unsigned long
+{
+	return (m_allocatedSize - m_writtenLength);
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::data() -> unsigned char*
+{
+	return m_data;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+inline METHOD
+Bytestream::data() const -> const unsigned char*
+{
+	return m_data;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/network/ipaddress.cpp	Thu Dec 11 05:58:55 2014 +0200
@@ -0,0 +1,165 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include "ipaddress.h"
+
+const IPAddress localhost (0x7F000001, 0);
+bool IPAddress::sink;
+
+// -----------------------------------------------------------------------------
+//
+IPAddress::IPAddress() :
+	host (0),
+	port (0) {}
+
+// -----------------------------------------------------------------------------
+//
+IPAddress::IPAddress (unsigned long host, unsigned short port) :
+	host (host),
+	port (port) {}
+
+// -----------------------------------------------------------------------------
+//
+IPAddress::IPAddress (const IPAddress& other) :
+	host (other.host),
+	port (other.port) {}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::to_string (WithPort withport) const -> String
+{
+	String val;
+
+	if (withport == IP_WITH_PORT)
+		val.sprintf ("%u.%u.%u.%u:%u", octet (0), octet (1), octet (2), octet (3), port);
+	else
+		val.sprintf ("%u.%u.%u.%u", octet (0), octet (1), octet (2), octet (3));
+
+	return val;
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::octet (int n) const -> unsigned char
+{
+	return (host >> ((3 - n) * 8)) & 0xFF;
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::set_octet (int n, unsigned char oct) -> void
+{
+	// TODO: make a big-endian version
+	host &= ~(0xFF << (3 - n) * 8);
+	host |= oct << ((3 - n) * 8);
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::compare (const IPAddress& other) const -> bool
+{
+	for (int i = 0; i < 4; ++i)
+	{
+		if (octet (i) != other.octet (i))
+			return false;
+	}
+
+	if (port != 0
+		and other.port != 0
+		and port != other.port)
+	{
+		return false;
+	}
+
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::operator< (const IPAddress& other) const -> bool
+{
+	for (int i = 0; i < 4; ++i)
+	{
+		if (octet (i) != other.octet (i))
+			return octet (i) < other.octet (i);
+	}
+
+	return port < other.port;
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::to_sockaddr_in() const -> sockaddr_in
+{
+	sockaddr_in claddr;
+	memset (&claddr, 0, sizeof claddr);
+	claddr.sin_addr.s_addr = htonl (host);
+	claddr.sin_port = htons (port);
+	claddr.sin_family = AF_INET;
+	return claddr;
+}
+
+// -----------------------------------------------------------------------------
+//
+STATIC METHOD
+IPAddress::from_string (String input, bool* ok) -> IPAddress
+{
+	unsigned int parts[4];
+	int colonpos = input.find (":");
+	String addressString = colonpos == -1 ? input : input.mid (0, colonpos);
+	IPAddress value;
+
+	// Try scanf the IPv4 host first. If it's not an IP string, it could
+	// be a hostname; thus try resolve it.
+	if (sscanf (addressString, "%u.%u.%u.%u", &parts[0], &parts[1], &parts[2], &parts[3]))
+	{
+		for (short i = 0; i < 4; ++i)
+			value.set_octet (i, parts[i]);
+	}
+	else
+	{
+		// try resolve it
+		return IPAddress::resolve (addressString, ok);
+	}
+
+	if (colonpos != -1)
+		value.port = atoi (input.mid (colonpos + 1, -1));
+
+	return value;
+}
+
+// -----------------------------------------------------------------------------
+//
+STATIC METHOD
+IPAddress::resolve (String node, bool* ok) -> IPAddress
+{
+	struct addrinfo hints;
+	struct addrinfo* lookup;
+	int errorcode;
+	memset (&hints, 0, sizeof hints);
+	hints.ai_family = AF_INET;
+
+	if ((errorcode = getaddrinfo (node, nullptr, &hints, &lookup)) != 0)
+	{
+		*ok = false;
+		return IPAddress();
+	}
+
+	IPAddress result;
+	assert (lookup != nullptr);
+	sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*> (lookup[0].ai_addr);
+	result.host = ntohl (addr->sin_addr.s_addr);
+	result.port = ntohs (addr->sin_port);
+	freeaddrinfo (lookup);
+	*ok = true;
+	return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/network/ipaddress.h	Thu Dec 11 05:58:55 2014 +0200
@@ -0,0 +1,50 @@
+#pragma once
+#include "../main.h"
+
+struct sockaddr;
+
+enum WithPort { IP_WITH_PORT, IP_NO_PORT };
+
+struct IPAddress
+{
+	unsigned long host;
+	unsigned short port;
+	static bool sink;
+
+	IPAddress();
+	IPAddress (unsigned long host, unsigned short port);
+	IPAddress (const IPAddress& other);
+
+	       METHOD compare (const IPAddress& other) const -> bool;
+	       METHOD octet (int n) const -> unsigned char;
+	       METHOD set_octet (int n, unsigned char oct) -> void;
+	       METHOD to_string (WithPort withport = IP_NO_PORT) const -> String;
+	       METHOD to_sockaddr_in() const -> sockaddr_in;
+	       METHOD operator< (const IPAddress& other) const -> bool;
+	inline METHOD operator== (const IPAddress& other) const -> bool;
+	inline METHOD operator!= (const IPAddress& other) const -> bool;
+	inline METHOD operator[] (int n) const -> unsigned char;
+
+	static METHOD from_string (String input, bool* ok = &sink) -> IPAddress;
+	static METHOD resolve (String node, bool* ok = &sink) -> IPAddress;
+};
+
+extern const IPAddress localhost;
+
+inline METHOD
+IPAddress::operator[] (int n) const -> unsigned char
+{
+	return octet (n);
+}
+
+inline METHOD
+IPAddress::operator== (const IPAddress& other) const -> bool
+{
+	return compare (other);
+}
+
+inline METHOD
+IPAddress::operator!= (const IPAddress& other) const -> bool
+{
+	return not operator== (other);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/network/udp.cpp	Thu Dec 11 05:58:55 2014 +0200
@@ -0,0 +1,98 @@
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <fcntl.h>
+#include "udp.h"
+
+// -----------------------------------------------------------------------------
+//
+UDPSocket::UDPSocket() :
+	m_socket (socket (AF_INET, SOCK_DGRAM, 0)) {}
+
+// -----------------------------------------------------------------------------
+//
+UDPSocket::~UDPSocket() {}
+
+// -------------------------------------------------------------------------------------------------
+//
+METHOD
+UDPSocket::set_blocking (bool a) -> bool
+{
+	int flags = fcntl (m_socket, F_GETFL, 0);
+	int newflags = (a ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK));
+
+	if (flags < 0 || fcntl (m_socket, F_SETFL, newflags) != 0)
+	{
+		m_error = "Unable to set socket as non-blocking";
+		return false;
+	}
+
+	return true;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+METHOD
+UDPSocket::bind (unsigned short port) -> bool
+{
+	struct sockaddr_in svaddr;
+	memset (&svaddr, 0, sizeof svaddr);
+	svaddr.sin_family = AF_INET;
+	svaddr.sin_port = htons (port);
+	svaddr.sin_addr.s_addr = htonl (INADDR_ANY);
+
+	if (::bind (m_socket, reinterpret_cast<struct sockaddr*> (&svaddr), sizeof svaddr) == -1)
+	{
+		m_error = String ("Couldn't bind to port ") + String::from_number (port);
+		return false;
+	}
+
+	return true;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+METHOD
+UDPSocket::read (Datagram& datagram) -> bool
+{
+	sockaddr_in claddr;
+	socklen_t socklen = sizeof claddr;
+	static unsigned char packet[MAX_DATAGRAM_LENGTH];
+	int length = ::recvfrom (m_socket, packet, sizeof packet, 0,
+		reinterpret_cast<struct sockaddr*> (&claddr), &socklen);
+
+	if (length == -1)
+	{
+		// We got an error, though EWOULDBLOCK is silent as it means no packets recieved.
+		if (errno != EWOULDBLOCK)
+			m_error.sprintf ("recvfrom error: %s", strerror (errno));;
+
+		return false;
+	}
+
+	datagram.from.host = ntohl (claddr.sin_addr.s_addr);
+	datagram.from.port = ntohs (claddr.sin_port);
+	datagram.data = Bytestream (packet, length);
+	return true;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+METHOD
+UDPSocket::send (const Bytestream& data, const IPAddress& addr) -> bool
+{
+	struct sockaddr_in claddr = addr.to_sockaddr_in();
+
+	int res = ::sendto (m_socket, data.data(), data.written_length(), 0,
+		reinterpret_cast<struct sockaddr*> (&claddr), sizeof claddr);
+
+	if (res == -1)
+	{
+		m_error = String ("Unable to launch packet: ") + strerror (errno);
+		return false;
+	}
+
+	return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/network/udp.h	Thu Dec 11 05:58:55 2014 +0200
@@ -0,0 +1,31 @@
+#pragma once
+#include "../main.h"
+#include "ipaddress.h"
+#include "bytestream.h"
+
+enum { MAX_DATAGRAM_LENGTH = 5120 };
+
+struct Datagram
+{
+	Bytestream data;
+	IPAddress from;
+};
+
+// -------------------------------------------------------------------------------------------------
+//
+class UDPSocket
+{
+public:
+	UDPSocket();
+	virtual ~UDPSocket();
+
+	METHOD bind (unsigned short port) -> bool;
+	METHOD read (Datagram& datagram) -> bool;
+	METHOD send (const Bytestream& data, const IPAddress& addr) -> bool;
+	METHOD set_blocking (bool a) -> bool;
+
+private:
+	IPAddress m_addr;
+	String m_error;
+	int m_socket;
+};
--- a/sources/range.h	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/range.h	Thu Dec 11 05:58:55 2014 +0200
@@ -63,57 +63,14 @@
 	METHOD max() const -> T;
 	METHOD check_bounds() -> void;
 	METHOD contains (const T& c) const -> bool;
-	METHOD contains_exclusive (const T& c) const -> bool;
+	METHOD contains_exclusively (const T& c) const -> bool;
 	METHOD overlaps (Range<T> const& other) const -> bool;
 	METHOD operator== (Range<T> const& other) const -> bool;
 	METHOD operator!= (Range<T> const& other) const -> bool;
 };
 
-//
-// -------------------------------------------------------------------------------------------------
-//
-
-template<typename T> inline METHOD
-Range<T>::Iterator::operator*() -> T&
-{
-	return value;
-}
-
-//
-// -------------------------------------------------------------------------------------------------
-//
-
-template<typename T> inline METHOD
-Range<T>::Iterator::operator== (const Iterator& other) const -> bool
-{
-	return value == other.value;
-}
-
-//
 // -------------------------------------------------------------------------------------------------
 //
-
-template<typename T> inline METHOD
-Range<T>::Iterator::operator!= (const Iterator& other) const -> bool
-{
-	return value != other.value;
-}
-
-//
-// -------------------------------------------------------------------------------------------------
-//
-
-template<typename T> inline METHOD
-Range<T>::Iterator::operator++() -> Iterator&
-{
-	value += step;
-	return *this;
-}
-
-//
-// -------------------------------------------------------------------------------------------------
-//
-
 template<typename T>
 Range<T>::Range (const T& a, const T& b, const T& step) :
 	m_a (a),
@@ -123,19 +80,48 @@
 	check_bounds();
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T>
 Range<T>::Range() :
 	m_a (T()),
 	m_b (T()) {}
 
+// -------------------------------------------------------------------------------------------------
 //
+template<typename T> inline METHOD
+Range<T>::Iterator::operator*() -> T&
+{
+	return value;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
+template<typename T> inline METHOD
+Range<T>::Iterator::operator== (const Iterator& other) const -> bool
+{
+	return value == other.value;
+}
+
 // -------------------------------------------------------------------------------------------------
 //
+template<typename T> inline METHOD
+Range<T>::Iterator::operator!= (const Iterator& other) const -> bool
+{
+	return value != other.value;
+}
 
+// -------------------------------------------------------------------------------------------------
+//
+template<typename T> inline METHOD
+Range<T>::Iterator::operator++() -> Iterator&
+{
+	value += step;
+	return *this;
+}
+
+// -------------------------------------------------------------------------------------------------
+//
 template<typename T> METHOD
 Range<T>::check_bounds() -> void
 {
@@ -143,80 +129,64 @@
 		std::swap (m_a, m_b);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T> METHOD
 Range<T>::contains (const T& c) const -> bool
 {
 	return (c >= m_a) and (c <= m_b);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T> METHOD
-Range<T>::contains_exclusive (const T& c) const -> bool
+Range<T>::contains_exclusively (const T& c) const -> bool
 {
 	return (c > m_a) and (c < m_b);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T> METHOD
 Range<T>::overlaps (Range<T> const& other) const -> bool
 {
 	return contains (other.m_a) or contains (other.m_b);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T> METHOD
 Range<T>::operator== (Range<T> const& other) const -> bool
 {
 	return m_a == other.m_a and m_b == other.m_b;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T> METHOD
 Range<T>::operator!= (Range<T> const& other) const -> bool
 {
 	return not operator== (other);
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T> METHOD
 Range<T>::min() const -> T
 {
 	return m_a;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T> METHOD
 Range<T>::max() const -> T
 {
 	return m_b;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T> METHOD
 Range<T>::begin() const -> Iterator
 {
@@ -226,10 +196,8 @@
 	return it;
 }
 
-//
 // -------------------------------------------------------------------------------------------------
 //
-
 template<typename T> METHOD
 Range<T>::end() const -> Iterator
 {
--- a/sources/version.cpp	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/version.cpp	Thu Dec 11 05:58:55 2014 +0200
@@ -38,6 +38,8 @@
 #include "version.h"
 #include "hginfo.h"
 
+// -------------------------------------------------------------------------------------------------
+//
 FUNCTION
 full_version_string() -> const char*
 {
@@ -54,6 +56,8 @@
 	return buffer;
 }
 
+// -------------------------------------------------------------------------------------------------
+//
 FUNCTION
 changeset_date_string() -> const char*
 {
--- a/sources/version.h	Wed Dec 10 19:26:13 2014 +0200
+++ b/sources/version.h	Thu Dec 11 05:58:55 2014 +0200
@@ -36,9 +36,9 @@
 #define VERSION_MINOR 0
 #define VERSION_PATCH 0
 
-//
+// -------------------------------------------------------------------------------------------------
 // Version string
-//
+
 #if VERSION_PATCH == 0
 # define VERSION_STRING \
 	MACRO_TO_STRING (VERSION_MAJOR) \
@@ -50,21 +50,17 @@
 	"." MACRO_TO_STRING (VERSION_PATCH)
 #endif
 
-//
+// -------------------------------------------------------------------------------------------------
 // Returns the bare version string (1.2.3)
-//
+
 inline FUNCTION
 version_string() -> const char*
 {
 	return VERSION_STRING;
 }
 
-//
-// Returns full version string, with hash (1.2.3-abcd123)
-//
+// Returns full version string, with hash (1.2.3-abcd456)
 FUNCTION full_version_string() -> const char*;
 
-//
 // Returns changeset date string
-//
 FUNCTION changeset_date_string() -> const char*;

mercurial