changeset 485:898d8b29a4f1

Switch to lowercase filenames
author David Demelier <markand@malikania.fr>
date Thu, 12 Nov 2015 21:53:36 +0100
parents 3ee3f3e53ee3
children 7ee8da32da98
files C++/modules/Base64/Base64.cpp C++/modules/Base64/Base64.h C++/modules/Base64/base64.cpp C++/modules/Base64/base64.h C++/modules/Converter/Converter.cpp C++/modules/Converter/Converter.h C++/modules/Converter/converter.cpp C++/modules/Converter/converter.h C++/modules/Date/Date.cpp C++/modules/Date/Date.h C++/modules/Date/date.cpp C++/modules/Date/date.h C++/modules/Directory/Directory.cpp C++/modules/Directory/Directory.h C++/modules/Directory/directory.cpp C++/modules/Directory/directory.h C++/modules/Dynlib/Dynlib.cpp C++/modules/Dynlib/Dynlib.h C++/modules/Dynlib/dynlib.cpp C++/modules/Dynlib/dynlib.h C++/modules/Format/Format.cpp C++/modules/Format/Format.h C++/modules/Format/format.cpp C++/modules/Format/format.h C++/modules/Hash/Hash.cpp C++/modules/Hash/Hash.h C++/modules/Hash/hash.cpp C++/modules/Hash/hash.h C++/modules/Ini/Ini.cpp C++/modules/Ini/Ini.h C++/modules/Ini/ini.cpp C++/modules/Ini/ini.h C++/modules/Js/Js.cpp C++/modules/Js/Js.h C++/modules/Js/js.cpp C++/modules/Js/js.h C++/modules/Json/Json.cpp C++/modules/Json/Json.h C++/modules/Json/json.cpp C++/modules/Json/json.h C++/modules/OptionParser/OptionParser.cpp C++/modules/OptionParser/OptionParser.h C++/modules/OptionParser/options.cpp C++/modules/OptionParser/options.h C++/modules/Socket/Sockets.cpp C++/modules/Socket/Sockets.h C++/modules/Socket/sockets.cpp C++/modules/Socket/sockets.h C++/modules/Xdg/Xdg.cpp C++/modules/Xdg/Xdg.h C++/modules/Xdg/xdg.cpp C++/modules/Xdg/xdg.h C++/tests/Base64/main.cpp C++/tests/Directory/main.cpp C++/tests/Dynlib/Plugin.cpp C++/tests/Dynlib/main.cpp C++/tests/Hash/main.cpp C++/tests/Ini/main.cpp C++/tests/Js/main.cpp C++/tests/Json/main.cpp C++/tests/OptionParser/main.cpp C++/tests/Socket/main.cpp C++/tests/Xdg/main.cpp CMakeLists.txt
diffstat 64 files changed, 11552 insertions(+), 11553 deletions(-) [+]
line wrap: on
line diff
--- a/C++/modules/Base64/Base64.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * Base64.cpp -- base64 encoding and decoding
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <cassert>
-#include <iterator>
-#include <sstream>
-#include <unordered_map>
-
-#include "Base64.h"
-
-namespace base64 {
-
-namespace {
-
-const std::string table{"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
-
-const std::unordered_map<unsigned char, unsigned int> rtable{
-	{ 'A', 0  },
-	{ 'B', 1  },
-	{ 'C', 2  },
-	{ 'D', 3  },
-	{ 'E', 4  },
-	{ 'F', 5  },
-	{ 'G', 6  },
-	{ 'H', 7  },
-	{ 'I', 8  },
-	{ 'J', 9  },
-	{ 'K', 10 },
-	{ 'L', 11 },
-	{ 'M', 12 },
-	{ 'N', 13 },
-	{ 'O', 14 },
-	{ 'P', 15 },
-	{ 'Q', 16 },
-	{ 'R', 17 },
-	{ 'S', 18 },
-	{ 'T', 19 },
-	{ 'U', 20 },
-	{ 'V', 21 },
-	{ 'W', 22 },
-	{ 'X', 23 },
-	{ 'Y', 24 },
-	{ 'Z', 25 },
-	{ 'a', 26 },
-	{ 'b', 27 },
-	{ 'c', 28 },
-	{ 'd', 29 },
-	{ 'e', 30 },
-	{ 'f', 31 },
-	{ 'g', 32 },
-	{ 'h', 33 },
-	{ 'i', 34 },
-	{ 'j', 35 },
-	{ 'k', 36 },
-	{ 'l', 37 },
-	{ 'm', 38 },
-	{ 'n', 39 },
-	{ 'o', 40 },
-	{ 'p', 41 },
-	{ 'q', 42 },
-	{ 'r', 43 },
-	{ 's', 44 },
-	{ 't', 45 },
-	{ 'u', 46 },
-	{ 'v', 47 },
-	{ 'w', 48 },
-	{ 'x', 49 },
-	{ 'y', 50 },
-	{ 'z', 51 },
-	{ '0', 52 },
-	{ '1', 53 },
-	{ '2', 54 },
-	{ '3', 55 },
-	{ '4', 56 },
-	{ '5', 57 },
-	{ '6', 58 },
-	{ '7', 59 },
-	{ '8', 60 },
-	{ '9', 61 },
-	{ '+', 62 },
-	{ '/', 63 }
-};
-
-} // !namespace
-
-unsigned char lookup(unsigned int value) noexcept
-{
-	assert(value < 64);
-
-	return table[value];
-}
-
-unsigned int rlookup(unsigned char ch)
-{
-	assert(rtable.count(ch) != 0 && ch != '=');
-
-	return rtable.at(ch);
-}
-
-bool isValid(unsigned char ch) noexcept
-{
-	return ch == '=' || rtable.count(ch);
-}
-
-std::string encode(const std::string &input)
-{
-	std::string result;
-	std::istringstream iss(input, std::istringstream::in);
-
-	encode(std::istreambuf_iterator<char>(iss), std::istreambuf_iterator<char>(), std::back_inserter(result));
-
-	return result;
-}
-
-std::string decode(const std::string &input)
-{
-	std::string result;
-	std::istringstream iss(input, std::istringstream::in);
-
-	decode(std::istreambuf_iterator<char>(iss), std::istreambuf_iterator<char>(), std::back_inserter(result));
-
-	return result;
-}
-
-} // !base64
--- a/C++/modules/Base64/Base64.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * Base64.h -- base64 encoding and decoding
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BASE_64_H_
-#define _BASE_64_H_
-
-/**
- * @file Base64.h
- * @brief Base64 encoding and decoding
- */
-
-#include <stdexcept>
-#include <string>
-
-namespace base64 {
-
-/**
- * Get the base 64 character from the 6-bits value.
- *
- * @pre value must be valid
- * @param value the value
- */
-unsigned char lookup(unsigned int value) noexcept;
-
-/**
- * Get the integer value from the base 64 character.
- *
- * @pre ch must be a valid base 64 character but not '='
- * @param ch the base64 character
- */
-unsigned int rlookup(unsigned char ch);
-
-/**
- * Check if the given character is a valid base 64 character.
- *
- * @param char the character
- * @return true if the character is valid
- */
-bool isValid(unsigned char) noexcept;
-
-/**
- * Encode the input to the output. Requirements:
- *	InputIt	must be InputIterator
- *	OutputIt must be OutputIterator
- *
- * @param input the beginning
- * @param end the end of the data
- * @param output the output destination
- * @return output
- */
-template <typename InputIt, typename OutputIt>
-OutputIt encode(InputIt input, InputIt end, OutputIt output)
-{
-	while (input != end) {
-		char inputbuf[3] = { 0, 0, 0 };
-		int count;
-
-		for (count = 0; count < 3 && input != end; ++count) {
-			inputbuf[count] = *input++;
-		}
-
-		*output++ = lookup(inputbuf[0] >> 2 & 0x3f);
-		*output++ = lookup((inputbuf[0] << 4 & 0x3f) | (inputbuf[1] >> 4 & 0x0f));
-		*output++ = (count < 2) ? '=' : lookup((inputbuf[1] << 2 & 0x3c) | (inputbuf[2] >> 6 & 0x03));
-		*output++ = (count < 3) ? '=' : lookup(inputbuf[2] & 0x3f);
-	}
-
-	return output;
-}
-
-/**
- * Decode the input to the output. Requirements:
- *	InputIt must be InputIterator
- *	OutputIt must be OutputIterator
- *
- * @param input the beginning
- * @param end the end of the data
- * @param output the output destination
- * @return output
- * @throw std::invalid_argument on bad base64 string
- */
-template <typename InputIt, typename OutputIt>
-OutputIt decode(InputIt input, InputIt end, OutputIt output)
-{
-	while (input != end) {
-		char inputbuf[4] = { -1, -1, -1, -1 };
-		int count;
-
-		for (count = 0; count < 4 && input != end; ++count) {
-			if (*input != '=') {
-				/* Check if the character is valid and get its value */
-				if (isValid(*input)) {
-					inputbuf[count] = rlookup(*input);
-				} else {
-					throw std::invalid_argument{"invalid base64 string"};
-				}
-			} else {
-				/* A base 64 string cannot start with "=" or "==" */
-				if (count == 0 || count == 1) {
-					throw std::invalid_argument{"invalid or truncated base64 string"};
-				}
-			}
-			
-			input++;
-		}
-
-		if (count != 4) {
-			throw std::invalid_argument("truncated string");
-		}
-
-		*output++ = static_cast<unsigned char>(((inputbuf[0] << 2) & 0xfc) | ((inputbuf[1] >> 4) & 0x03));
-
-		if (inputbuf[2] != -1) {
-			*output++ = static_cast<unsigned char>(((inputbuf[1] << 4) & 0xf0) | ((inputbuf[2] >> 2) & 0x0f));
-		}
-		if (inputbuf[3] != -1) {
-			/* "XY=Z" is not allowed */
-			if (inputbuf[2] == -1) {
-				throw std::invalid_argument{"invalid base64 string"};
-			}
-
-			*output++ = static_cast<unsigned char>(((inputbuf[2] << 6) & 0xc0) | (inputbuf[3] & 0x3f));
-		}
-	}
-
-	return output;
-}
-
-/**
- * Encode a string.
- *
- * @param input the input string
- * @return the base64 formatted string
- */
-std::string encode(const std::string &input);
-
-/**
- * Decode a string.
- *
- * @param input the base64 formatted string
- * @return the original string
- * @throw std::invalid_argument on bad base64 string
- */
-std::string decode(const std::string &input);
-
-} // !base64
-
-#endif // !_BASE_64_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Base64/base64.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,140 @@
+/*
+ * Base64.cpp -- base64 encoding and decoding
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cassert>
+#include <iterator>
+#include <sstream>
+#include <unordered_map>
+
+#include "base64.h"
+
+namespace base64 {
+
+namespace {
+
+const std::string table{"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
+
+const std::unordered_map<unsigned char, unsigned int> rtable{
+	{ 'A', 0  },
+	{ 'B', 1  },
+	{ 'C', 2  },
+	{ 'D', 3  },
+	{ 'E', 4  },
+	{ 'F', 5  },
+	{ 'G', 6  },
+	{ 'H', 7  },
+	{ 'I', 8  },
+	{ 'J', 9  },
+	{ 'K', 10 },
+	{ 'L', 11 },
+	{ 'M', 12 },
+	{ 'N', 13 },
+	{ 'O', 14 },
+	{ 'P', 15 },
+	{ 'Q', 16 },
+	{ 'R', 17 },
+	{ 'S', 18 },
+	{ 'T', 19 },
+	{ 'U', 20 },
+	{ 'V', 21 },
+	{ 'W', 22 },
+	{ 'X', 23 },
+	{ 'Y', 24 },
+	{ 'Z', 25 },
+	{ 'a', 26 },
+	{ 'b', 27 },
+	{ 'c', 28 },
+	{ 'd', 29 },
+	{ 'e', 30 },
+	{ 'f', 31 },
+	{ 'g', 32 },
+	{ 'h', 33 },
+	{ 'i', 34 },
+	{ 'j', 35 },
+	{ 'k', 36 },
+	{ 'l', 37 },
+	{ 'm', 38 },
+	{ 'n', 39 },
+	{ 'o', 40 },
+	{ 'p', 41 },
+	{ 'q', 42 },
+	{ 'r', 43 },
+	{ 's', 44 },
+	{ 't', 45 },
+	{ 'u', 46 },
+	{ 'v', 47 },
+	{ 'w', 48 },
+	{ 'x', 49 },
+	{ 'y', 50 },
+	{ 'z', 51 },
+	{ '0', 52 },
+	{ '1', 53 },
+	{ '2', 54 },
+	{ '3', 55 },
+	{ '4', 56 },
+	{ '5', 57 },
+	{ '6', 58 },
+	{ '7', 59 },
+	{ '8', 60 },
+	{ '9', 61 },
+	{ '+', 62 },
+	{ '/', 63 }
+};
+
+} // !namespace
+
+unsigned char lookup(unsigned int value) noexcept
+{
+	assert(value < 64);
+
+	return table[value];
+}
+
+unsigned int rlookup(unsigned char ch)
+{
+	assert(rtable.count(ch) != 0 && ch != '=');
+
+	return rtable.at(ch);
+}
+
+bool isValid(unsigned char ch) noexcept
+{
+	return ch == '=' || rtable.count(ch);
+}
+
+std::string encode(const std::string &input)
+{
+	std::string result;
+	std::istringstream iss(input, std::istringstream::in);
+
+	encode(std::istreambuf_iterator<char>(iss), std::istreambuf_iterator<char>(), std::back_inserter(result));
+
+	return result;
+}
+
+std::string decode(const std::string &input)
+{
+	std::string result;
+	std::istringstream iss(input, std::istringstream::in);
+
+	decode(std::istreambuf_iterator<char>(iss), std::istreambuf_iterator<char>(), std::back_inserter(result));
+
+	return result;
+}
+
+} // !base64
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Base64/base64.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,163 @@
+/*
+ * Base64.h -- base64 encoding and decoding
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BASE_64_H_
+#define _BASE_64_H_
+
+/**
+ * @file Base64.h
+ * @brief Base64 encoding and decoding
+ */
+
+#include <stdexcept>
+#include <string>
+
+namespace base64 {
+
+/**
+ * Get the base 64 character from the 6-bits value.
+ *
+ * @pre value must be valid
+ * @param value the value
+ */
+unsigned char lookup(unsigned int value) noexcept;
+
+/**
+ * Get the integer value from the base 64 character.
+ *
+ * @pre ch must be a valid base 64 character but not '='
+ * @param ch the base64 character
+ */
+unsigned int rlookup(unsigned char ch);
+
+/**
+ * Check if the given character is a valid base 64 character.
+ *
+ * @param char the character
+ * @return true if the character is valid
+ */
+bool isValid(unsigned char) noexcept;
+
+/**
+ * Encode the input to the output. Requirements:
+ *	InputIt	must be InputIterator
+ *	OutputIt must be OutputIterator
+ *
+ * @param input the beginning
+ * @param end the end of the data
+ * @param output the output destination
+ * @return output
+ */
+template <typename InputIt, typename OutputIt>
+OutputIt encode(InputIt input, InputIt end, OutputIt output)
+{
+	while (input != end) {
+		char inputbuf[3] = { 0, 0, 0 };
+		int count;
+
+		for (count = 0; count < 3 && input != end; ++count) {
+			inputbuf[count] = *input++;
+		}
+
+		*output++ = lookup(inputbuf[0] >> 2 & 0x3f);
+		*output++ = lookup((inputbuf[0] << 4 & 0x3f) | (inputbuf[1] >> 4 & 0x0f));
+		*output++ = (count < 2) ? '=' : lookup((inputbuf[1] << 2 & 0x3c) | (inputbuf[2] >> 6 & 0x03));
+		*output++ = (count < 3) ? '=' : lookup(inputbuf[2] & 0x3f);
+	}
+
+	return output;
+}
+
+/**
+ * Decode the input to the output. Requirements:
+ *	InputIt must be InputIterator
+ *	OutputIt must be OutputIterator
+ *
+ * @param input the beginning
+ * @param end the end of the data
+ * @param output the output destination
+ * @return output
+ * @throw std::invalid_argument on bad base64 string
+ */
+template <typename InputIt, typename OutputIt>
+OutputIt decode(InputIt input, InputIt end, OutputIt output)
+{
+	while (input != end) {
+		char inputbuf[4] = { -1, -1, -1, -1 };
+		int count;
+
+		for (count = 0; count < 4 && input != end; ++count) {
+			if (*input != '=') {
+				/* Check if the character is valid and get its value */
+				if (isValid(*input)) {
+					inputbuf[count] = rlookup(*input);
+				} else {
+					throw std::invalid_argument{"invalid base64 string"};
+				}
+			} else {
+				/* A base 64 string cannot start with "=" or "==" */
+				if (count == 0 || count == 1) {
+					throw std::invalid_argument{"invalid or truncated base64 string"};
+				}
+			}
+			
+			input++;
+		}
+
+		if (count != 4) {
+			throw std::invalid_argument("truncated string");
+		}
+
+		*output++ = static_cast<unsigned char>(((inputbuf[0] << 2) & 0xfc) | ((inputbuf[1] >> 4) & 0x03));
+
+		if (inputbuf[2] != -1) {
+			*output++ = static_cast<unsigned char>(((inputbuf[1] << 4) & 0xf0) | ((inputbuf[2] >> 2) & 0x0f));
+		}
+		if (inputbuf[3] != -1) {
+			/* "XY=Z" is not allowed */
+			if (inputbuf[2] == -1) {
+				throw std::invalid_argument{"invalid base64 string"};
+			}
+
+			*output++ = static_cast<unsigned char>(((inputbuf[2] << 6) & 0xc0) | (inputbuf[3] & 0x3f));
+		}
+	}
+
+	return output;
+}
+
+/**
+ * Encode a string.
+ *
+ * @param input the input string
+ * @return the base64 formatted string
+ */
+std::string encode(const std::string &input);
+
+/**
+ * Decode a string.
+ *
+ * @param input the base64 formatted string
+ * @return the original string
+ * @throw std::invalid_argument on bad base64 string
+ */
+std::string decode(const std::string &input);
+
+} // !base64
+
+#endif // !_BASE_64_H_
--- a/C++/modules/Converter/Converter.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Converter.cpp -- iconv based converter
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <cerrno>
-#include <cstring>
-#include <string>
-#include <iterator>
-#include <memory>
-#include <string>
-#include <stdexcept>
-#include <vector>
-
-#include <iconv.h>
-
-#include "Converter.h"
-
-struct Deleter {
-	void operator()(iconv_t desc)
-	{
-		iconv_close(desc);
-	}
-};
-
-using Iconv = std::unique_ptr<std::remove_pointer<iconv_t>::type, Deleter>;
-
-std::string Converter::convert(const char *from,
-			       const char *to,
-			       const std::string &input)
-{
-	// No conversion if from and to are identical
-	if (std::strcmp(from, to) == 0)
-		return input;
-
-	// Try to open the conversion descriptor
-	auto cd = iconv_open(to, from);
-
-	if (cd == (iconv_t)-1)
-		throw std::invalid_argument(std::strerror(errno));
-
-	Iconv cv(cd);
-	std::size_t insize(input.size());
-	std::size_t outsize(insize);
-	std::vector<char> result(insize + 1);
-
-	auto *b = &input[0];
-	auto *p = &result[0];
-
-	while (insize > 0) {
-		/* Convert */
-		auto r = iconv(cv.get(), &b, &insize, &p, &outsize);
-
-		if (r == (size_t)-1) {
-			switch (errno) {
-			case EBADF:
-			case EILSEQ:
-			case EINVAL:
-				throw std::invalid_argument(std::strerror(errno));
-			case E2BIG:
-				/*
-				 * Here, we need to reallocate more data because the output
-				 * string may need more space.
-				 *
-				 * We use 16 as an optimistic value.
-				 */
-
-				result.reserve(result.size() + 16 + 1);
-				p = &result[result.size()];
-				outsize += 16;
-			default:
-				break;
-			}
-		}
-
-	}
-
-	return std::string(&result[0], (p - &result[0]));
-}
--- a/C++/modules/Converter/Converter.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Converter.h -- iconv based converter
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _CONVERTER_H_
-#define _CONVERTER_H_
-
-/**
- * @file Converter.h
- * @brief Converter using libiconv
- */
-
-#include <string>
-
-/**
- * @class Converter
- * @brief Convert string between different encodings
- */
-class Converter {
-public:
-	/**
-	 * Convert the string into a different encoding.
-	 *
-	 * @param from the from encoding
-	 * @param to the destination encoding
-	 * @param input the string to convert
-	 * @return the converted string
-	 * @throw std::invalid_argument on invalid sequence
-	 */
-	static std::string convert(const char *from,
-				   const char *to,
-				   const std::string &input);
-};
-
-#endif // !_CONVERTER_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Converter/converter.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,92 @@
+/*
+ * Converter.cpp -- iconv based converter
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cerrno>
+#include <cstring>
+#include <string>
+#include <iterator>
+#include <memory>
+#include <string>
+#include <stdexcept>
+#include <vector>
+
+#include <iconv.h>
+
+#include "converter.h"
+
+struct Deleter {
+	void operator()(iconv_t desc)
+	{
+		iconv_close(desc);
+	}
+};
+
+using Iconv = std::unique_ptr<std::remove_pointer<iconv_t>::type, Deleter>;
+
+std::string Converter::convert(const char *from,
+			       const char *to,
+			       const std::string &input)
+{
+	// No conversion if from and to are identical
+	if (std::strcmp(from, to) == 0)
+		return input;
+
+	// Try to open the conversion descriptor
+	auto cd = iconv_open(to, from);
+
+	if (cd == (iconv_t)-1)
+		throw std::invalid_argument(std::strerror(errno));
+
+	Iconv cv(cd);
+	std::size_t insize(input.size());
+	std::size_t outsize(insize);
+	std::vector<char> result(insize + 1);
+
+	auto *b = &input[0];
+	auto *p = &result[0];
+
+	while (insize > 0) {
+		/* Convert */
+		auto r = iconv(cv.get(), &b, &insize, &p, &outsize);
+
+		if (r == (size_t)-1) {
+			switch (errno) {
+			case EBADF:
+			case EILSEQ:
+			case EINVAL:
+				throw std::invalid_argument(std::strerror(errno));
+			case E2BIG:
+				/*
+				 * Here, we need to reallocate more data because the output
+				 * string may need more space.
+				 *
+				 * We use 16 as an optimistic value.
+				 */
+
+				result.reserve(result.size() + 16 + 1);
+				p = &result[result.size()];
+				outsize += 16;
+			default:
+				break;
+			}
+		}
+
+	}
+
+	return std::string(&result[0], (p - &result[0]));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Converter/converter.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,49 @@
+/*
+ * Converter.h -- iconv based converter
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _CONVERTER_H_
+#define _CONVERTER_H_
+
+/**
+ * @file Converter.h
+ * @brief Converter using libiconv
+ */
+
+#include <string>
+
+/**
+ * @class Converter
+ * @brief Convert string between different encodings
+ */
+class Converter {
+public:
+	/**
+	 * Convert the string into a different encoding.
+	 *
+	 * @param from the from encoding
+	 * @param to the destination encoding
+	 * @param input the string to convert
+	 * @return the converted string
+	 * @throw std::invalid_argument on invalid sequence
+	 */
+	static std::string convert(const char *from,
+				   const char *to,
+				   const std::string &input);
+};
+
+#endif // !_CONVERTER_H_
--- a/C++/modules/Date/Date.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Date.cpp -- date and time manipulation
- *
- * Copyright (c) 2011-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "Date.h"
-
-Date::Date()
-{
-	m_timestamp = time(nullptr);
-}
-
-Date::Date(time_t timestamp)
-{
-	m_timestamp = timestamp;
-}
-
-std::string Date::format(const std::string &format)
-{
-	char buffer[512];
-	struct tm *tm;
-
-	tm = localtime(&m_timestamp);
-	strftime(buffer, sizeof (buffer), format.c_str(), tm);
-
-	return std::string(buffer);
-}
-
-bool operator==(const Date &d1, const Date &d2)
-{
-	return d1.timestamp() == d2.timestamp();
-}
-
-bool operator<=(const Date &d1, const Date &d2)
-{
-	return d1.timestamp() <= d2.timestamp();
-}
--- a/C++/modules/Date/Date.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Date.h -- date and time manipulation
- *
- * Copyright (c) 2011-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _DATE_H_
-#define _DATE_H_
-
-/**
- * @file Date.h
- * @brief Basic date management.
- */
-
-#include <cstdint>
-#include <ctime>
-#include <string>
-
-/**
- * @class Date
- * @brief Basic date class and format.
- */
-class Date {
-private:
-	time_t m_timestamp;
-
-public:
-	/**
-	 * Default constructor to the current date.
-	 */
-	Date();
-
-	/**
-	 * Date with specific timestamp.
-	 *
-	 * @param timestamp the timestamp
-	 */
-	Date(time_t timestamp);
-
-	/**
-	 * Get the timestamp.
-	 *
-	 * @return the timestamp
-	 */
-	inline time_t timestamp() const noexcept
-	{
-		return m_timestamp;
-	}
-
-	/**
-	 * Format the current that in the specified format,
-	 * see strftime(3) for patterns.
-	 *
-	 * @param format the format
-	 * @return the date formated
-	 */
-	std::string format(const std::string &format);
-};
-
-/**
- * Check is two dates are identical.
- *
- * @param d1 the first date
- * @param d2 the second date
- * @return true if same
- */
-bool operator==(const Date &d1, const Date &d2);
-
-/**
- * Check is a date is less or equal the second date.
- *
- * @param d1 the first date
- * @param d2 the second date
- * @return true if d1 <= d2
- */
-bool operator<=(const Date &d1, const Date &d2);
-
-#endif // !_DATE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Date/date.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,50 @@
+/*
+ * date.cpp -- date and time manipulation
+ *
+ * Copyright (c) 2011-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "date.h"
+
+Date::Date()
+{
+	m_timestamp = time(nullptr);
+}
+
+Date::Date(time_t timestamp)
+{
+	m_timestamp = timestamp;
+}
+
+std::string Date::format(const std::string &format)
+{
+	char buffer[512];
+	struct tm *tm;
+
+	tm = localtime(&m_timestamp);
+	strftime(buffer, sizeof (buffer), format.c_str(), tm);
+
+	return std::string(buffer);
+}
+
+bool operator==(const Date &d1, const Date &d2)
+{
+	return d1.timestamp() == d2.timestamp();
+}
+
+bool operator<=(const Date &d1, const Date &d2)
+{
+	return d1.timestamp() <= d2.timestamp();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Date/date.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,90 @@
+/*
+ * date.h -- date and time manipulation
+ *
+ * Copyright (c) 2011-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DATE_H_
+#define _DATE_H_
+
+/**
+ * @file date.h
+ * @brief Basic date management.
+ */
+
+#include <cstdint>
+#include <ctime>
+#include <string>
+
+/**
+ * @class Date
+ * @brief Basic date class and format.
+ */
+class Date {
+private:
+	time_t m_timestamp;
+
+public:
+	/**
+	 * Default constructor to the current date.
+	 */
+	Date();
+
+	/**
+	 * Date with specific timestamp.
+	 *
+	 * @param timestamp the timestamp
+	 */
+	Date(time_t timestamp);
+
+	/**
+	 * Get the timestamp.
+	 *
+	 * @return the timestamp
+	 */
+	inline time_t timestamp() const noexcept
+	{
+		return m_timestamp;
+	}
+
+	/**
+	 * Format the current that in the specified format,
+	 * see strftime(3) for patterns.
+	 *
+	 * @param format the format
+	 * @return the date formated
+	 */
+	std::string format(const std::string &format);
+};
+
+/**
+ * Check is two dates are identical.
+ *
+ * @param d1 the first date
+ * @param d2 the second date
+ * @return true if same
+ */
+bool operator==(const Date &d1, const Date &d2);
+
+/**
+ * Check is a date is less or equal the second date.
+ *
+ * @param d1 the first date
+ * @param d2 the second date
+ * @return true if d1 <= d2
+ */
+bool operator<=(const Date &d1, const Date &d2);
+
+#endif // !_DATE_H_
--- a/C++/modules/Directory/Directory.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- * Directory.cpp -- open and read directories
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sstream>
-#include <stdexcept>
-
-#include "Directory.h"
-
-#if defined(_WIN32)
-#  include <Windows.h>
-#else
-#  include <cstring>
-#  include <cerrno>
-
-#  include <sys/types.h>
-#  include <dirent.h>
-#endif
-
-#if defined(_WIN32)
-
-namespace {
-
-std::string systemError()
-{
-	LPSTR error = nullptr;
-	std::string errmsg = "Unknown error";
-
-	FormatMessageA(
-		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-		NULL,
-		GetLastError(),
-		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		(LPSTR)&error, 0, NULL);
-
-	if (error) {
-		errmsg = std::string(error);
-		LocalFree(error);
-	}
-
-	return errmsg;
-}
-
-} // !namespace
-
-void Directory::systemLoad(const std::string &path, int flags)
-{
-	std::ostringstream oss;
-	HANDLE handle;
-	WIN32_FIND_DATA fdata;
-
-	oss << path << "\\*";
-	handle = FindFirstFile(oss.str().c_str(), &fdata);
-
-	if (handle == nullptr)
-		throw std::runtime_error(systemError());
-
-	do {
-		DirectoryEntry entry;
-
-		entry.name = fdata.cFileName;
-		if (entry.name == "." && !(flags & Directory::Dot))
-			continue;
-		if (entry.name == ".." && !(flags & Directory::DotDot))
-			continue;
-
-		switch (fdata.dwFileAttributes) {
-		case FILE_ATTRIBUTE_DIRECTORY:
-			entry.type = DirectoryEntry::Dir;
-			break;
-		case FILE_ATTRIBUTE_NORMAL:
-			entry.type = DirectoryEntry::File;
-			break;
-		case FILE_ATTRIBUTE_REPARSE_POINT:
-			entry.type = DirectoryEntry::Link;
-			break;
-		default:
-			break;
-		}
-
-		push_back(entry);
-	} while (FindNextFile(handle, &fdata) != 0);
-
-	FindClose(handle);
-}
-
-#else
-
-void Directory::systemLoad(const std::string &path, int flags)
-{
-	DIR *dp;
-	struct dirent *ent;
-
-	if ((dp = opendir(path.c_str())) == nullptr)
-		throw std::runtime_error(strerror(errno));
-
-	while ((ent = readdir(dp)) != nullptr) {
-		DirectoryEntry entry;
-
-		entry.name = ent->d_name;
-		if (entry.name == "." && !(flags & Directory::Dot))
-			continue;
-		if (entry.name == ".." && !(flags & Directory::DotDot))
-			continue;
-
-		switch (ent->d_type) {
-		case DT_DIR:
-			entry.type = DirectoryEntry::Dir;
-			break;
-		case DT_REG:
-			entry.type = DirectoryEntry::File;
-			break;
-		case DT_LNK:
-			entry.type = DirectoryEntry::Link;
-			break;
-		default:
-			break;
-		}
-
-		push_back(entry);
-	}
-
-	closedir(dp);
-}
-
-#endif
-
-bool operator==(const DirectoryEntry &e1, const DirectoryEntry &e2)
-{
-	return e1.name == e2.name && e1.type == e2.type;
-}
-
-Directory::Directory()
-{
-}
-
-Directory::Directory(const std::string &path, int flags)
-{
-	systemLoad(path, flags);
-}
-
-int Directory::count() const
-{
-	return size();
-}
--- a/C++/modules/Directory/Directory.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Directory.h -- open and read directories
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _DIRECTORY_H_
-#define _DIRECTORY_H_
-
-#include <cstddef>
-#include <string>
-#include <vector>
-
-/**
- * @class DirectoryEntry
- * @brief Entry in the directory list
- */
-class DirectoryEntry {
-public:
-	/**
-	 * @brief Describe the type of an entry
-	 */
-	enum {
-		Unknown		= 0,
-		File,
-		Dir,
-		Link
-	};
-
-	std::string	name;		//! name of entry (base name)
-	int		type{Unknown};	//! type of file
-
-	friend bool operator==(const DirectoryEntry &e1, const DirectoryEntry &e2);
-};
-
-/**
- * @class Directory
- * @brief class to manipulate directories
- *
- * This class allow the user to iterate directories in a for range based
- * loop using iterators.
- */
-class Directory : public std::vector<DirectoryEntry> {
-public:
-	/**
-	 * @enum Flags
-	 * @brief optional flags to read directories
-	 */
-	enum Flags {
-		Dot	= (1 << 0),	//!< If set, lists "." too
-		DotDot	= (1 << 1)	//!< If set, lists ".." too
-	};
-
-private:
-	void systemLoad(const std::string &path, int flags);
-
-public:
-	/**
-	 * Default constructor, does nothing.
-	 */
-	Directory();
-
-	/**
-	 * Open a directory and read all its content.
-	 * @param path the path
-	 * @param flags the optional flags
-	 */
-	Directory(const std::string &path, int flags = 0);
-
-	/**
-	 * Get the number of entries in the directory.
-	 *
-	 * @return the number
-	 */
-	int count() const;
-};
-
-#endif // !_DIRECTORY_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Directory/directory.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,159 @@
+/*
+ * directory.cpp -- open and read directories
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sstream>
+#include <stdexcept>
+
+#include "directory.h"
+
+#if defined(_WIN32)
+#  include <Windows.h>
+#else
+#  include <cstring>
+#  include <cerrno>
+
+#  include <sys/types.h>
+#  include <dirent.h>
+#endif
+
+#if defined(_WIN32)
+
+namespace {
+
+std::string systemError()
+{
+	LPSTR error = nullptr;
+	std::string errmsg = "Unknown error";
+
+	FormatMessageA(
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,
+		GetLastError(),
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPSTR)&error, 0, NULL);
+
+	if (error) {
+		errmsg = std::string(error);
+		LocalFree(error);
+	}
+
+	return errmsg;
+}
+
+} // !namespace
+
+void Directory::systemLoad(const std::string &path, int flags)
+{
+	std::ostringstream oss;
+	HANDLE handle;
+	WIN32_FIND_DATA fdata;
+
+	oss << path << "\\*";
+	handle = FindFirstFile(oss.str().c_str(), &fdata);
+
+	if (handle == nullptr)
+		throw std::runtime_error(systemError());
+
+	do {
+		DirectoryEntry entry;
+
+		entry.name = fdata.cFileName;
+		if (entry.name == "." && !(flags & Directory::Dot))
+			continue;
+		if (entry.name == ".." && !(flags & Directory::DotDot))
+			continue;
+
+		switch (fdata.dwFileAttributes) {
+		case FILE_ATTRIBUTE_DIRECTORY:
+			entry.type = DirectoryEntry::Dir;
+			break;
+		case FILE_ATTRIBUTE_NORMAL:
+			entry.type = DirectoryEntry::File;
+			break;
+		case FILE_ATTRIBUTE_REPARSE_POINT:
+			entry.type = DirectoryEntry::Link;
+			break;
+		default:
+			break;
+		}
+
+		push_back(entry);
+	} while (FindNextFile(handle, &fdata) != 0);
+
+	FindClose(handle);
+}
+
+#else
+
+void Directory::systemLoad(const std::string &path, int flags)
+{
+	DIR *dp;
+	struct dirent *ent;
+
+	if ((dp = opendir(path.c_str())) == nullptr)
+		throw std::runtime_error(strerror(errno));
+
+	while ((ent = readdir(dp)) != nullptr) {
+		DirectoryEntry entry;
+
+		entry.name = ent->d_name;
+		if (entry.name == "." && !(flags & Directory::Dot))
+			continue;
+		if (entry.name == ".." && !(flags & Directory::DotDot))
+			continue;
+
+		switch (ent->d_type) {
+		case DT_DIR:
+			entry.type = DirectoryEntry::Dir;
+			break;
+		case DT_REG:
+			entry.type = DirectoryEntry::File;
+			break;
+		case DT_LNK:
+			entry.type = DirectoryEntry::Link;
+			break;
+		default:
+			break;
+		}
+
+		push_back(entry);
+	}
+
+	closedir(dp);
+}
+
+#endif
+
+bool operator==(const DirectoryEntry &e1, const DirectoryEntry &e2)
+{
+	return e1.name == e2.name && e1.type == e2.type;
+}
+
+Directory::Directory()
+{
+}
+
+Directory::Directory(const std::string &path, int flags)
+{
+	systemLoad(path, flags);
+}
+
+int Directory::count() const
+{
+	return size();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Directory/directory.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,90 @@
+/*
+ * directory.h -- open and read directories
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DIRECTORY_H_
+#define _DIRECTORY_H_
+
+#include <cstddef>
+#include <string>
+#include <vector>
+
+/**
+ * @class DirectoryEntry
+ * @brief Entry in the directory list
+ */
+class DirectoryEntry {
+public:
+	/**
+	 * @brief Describe the type of an entry
+	 */
+	enum {
+		Unknown		= 0,
+		File,
+		Dir,
+		Link
+	};
+
+	std::string	name;		//! name of entry (base name)
+	int		type{Unknown};	//! type of file
+
+	friend bool operator==(const DirectoryEntry &e1, const DirectoryEntry &e2);
+};
+
+/**
+ * @class Directory
+ * @brief class to manipulate directories
+ *
+ * This class allow the user to iterate directories in a for range based
+ * loop using iterators.
+ */
+class Directory : public std::vector<DirectoryEntry> {
+public:
+	/**
+	 * @enum Flags
+	 * @brief optional flags to read directories
+	 */
+	enum Flags {
+		Dot	= (1 << 0),	//!< If set, lists "." too
+		DotDot	= (1 << 1)	//!< If set, lists ".." too
+	};
+
+private:
+	void systemLoad(const std::string &path, int flags);
+
+public:
+	/**
+	 * Default constructor, does nothing.
+	 */
+	Directory();
+
+	/**
+	 * Open a directory and read all its content.
+	 * @param path the path
+	 * @param flags the optional flags
+	 */
+	Directory(const std::string &path, int flags = 0);
+
+	/**
+	 * Get the number of entries in the directory.
+	 *
+	 * @return the number
+	 */
+	int count() const;
+};
+
+#endif // !_DIRECTORY_H_
--- a/C++/modules/Dynlib/Dynlib.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * DynLib.cpp -- portable shared library loader
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdexcept>
-
-#if defined(_WIN32)
-#  include <Windows.h>
-#else
-#  include <dlfcn.h>
-#endif
-
-#include "Dynlib.h"
-
-#if defined(_WIN32)
-
-namespace {
-
-std::string systemError()
-{
-	LPSTR error = nullptr;
-	std::string errmsg = "Unknown error";
-
-	FormatMessageA(
-		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-		NULL,
-		GetLastError(),
-		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		(LPSTR)&error, 0, NULL);
-
-	if (error) {
-		errmsg = std::string(error);
-		LocalFree(error);
-	}
-
-	return errmsg;
-}
-
-}
-
-void Dynlib::systemInit()
-{
-	m_handle = nullptr;
-}
-
-Dynlib::Handle Dynlib::systemLoad(const std::string &path, Policy) const
-{
-	Handle handle = LoadLibraryA(path.c_str());
-
-	if (handle == nullptr)
-		throw std::runtime_error(systemError());
-
-	return handle;
-}
-
-Dynlib::Sym Dynlib::systemSym(const std::string &name)
-{
-	Sym sym;
-
-	if (m_handle == nullptr)
-		throw std::runtime_error("library not loaded");
-
-	sym = GetProcAddress(m_handle, name.c_str());
-	if (sym == nullptr)
-		throw std::out_of_range(systemError());
-
-	return sym;
-}
-
-void Dynlib::systemClose()
-{
-	if (m_handle != nullptr)
-		FreeLibrary(m_handle);
-}
-
-#else
-
-void Dynlib::systemInit()
-{
-	m_handle = nullptr;
-}
-
-Dynlib::Handle Dynlib::systemLoad(const std::string &path, Policy policy) const
-{
-	int mode = (policy == Immediately) ? RTLD_NOW : RTLD_LAZY;
-	Handle handle;
-
-	handle = dlopen(path.c_str(), mode);
-	if (handle == nullptr)
-		throw std::runtime_error(dlerror());
-
-	return handle;
-}
-
-Dynlib::Sym Dynlib::systemSym(const std::string &name)
-{
-	Sym sym;
-
-	if (m_handle == nullptr)
-		throw std::runtime_error("library not loaded");
-
-	sym = dlsym(m_handle, name.c_str());
-	if (sym == nullptr)
-		throw std::out_of_range(dlerror());
-
-	return sym;
-}
-
-void Dynlib::systemClose()
-{
-	if (m_handle != nullptr)
-		dlclose(m_handle);
-}
-
-#endif
-
-Dynlib::Dynlib()
-{
-	systemInit();
-}
-
-Dynlib::Dynlib(const std::string &path, Policy policy)
-{
-	m_handle = systemLoad(path, policy);
-}
-
-Dynlib::~Dynlib()
-{
-	systemClose();
-}
--- a/C++/modules/Dynlib/Dynlib.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * DynLib.h -- portable shared library loader
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _DYNLIB_H_
-#define _DYNLIB_H_
-
-#include <string>
-
-#if defined(_WIN32)
-#  include <Windows.h>
-#  define DYNLIB_EXPORT	__declspec(dllexport)
-#else
-#  define DYNLIB_EXPORT
-#endif
-
-/**
- * @class Dynlib
- * @brief Load a dynamic module
- *
- * This class is a portable wrapper to load shared libraries on
- * supported systems.
- */
-class Dynlib {
-public:
-#if defined(_WIN32)
-	using Handle	= HMODULE;
-	using Sym	= FARPROC;
-#else
-	using Handle	= void *;
-	using Sym	= void *;
-#endif
-
-	enum Policy {
-		Immediately,		//! load symbols immediately
-		Lazy			//! load symbols when needed
-	};
-
-private:
-	Handle	m_handle;
-
-	void	systemInit();
-	Handle	systemLoad(const std::string &path, Policy policy) const;
-	Sym	systemSym(const std::string &name);
-	void	systemClose();
-
-public:
-	/**
-	 * Copy is forbidden.
-	 */
-	Dynlib(const Dynlib &) = delete;
-	Dynlib &operator=(const Dynlib &) = delete;
-
-	/**
-	 * Default constructor.
-	 */
-	Dynlib();
-
-	/**
-	 * Constructor to load a shared module. The path must
-	 * be absolute.
-	 *
-	 * @param path the absolute path
-	 * @param policy the policy to load
-	 * @throw std::runtime_error on error
-	 */
-	Dynlib(const std::string &path, Policy policy = Immediately);
-
-	/**
-	 * Close the library automatically.
-	 */
-	~Dynlib();
-
-	/**
-	 * Get a symbol from the library.
-	 *
-	 * @param name the symbol
-	 * @return the symbol
-	 * @throw std::runtime_error on error
-	 * @throw std::out_of_range if not found
-	 */
-	template <typename T>
-	T sym(const std::string &name)
-	{
-		return reinterpret_cast<T>(systemSym(name));
-	}
-};
-
-#endif // !_DYNLIB_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Dynlib/dynlib.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,144 @@
+/*
+ * dynlib.cpp -- portable shared library loader
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdexcept>
+
+#if defined(_WIN32)
+#  include <Windows.h>
+#else
+#  include <dlfcn.h>
+#endif
+
+#include "dynlib.h"
+
+#if defined(_WIN32)
+
+namespace {
+
+std::string systemError()
+{
+	LPSTR error = nullptr;
+	std::string errmsg = "Unknown error";
+
+	FormatMessageA(
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,
+		GetLastError(),
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPSTR)&error, 0, NULL);
+
+	if (error) {
+		errmsg = std::string(error);
+		LocalFree(error);
+	}
+
+	return errmsg;
+}
+
+}
+
+void Dynlib::systemInit()
+{
+	m_handle = nullptr;
+}
+
+Dynlib::Handle Dynlib::systemLoad(const std::string &path, Policy) const
+{
+	Handle handle = LoadLibraryA(path.c_str());
+
+	if (handle == nullptr)
+		throw std::runtime_error(systemError());
+
+	return handle;
+}
+
+Dynlib::Sym Dynlib::systemSym(const std::string &name)
+{
+	Sym sym;
+
+	if (m_handle == nullptr)
+		throw std::runtime_error("library not loaded");
+
+	sym = GetProcAddress(m_handle, name.c_str());
+	if (sym == nullptr)
+		throw std::out_of_range(systemError());
+
+	return sym;
+}
+
+void Dynlib::systemClose()
+{
+	if (m_handle != nullptr)
+		FreeLibrary(m_handle);
+}
+
+#else
+
+void Dynlib::systemInit()
+{
+	m_handle = nullptr;
+}
+
+Dynlib::Handle Dynlib::systemLoad(const std::string &path, Policy policy) const
+{
+	int mode = (policy == Immediately) ? RTLD_NOW : RTLD_LAZY;
+	Handle handle;
+
+	handle = dlopen(path.c_str(), mode);
+	if (handle == nullptr)
+		throw std::runtime_error(dlerror());
+
+	return handle;
+}
+
+Dynlib::Sym Dynlib::systemSym(const std::string &name)
+{
+	Sym sym;
+
+	if (m_handle == nullptr)
+		throw std::runtime_error("library not loaded");
+
+	sym = dlsym(m_handle, name.c_str());
+	if (sym == nullptr)
+		throw std::out_of_range(dlerror());
+
+	return sym;
+}
+
+void Dynlib::systemClose()
+{
+	if (m_handle != nullptr)
+		dlclose(m_handle);
+}
+
+#endif
+
+Dynlib::Dynlib()
+{
+	systemInit();
+}
+
+Dynlib::Dynlib(const std::string &path, Policy policy)
+{
+	m_handle = systemLoad(path, policy);
+}
+
+Dynlib::~Dynlib()
+{
+	systemClose();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Dynlib/dynlib.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,103 @@
+/*
+ * dynlib.h -- portable shared library loader
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DYNLIB_H_
+#define _DYNLIB_H_
+
+#include <string>
+
+#if defined(_WIN32)
+#  include <Windows.h>
+#  define DYNLIB_EXPORT	__declspec(dllexport)
+#else
+#  define DYNLIB_EXPORT
+#endif
+
+/**
+ * @class Dynlib
+ * @brief Load a dynamic module
+ *
+ * This class is a portable wrapper to load shared libraries on
+ * supported systems.
+ */
+class Dynlib {
+public:
+#if defined(_WIN32)
+	using Handle	= HMODULE;
+	using Sym	= FARPROC;
+#else
+	using Handle	= void *;
+	using Sym	= void *;
+#endif
+
+	enum Policy {
+		Immediately,		//! load symbols immediately
+		Lazy			//! load symbols when needed
+	};
+
+private:
+	Handle	m_handle;
+
+	void	systemInit();
+	Handle	systemLoad(const std::string &path, Policy policy) const;
+	Sym	systemSym(const std::string &name);
+	void	systemClose();
+
+public:
+	/**
+	 * Copy is forbidden.
+	 */
+	Dynlib(const Dynlib &) = delete;
+	Dynlib &operator=(const Dynlib &) = delete;
+
+	/**
+	 * Default constructor.
+	 */
+	Dynlib();
+
+	/**
+	 * Constructor to load a shared module. The path must
+	 * be absolute.
+	 *
+	 * @param path the absolute path
+	 * @param policy the policy to load
+	 * @throw std::runtime_error on error
+	 */
+	Dynlib(const std::string &path, Policy policy = Immediately);
+
+	/**
+	 * Close the library automatically.
+	 */
+	~Dynlib();
+
+	/**
+	 * Get a symbol from the library.
+	 *
+	 * @param name the symbol
+	 * @return the symbol
+	 * @throw std::runtime_error on error
+	 * @throw std::out_of_range if not found
+	 */
+	template <typename T>
+	T sym(const std::string &name)
+	{
+		return reinterpret_cast<T>(systemSym(name));
+	}
+};
+
+#endif // !_DYNLIB_H_
--- a/C++/modules/Format/Format.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Format.cpp -- convenient function for formatting text with escape sequences
- *
- * Copyright (c) 2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <array>
-#include <sstream>
-#include <unordered_map>
-
-#include "Format.h"
-
-namespace fmt {
-
-namespace {
-
-const std::array<unsigned char, 17> colorsTable{
-	0,	// Default
-	30,	// Black
-	31,	// Red
-	32,	// Green
-	33,	// Yellow
-	34,	// Blue
-	35,	// Magenta
-	36,	// Cyan
-	37,	// Light gray
-	90,	// Dark gray
-	91,	// Light red
-	92,	// Light green
-	93,	// Light yellow
-	94,	// Light blue
-	95,	// Light cyan
-	96,	// White
-	97	
-};
-
-const std::unordered_map<int, int> attributesTable{
-	{ Bold,		1 },
-	{ Dim,		2 },
-	{ Underline,	4 },
-	{ Blink,	5 },
-	{ Reverse,	7 },
-	{ Hidden,	8 }
-};
-
-} // !namespace
-
-std::string convert(std::string input, unsigned short flags)
-{
-	std::ostringstream oss;
-
-#if !defined(_WIN32)
-	// Attributes
-	for (const auto &pair : attributesTable) {
-		if (flags & pair.first) {
-			oss << "\033[" << pair.second << "m";
-		}
-	}
-
-	// Background
-	if (((flags >> 11) & 0x3f) != Default) {
-		oss << "\033[" << std::to_string(colorsTable[static_cast<unsigned char>((flags >> 11) & 0x3f)] + 10) << "m";
-	}
-
-	// Foreground
-	if (((flags >> 6) & 0x3f) != Default) {
-		oss << "\033[" << std::to_string(colorsTable[static_cast<unsigned char>((flags >> 6) & 0x3f)]) << "m";
-	}
-
-	oss << std::move(input) << "\033[0m";
-#else
-	oss << std::move(input);
-#endif
-
-	return oss.str();
-}
-
-} // !fmt
--- a/C++/modules/Format/Format.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Format.h -- convenient function for formatting text with escape sequences
- *
- * Copyright (c) 2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _FORMAT_H_
-#define _FORMAT_H_
-
-#include <string>
-
-/**
- * Format namespace.
- */
-namespace fmt {
-
-/**
- * Enumeration of supported colors.
- */
-enum Color {
-	Default	= 0,
-	Black,
-	Red,
-	Green,
-	Yellow,
-	Blue,
-	Magenta,
-	Cyan,
-	LightGray,
-	DarkGray,
-	LightRed,
-	LightGreen,
-	LightYellow,
-	LightBlue,
-	LightMagenta,
-	LightCyan,
-	White
-};
-
-/**
- * Enumeration of supported attributes.
- */
-enum Attributes {
-	None		= 0,
-	Bold		= (1 << 0),	//! [1m
-	Dim		= (1 << 1),	//! [2m
-	Underline	= (1 << 2),	//! [4m
-	Blink		= (1 << 3),	//! [5m
-	Reverse		= (1 << 4),	//! [7m
-	Hidden		= (1 << 5)	//! [8m
-};
-
-/**
- * Create a mask for the foreground color.
- *
- * @param color the foreground color
- * @return the correct mask
- */
-constexpr unsigned short fg(unsigned short color) noexcept
-{
-	return color << 6;
-}
-
-/**
- * Create a mask for the background color.
- *
- * @param color the background color
- * @return the correct mask
- */
-constexpr unsigned short bg(unsigned short color) noexcept
-{
-	return color << 11;
-}
-
-/**
- * Return a formatted string with escape sequences. The string is terminated with reset sequence.
- *
- * Flags is defined as following:
- *
- * b b b b b f f f | f f a a a a a a
- *
- * Where:
- *   - b is the background color
- *   - g is the foreground color
- *   - a are attributes
- *
- * The attributes and colors are OR'ed together and to specify the background or foreground
- * you must use the dedicated fg() and bg() functions.
- *
- * @param input the input string
- * @param flags the flags
- * @return the formatted string
- * @example convert(fg(Red) | bg(White) | Bold | Underline);
- */
-std::string convert(std::string input, unsigned short flags);
-
-} // !fmt
-
-#endif // !_FORMAT_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Format/format.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,90 @@
+/*
+ * format.cpp -- convenient function for formatting text with escape sequences
+ *
+ * Copyright (c) 2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <array>
+#include <sstream>
+#include <unordered_map>
+
+#include "format.h"
+
+namespace fmt {
+
+namespace {
+
+const std::array<unsigned char, 17> colorsTable{
+	0,	// Default
+	30,	// Black
+	31,	// Red
+	32,	// Green
+	33,	// Yellow
+	34,	// Blue
+	35,	// Magenta
+	36,	// Cyan
+	37,	// Light gray
+	90,	// Dark gray
+	91,	// Light red
+	92,	// Light green
+	93,	// Light yellow
+	94,	// Light blue
+	95,	// Light cyan
+	96,	// White
+	97	
+};
+
+const std::unordered_map<int, int> attributesTable{
+	{ Bold,		1 },
+	{ Dim,		2 },
+	{ Underline,	4 },
+	{ Blink,	5 },
+	{ Reverse,	7 },
+	{ Hidden,	8 }
+};
+
+} // !namespace
+
+std::string convert(std::string input, unsigned short flags)
+{
+	std::ostringstream oss;
+
+#if !defined(_WIN32)
+	// Attributes
+	for (const auto &pair : attributesTable) {
+		if (flags & pair.first) {
+			oss << "\033[" << pair.second << "m";
+		}
+	}
+
+	// Background
+	if (((flags >> 11) & 0x3f) != Default) {
+		oss << "\033[" << std::to_string(colorsTable[static_cast<unsigned char>((flags >> 11) & 0x3f)] + 10) << "m";
+	}
+
+	// Foreground
+	if (((flags >> 6) & 0x3f) != Default) {
+		oss << "\033[" << std::to_string(colorsTable[static_cast<unsigned char>((flags >> 6) & 0x3f)]) << "m";
+	}
+
+	oss << std::move(input) << "\033[0m";
+#else
+	oss << std::move(input);
+#endif
+
+	return oss.str();
+}
+
+} // !fmt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Format/format.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,111 @@
+/*
+ * format.h -- convenient function for formatting text with escape sequences
+ *
+ * Copyright (c) 2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _FORMAT_H_
+#define _FORMAT_H_
+
+#include <string>
+
+/**
+ * Format namespace.
+ */
+namespace fmt {
+
+/**
+ * Enumeration of supported colors.
+ */
+enum Color {
+	Default	= 0,
+	Black,
+	Red,
+	Green,
+	Yellow,
+	Blue,
+	Magenta,
+	Cyan,
+	LightGray,
+	DarkGray,
+	LightRed,
+	LightGreen,
+	LightYellow,
+	LightBlue,
+	LightMagenta,
+	LightCyan,
+	White
+};
+
+/**
+ * Enumeration of supported attributes.
+ */
+enum Attributes {
+	None		= 0,
+	Bold		= (1 << 0),	//! [1m
+	Dim		= (1 << 1),	//! [2m
+	Underline	= (1 << 2),	//! [4m
+	Blink		= (1 << 3),	//! [5m
+	Reverse		= (1 << 4),	//! [7m
+	Hidden		= (1 << 5)	//! [8m
+};
+
+/**
+ * Create a mask for the foreground color.
+ *
+ * @param color the foreground color
+ * @return the correct mask
+ */
+constexpr unsigned short fg(unsigned short color) noexcept
+{
+	return color << 6;
+}
+
+/**
+ * Create a mask for the background color.
+ *
+ * @param color the background color
+ * @return the correct mask
+ */
+constexpr unsigned short bg(unsigned short color) noexcept
+{
+	return color << 11;
+}
+
+/**
+ * Return a formatted string with escape sequences. The string is terminated with reset sequence.
+ *
+ * Flags is defined as following:
+ *
+ * b b b b b f f f | f f a a a a a a
+ *
+ * Where:
+ *   - b is the background color
+ *   - g is the foreground color
+ *   - a are attributes
+ *
+ * The attributes and colors are OR'ed together and to specify the background or foreground
+ * you must use the dedicated fg() and bg() functions.
+ *
+ * @param input the input string
+ * @param flags the flags
+ * @return the formatted string
+ * @example convert(fg(Red) | bg(White) | Bold | Underline);
+ */
+std::string convert(std::string input, unsigned short flags);
+
+} // !fmt
+
+#endif // !_FORMAT_H_
--- a/C++/modules/Hash/Hash.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Hash.cpp -- hash functions
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "Hash.h"
-
-#include <openssl/sha.h>
-#include <openssl/md5.h>
-
-namespace hash {
-
-namespace {
-
-template <typename Context>
-using Init	= int (*)(Context *);
-
-template <typename Context>
-using Update	= int (*)(Context *, const void *, size_t);
-
-template <typename Context>
-using Final	= int (*)(unsigned char *, Context *);
-
-template <typename Context, size_t Length>
-std::string convert(const std::string &input, Init<Context> init, Update<Context> update, Final<Context> finalize)
-{
-	unsigned char digest[Length];
-	char hash[Length * 2 + 1];
-	
-	Context ctx;
-	init(&ctx);
-	update(&ctx, input.c_str(), input.length());
-	finalize(digest, &ctx);
-	
-	for (unsigned long i = 0; i < Length; i++)
-		sprintf(&hash[i * 2], "%02x", (unsigned int)digest[i]);
-	
-	return std::string(hash);
-}
-
-} // !namespace
-
-std::string md5(const std::string &input)
-{
-	return convert<MD5_CTX, MD5_DIGEST_LENGTH>(input, MD5_Init, MD5_Update, MD5_Final);
-}
-
-std::string sha1(const std::string &input)
-{
-	return convert<SHA_CTX, SHA_DIGEST_LENGTH>(input, SHA1_Init, SHA1_Update, SHA1_Final);
-}
-
-std::string sha256(const std::string &input)
-{
-	return convert<SHA256_CTX, SHA256_DIGEST_LENGTH>(input, SHA256_Init, SHA256_Update, SHA256_Final);
-}
-
-std::string sha512(const std::string &input)
-{
-	return convert<SHA512_CTX, SHA512_DIGEST_LENGTH>(input, SHA512_Init, SHA512_Update, SHA512_Final);
-}
-
-} // !hash
--- a/C++/modules/Hash/Hash.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Hash.h -- hash functions
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _HASH_H_
-#define _HASH_H_
-
-/**
- * @file Hash.h
- * @brief Hash functions
- */
-
-#include <string>
-
-namespace hash {
-
-/**
- * Hash using MD5.
- *
- * @param input the input string
- * @return the hashed string
- */
-std::string md5(const std::string &input);
-
-/**
- * Hash using SHA1.
- *
- * @param input the input string
- * @return the hashed string
- */
-std::string sha1(const std::string &input);
-
-/**
- * Hash using SHA256.
- *
- * @param input the input string
- * @return the hashed string
- */
-std::string sha256(const std::string &input);
-
-/**
- * Hash using SHA512.
- *
- * @param input the input string
- * @return the hashed string
- */
-std::string sha512(const std::string &input);
-
-} // !hash
-
-#endif // !_HASH_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Hash/hash.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,76 @@
+/*
+ * hash.cpp -- hash functions
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hash.h"
+
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+
+namespace hash {
+
+namespace {
+
+template <typename Context>
+using Init	= int (*)(Context *);
+
+template <typename Context>
+using Update	= int (*)(Context *, const void *, size_t);
+
+template <typename Context>
+using Final	= int (*)(unsigned char *, Context *);
+
+template <typename Context, size_t Length>
+std::string convert(const std::string &input, Init<Context> init, Update<Context> update, Final<Context> finalize)
+{
+	unsigned char digest[Length];
+	char hash[Length * 2 + 1];
+	
+	Context ctx;
+	init(&ctx);
+	update(&ctx, input.c_str(), input.length());
+	finalize(digest, &ctx);
+	
+	for (unsigned long i = 0; i < Length; i++)
+		sprintf(&hash[i * 2], "%02x", (unsigned int)digest[i]);
+	
+	return std::string(hash);
+}
+
+} // !namespace
+
+std::string md5(const std::string &input)
+{
+	return convert<MD5_CTX, MD5_DIGEST_LENGTH>(input, MD5_Init, MD5_Update, MD5_Final);
+}
+
+std::string sha1(const std::string &input)
+{
+	return convert<SHA_CTX, SHA_DIGEST_LENGTH>(input, SHA1_Init, SHA1_Update, SHA1_Final);
+}
+
+std::string sha256(const std::string &input)
+{
+	return convert<SHA256_CTX, SHA256_DIGEST_LENGTH>(input, SHA256_Init, SHA256_Update, SHA256_Final);
+}
+
+std::string sha512(const std::string &input)
+{
+	return convert<SHA512_CTX, SHA512_DIGEST_LENGTH>(input, SHA512_Init, SHA512_Update, SHA512_Final);
+}
+
+} // !hash
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Hash/hash.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,65 @@
+/*
+ * hash.h -- hash functions
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HASH_H_
+#define _HASH_H_
+
+/**
+ * @file hash.h
+ * @brief Hash functions
+ */
+
+#include <string>
+
+namespace hash {
+
+/**
+ * Hash using MD5.
+ *
+ * @param input the input string
+ * @return the hashed string
+ */
+std::string md5(const std::string &input);
+
+/**
+ * Hash using SHA1.
+ *
+ * @param input the input string
+ * @return the hashed string
+ */
+std::string sha1(const std::string &input);
+
+/**
+ * Hash using SHA256.
+ *
+ * @param input the input string
+ * @return the hashed string
+ */
+std::string sha256(const std::string &input);
+
+/**
+ * Hash using SHA512.
+ *
+ * @param input the input string
+ * @return the hashed string
+ */
+std::string sha512(const std::string &input);
+
+} // !hash
+
+#endif // !_HASH_H_
--- a/C++/modules/Ini/Ini.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,445 +0,0 @@
-/*
- * Ini.cpp -- .ini file parsing
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <cctype>
-#include <cstring>
-#include <iostream>
-#include <iterator>
-#include <fstream>
-#include <sstream>
-#include <stdexcept>
-
-#if defined(_WIN32)
-#  include <Shlwapi.h>	// for PathIsRelative
-#endif
-
-#include "Ini.h"
-
-namespace {
-
-using namespace ini;
-
-using StreamIterator = std::istreambuf_iterator<char>;
-using TokenIterator = std::vector<Token>::const_iterator;
-
-inline bool isAbsolute(const std::string &path) noexcept
-{
-#if defined(_WIN32)
-	return !PathIsRelative(path.c_str());
-#else
-	return path.size() > 0 && path[0] == '/';
-#endif
-}
-
-inline bool isQuote(char c) noexcept
-{
-	return c == '\'' || c == '"';
-}
-
-inline bool isSpace(char c) noexcept
-{
-	/* Custom version because std::isspace includes \n as space */
-	return c == ' ' || c == '\t';
-}
-
-inline bool isList(char c) noexcept
-{
-	return c == '(' || c == ')' || c == ',';
-}
-
-inline bool isReserved(char c) noexcept
-{
-	return isList(c) || isQuote(c) || c == '[' || c == ']' || c == '@' || c == '#' || c == '=';
-}
-
-void analyzeLine(int &line, int &column, StreamIterator &it) noexcept
-{
-	assert(*it == '\n');
-
-	++ line;
-	++ it;
-	column = 0;
-}
-
-void analyzeComment(int &column, StreamIterator &it, StreamIterator end) noexcept
-{
-	assert(*it == '#');
-
-	while (it != end && *it != '\n') {
-		++ column;
-		++ it;
-	}
-}
-
-void analyzeSpaces(int &column, StreamIterator &it, StreamIterator end) noexcept
-{
-	assert(isSpace(*it));
-
-	while (it != end && isSpace(*it)) {
-		++ column;
-		++ it;
-	}
-}
-
-void analyzeList(Tokens &list, int line, int &column, StreamIterator &it) noexcept
-{
-	assert(isList(*it));
-
-	switch (*it++) {
-	case '(':
-		list.emplace_back(Token::ListBegin, line, column++);
-		break;
-	case ')':
-		list.emplace_back(Token::ListEnd, line, column++);
-		break;
-	case ',':
-		list.emplace_back(Token::Comma, line, column++);
-		break;
-	default:
-		break;
-	}
-}
-
-void analyzeSection(Tokens &list, int &line, int &column, StreamIterator &it, StreamIterator end)
-{
-	assert(*it == '[');
-
-	std::string value;
-	int save = column;
-
-	/* Read section name */
-	++ it;
-	while (it != end && *it != ']') {
-		if (*it == '\n') {
-			throw Error{line, column, "section not terminated, missing ']'"};
-		}
-		if (isReserved(*it)) {
-			throw Error{line, column, "section name expected after '[', got '" + std::string(1, *it) + "'"};
-		}
-		++ column;
-		value += *it++;
-	}
-
-	if (it == end) {
-		throw Error{line, column, "section name expected after '[', got <EOF>"};
-	}
-	if (value.empty()) {
-		throw Error{line, column, "empty section name"};
-	}
-
-	/* Remove ']' */
-	++ it;
-
-	list.emplace_back(Token::Section, line, save, std::move(value));
-}
-
-void analyzeAssign(Tokens &list, int &line, int &column, StreamIterator &it)
-{
-	assert(*it == '=');
-
-	list.push_back({ Token::Assign, line, column++ });
-	++ it;
-}
-
-void analyzeQuotedWord(Tokens &list, int &line, int &column, StreamIterator &it, StreamIterator end)
-{
-	std::string value;
-	int save = column;
-	char quote = *it++;
-
-	while (it != end && *it != quote) {
-		// TODO: escape sequence
-		++ column;
-		value += *it++;
-	}
-
-	if (it == end) {
-		throw Error{line, column, "undisclosed '" + std::string(1, quote) + "', got <EOF>"};
-	}
-
-	/* Remove quote */
-	++ it;
-
-	list.push_back({ Token::QuotedWord, line, save, std::move(value) });
-}
-
-void analyzeWord(Tokens &list, int &line, int &column, StreamIterator &it, StreamIterator end)
-{
-	assert(!isReserved(*it));
-
-	std::string value;
-	int save = column;
-
-	while (it != end && !std::isspace(*it) && !isReserved(*it)) {
-		++ column;
-		value += *it++;
-	}
-
-	list.push_back({ Token::Word, line, save, std::move(value) });
-}
-
-void analyzeInclude(Tokens &list, int &line, int &column, StreamIterator &it, StreamIterator end)
-{
-	assert(*it == '@');
-
-	std::string include;
-	int save = column;
-
-	/* Read include */
-	++ it;
-	while (it != end && !isSpace(*it)) {
-		++ column;
-		include += *it++;
-	}
-
-	if (include != "include") {
-		throw Error{line, column, "expected include after '@' token"};
-	}
-
-	list.push_back({ Token::Include, line, save });
-}
-
-Tokens analyze(StreamIterator &it, StreamIterator end)
-{
-	Tokens list;
-	int line = 1;
-	int column = 0;
-
-	while (it != end) {
-		if (*it == '\n') {
-			analyzeLine(line, column, it);
-		} else if (*it == '#') {
-			analyzeComment(column, it, end);
-		} else if (*it == '[') {
-			analyzeSection(list, line, column, it, end);
-		} else if (*it == '=') {
-			analyzeAssign(list, line, column, it);
-		} else if (isSpace(*it)) {
-			analyzeSpaces(column, it, end);
-		} else if (*it == '@') {
-			analyzeInclude(list, line, column, it, end);
-		} else if (isQuote(*it)) {
-			analyzeQuotedWord(list, line, column, it, end);
-		} else if (isList(*it)) {
-			analyzeList(list, line, column, it);
-		} else {
-			analyzeWord(list, line, column, it, end);
-		}
-	}
-
-	return list;
-}
-
-void parseOptionValueSimple(Option &option, TokenIterator &it)
-{
-	assert(it->type() == Token::Word || it->type() == Token::QuotedWord);
-
-	option.push_back((it++)->value());
-}
-
-void parseOptionValueList(Option &option, TokenIterator &it, TokenIterator end)
-{
-	assert(it->type() == Token::ListBegin);
-
-	TokenIterator save = it++;
-
-	while (it != end && it->type() != Token::ListEnd) {
-		switch (it->type()) {
-		case Token::Comma:
-			/* Previous must be a word */
-			if (it[-1].type() != Token::Word && it[-1].type() != Token::QuotedWord) {
-				throw Error{it->line(), it->column(), "unexpected comma after '" + it[-1].value() + "'"};
-			}
-
-			++ it;
-			break;
-		case Token::Word:
-		case Token::QuotedWord:
-			option.push_back((it++)->value());
-			break;
-		default:
-			throw Error{it->line(), it->column(), "unexpected '" + it[-1].value() + "' in list construct"};
-			break;
-		}
-	}
-
-	if (it == end) {
-		throw Error{save->line(), save->column(), "unterminated list construct"};
-	}
-
-	/* Remove ) */
-	++ it;
-}
-
-void parseOption(Section &sc, TokenIterator &it, TokenIterator end)
-{
-	Option option{it->value()};
-
-	TokenIterator save = it;
-
-	/* No '=' or something else? */
-	if (++it == end) {
-		throw Error{save->line(), save->column(), "expected '=' assignment, got <EOF>"};
-	}
-	if (it->type() != Token::Assign) {
-		throw Error{it->line(), it->column(), "expected '=' assignment, got " + it->value()};
-	}
-
-	/* Empty options are allowed so just test for words */
-	if (++it != end) {
-		if (it->type() == Token::Word || it->type() == Token::QuotedWord) {
-			parseOptionValueSimple(option, it);
-		} else if (it->type() == Token::ListBegin) {
-			parseOptionValueList(option, it, end);
-		}
-	}
-
-	sc.push_back(std::move(option));
-}
-
-void parseInclude(Document &doc, TokenIterator &it, TokenIterator end)
-{
-	TokenIterator save = it;
-
-	if (++it == end) {
-		throw Error{save->line(), save->column(), "expected file name after '@include' statement, got <EOF>"};
-	}
-
-	if (it->type() != Token::Word && it->type() != Token::QuotedWord) {
-		throw Error{it->line(), it->column(), "expected file name after '@include' statement, got " + it->value()};
-	}
-
-	if (doc.path().empty()) {
-		throw Error{it->line(), it->column(), "'@include' statement invalid with buffer documents"};
-	}
-
-	std::string value = (it++)->value();
-	std::string file;
-
-	if (!isAbsolute(value)) {
-#if defined(_WIN32)
-		file = doc.path() + "\\" + value;
-#else
-		file = doc.path() + "/" + value;
-#endif
-	} else {
-		file = value;
-	}
-
-	Document child{File{file}};
-
-	for (const auto &sc : child) {
-		doc.push_back(sc);
-	}
-}
-
-void parseSection(Document &doc, TokenIterator &it, TokenIterator end)
-{
-	Section sc{it->value()};
-
-	/* Skip [section] */
-	++ it;
-
-	/* Read until next section */
-	while (it != end && it->type() != Token::Section) {
-		if (it->type() != Token::Word) {
-			throw Error{it->line(), it->column(), "unexpected token '" + it->value() + "' in section definition"};
-		}
-
-		parseOption(sc, it, end);
-	}
-
-	doc.push_back(std::move(sc));
-}
-
-void parse(Document &doc, const Tokens &tokens)
-{
-	TokenIterator it = tokens.cbegin();
-	TokenIterator end = tokens.cend();
-
-	while (it != end) {
-		/* Just ignore this */
-		switch (it->type()) {
-		case Token::Include:
-			parseInclude(doc, it, end);
-			break;
-		case Token::Section:
-			parseSection(doc, it, end);
-			break;
-		default:
-			throw Error{it->line(), it->column(), "unexpected '" + it->value() + "' on root document"};
-		}
-	}
-}
-
-} // !namespace
-
-namespace ini {
-
-Tokens Document::analyze(const File &file)
-{
-	std::fstream stream{file.path};
-
-	if (!stream) {
-		throw std::runtime_error{std::strerror(errno)};
-	}
-
-	std::istreambuf_iterator<char> it{stream};
-	std::istreambuf_iterator<char> end{};
-
-	return ::analyze(it, end);
-}
-
-Tokens Document::analyze(const Buffer &buffer)
-{
-	std::istringstream stream{buffer.text};
-	std::istreambuf_iterator<char> it{stream};
-	std::istreambuf_iterator<char> end{};
-
-	return ::analyze(it, end);
-}
-
-Document::Document(const File &file)
-	: m_path{file.path}
-{
-	/* Update path */
-	auto pos = m_path.find_last_of("/\\");
-
-	if (pos != std::string::npos) {
-		m_path.erase(pos);
-	} else {
-		m_path = ".";
-	}
-
-	parse(*this, analyze(file));
-}
-
-Document::Document(const Buffer &buffer)
-{
-	parse(*this, analyze(buffer));
-}
-
-void Document::dump(const Tokens &tokens)
-{
-	for (const Token &token: tokens) {
-		// TODO: add better description
-		std::cout << token.line() << ":" << token.column() << ": " << token.value() << std::endl;
-	}
-}
-
-} // !ini
--- a/C++/modules/Ini/Ini.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,546 +0,0 @@
-/*
- * Ini.h -- .ini file parsing
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _INI_H_
-#define _INI_H_
-
-/**
- * @file Ini.h
- * @brief Configuration file parser.
- */
-
-#include <algorithm>
-#include <cassert>
-#include <exception>
-#include <stdexcept>
-#include <string>
-#include <vector>
-
-/**
- * Namespace for ini related classes.
- */
-namespace ini {
-
-class Document;
-
-/**
- * @class Error
- * @brief Error in a file
- */
-class Error : public std::exception {
-private:
-	int m_line;		//!< line number
-	int m_column;		//!< line column
-	std::string m_message;	//!< error message
-
-public:
-	/**
-	 * Constructor.
-	 *
-	 * @param l the line
-	 * @param c the column
-	 * @param m the message
-	 */
-	inline Error(int l, int c, std::string m) noexcept
-		: m_line{l}
-		, m_column{c}
-		, m_message{std::move(m)}
-	{
-	}
-
-	/**
-	 * Get the line number.
-	 *
-	 * @return the line
-	 */
-	inline int line() const noexcept
-	{
-		return m_line;
-	}
-
-	/**
-	 * Get the column number.
-	 *
-	 * @return the column
-	 */
-	inline int column() const noexcept
-	{
-		return m_column;
-	}
-
-	/**
-	 * Return the raw error message (no line and column shown).
-	 *
-	 * @return the error message
-	 */
-	const char *what() const noexcept override
-	{
-		return m_message.c_str();
-	}
-};
-
-/**
- * @class Token
- * @brief Describe a token read in the .ini source
- *
- * This class can be used when you want to parse a .ini file yourself.
- *
- * @see Document::analyze
- */
-class Token {
-public:
-	/**
-	 * @brief Token type
-	 */
-	enum Type {
-		Include,	//!< include statement
-		Section,	//!< [section]
-		Word,		//!< word without quotes
-		QuotedWord,	//!< word with quotes
-		Assign,		//!< = assignment
-		ListBegin,	//!< begin of list (
-		ListEnd,	//!< end of list )
-		Comma		//!< list separation
-	};
-
-private:
-	Type m_type;
-	int m_line;
-	int m_column;
-	std::string m_value;
-
-public:
-	/**
-	 * Construct a token.
-	 *
-	 * @param type the type
-	 * @param line the line
-	 * @param column the column
-	 * @param value the value
-	 */
-	Token(Type type, int line, int column, std::string value = "") noexcept
-		: m_type{type}
-		, m_line{line}
-		, m_column{column}
-	{
-		switch (type) {
-		case Include:
-			m_value = "@include";
-			break;
-		case Section:
-		case Word:
-		case QuotedWord:
-			m_value = value;
-			break;
-		case Assign:
-			m_value = "=";
-			break;
-		case ListBegin:
-			m_value = "(";
-			break;
-		case ListEnd:
-			m_value = ")";
-			break;
-		case Comma:
-			m_value = ",";
-			break;
-		default:
-			break;
-		}
-	}
-
-	/**
-	 * Get the type.
-	 *
-	 * @return the type
-	 */
-	inline Type type() const noexcept
-	{
-		return m_type;
-	}
-
-	/**
-	 * Get the line.
-	 *
-	 * @return the line
-	 */
-	inline int line() const noexcept
-	{
-		return m_line;
-	}
-
-	/**
-	 * Get the column.
-	 *
-	 * @return the column
-	 */
-	inline int column() const noexcept
-	{
-		return m_column;
-	}
-
-	/**
-	 * Get the value. For words, quoted words and section, the value is the content. Otherwise it's the
-	 * characters parsed.
-	 *
-	 * @return the value
-	 */
-	inline const std::string &value() const noexcept
-	{
-		return m_value;
-	}
-};
-
-/**
- * List of tokens in order they are analyzed.
- */
-using Tokens = std::vector<Token>;
-
-/**
- * @class Option
- * @brief Option definition.
- */
-class Option : public std::vector<std::string> {
-private:
-	std::string m_key;
-
-public:
-	/**
-	 * Construct an empty option.
-	 *
-	 * @param key the key
-	 * @param value the value
-	 */
-	inline Option(std::string key) noexcept
-		: std::vector<std::string>{}
-		, m_key{std::move(key)}
-	{
-	}
-
-	/**
-	 * Construct a single option.
-	 *
-	 * @param key the key
-	 * @param value the value
-	 */
-	inline Option(std::string key, std::string value) noexcept
-		: m_key{std::move(key)}
-	{
-		push_back(std::move(value));
-	}
-
-	/**
-	 * Construct a list option.
-	 *
-	 * @param key the key
-	 * @param values the values
-	 */
-	inline Option(std::string key, std::vector<std::string> values) noexcept
-		: std::vector<std::string>{std::move(values)}
-		, m_key{std::move(key)}
-	{
-	}
-
-	/**
-	 * Get the option key.
-	 *
-	 * @return the key
-	 */
-	inline const std::string &key() const noexcept
-	{
-		return m_key;
-	}
-
-	/**
-	 * Get the option value.
-	 *
-	 * @return the value
-	 */
-	inline const std::string &value() const noexcept
-	{
-		static std::string dummy;
-
-		return empty() ? dummy : (*this)[0];
-	}
-};
-
-/**
- * @class Section
- * @brief Section that contains one or more options.
- */
-class Section : public std::vector<Option> {
-private:
-	std::string m_key;
-
-public:
-	/**
-	 * Construct a section with its name.
-	 *
-	 * @param key the key
-	 * @pre key must not be empty
-	 */
-	inline Section(std::string key) noexcept
-		: m_key{std::move(key)}
-	{
-		assert(!m_key.empty());
-	}
-
-	/**
-	 * Get the section key.
-	 *
-	 * @return the key
-	 */
-	inline const std::string &key() const noexcept
-	{
-		return m_key;
-	}
-
-	/**
-	 * Check if the section contains a specific option.
-	 *
-	 * @param key the option key
-	 * @return true if the option exists
-	 */
-	inline bool contains(const std::string &key) const noexcept
-	{
-		return find(key) != end();
-	}
-
-	/**
-	 * Access an option at the specified key.
-	 *
-	 * @param key the key
-	 * @return the option
-	 * @pre contains(key) must return true
-	 */
-	inline Option &operator[](const std::string &key)
-	{
-		assert(contains(key));
-
-		return *find(key);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param key the key
-	 * @return the option
-	 * @pre contains(key) must return true
-	 */
-	inline const Option &operator[](const std::string &key) const
-	{
-		assert(contains(key));
-
-		return *find(key);
-	}
-
-	/**
-	 * Find an option by key and return an iterator.
-	 *
-	 * @param key the key
-	 * @return the iterator or end() if not found
-	 */
-	inline iterator find(const std::string &key) noexcept
-	{
-		return std::find_if(begin(), end(), [&] (const auto &o) {
-			return o.key() == key;
-		});
-	}
-
-	/**
-	 * Find an option by key and return an iterator.
-	 *
-	 * @param key the key
-	 * @return the iterator or end() if not found
-	 */
-	inline const_iterator find(const std::string &key) const noexcept
-	{
-		return std::find_if(cbegin(), cend(), [&] (const auto &o) {
-			return o.key() == key;
-		});
-	}
-
-	/**
-	 * Inherited operators.
-	 */
-	using std::vector<Option>::operator[];
-};
-
-/**
- * @class File
- * @brief Source for reading .ini files.
- */
-class File {
-public:
-	/**
-	 * Path to the file.
-	 */
-	std::string path;
-};
-
-/**
- * @class Buffer
- * @brief Source for reading ini from text.
- * @note the include statement is not supported with buffers.
- */
-class Buffer {
-public:
-	/**
-	 * The ini content.
-	 */
-	std::string text;
-};
-
-/**
- * @class Document
- * @brief Ini config file loader
- */
-class Document : public std::vector<Section> {
-private:
-	std::string m_path;
-
-public:
-	/**
-	 * Analyze a file and extract tokens. If the function succeeds, that does not mean the content is valid,
-	 * it just means that there are no syntax error.
-	 *
-	 * For example, this class does not allow adding options under no sections and this function will not
-	 * detect that issue.
-	 *
-	 * @param file the file to read
-	 * @return the list of tokens
-	 * @throws Error on errors
-	 */
-	static Tokens analyze(const File &file);
-
-	/**
-	 * Overloaded function for buffers.
-	 *
-	 * @param buffer the buffer to read
-	 * @return the list of tokens
-	 * @throws Error on errors
-	 */
-	static Tokens analyze(const Buffer &buffer);
-
-	/**
-	 * Show all tokens and their description.
-	 *
-	 * @param tokens the tokens
-	 */
-	static void dump(const Tokens &tokens);
-
-	/**
-	 * Construct a document from a file.
-	 *
-	 * @param file the file to read
-	 * @throws Error on errors
-	 */
-	Document(const File &file);
-
-	/**
-	 * Overloaded constructor for buffers.
-	 *
-	 * @param buffer the buffer to read
-	 * @throws Error on errors
-	 */
-	Document(const Buffer &buffer);
-
-	/**
-	 * Get the current document path, only useful when constructed from File source.
-	 *
-	 * @return the path
-	 */
-	inline const std::string &path() const noexcept
-	{
-		return m_path;
-	}
-
-	/**
-	 * Check if a document has a specific section.
-	 *
-	 * @param key the key
-	 * @return true if the document contains the section
-	 */
-	inline bool contains(const std::string &key) const noexcept
-	{
-		return std::find_if(begin(), end(), [&] (const auto &sc) { return sc.key() == key; }) != end();
-	}
-
-	/**
-	 * Access a section at the specified key.
-	 *
-	 * @param key the key
-	 * @return the section
-	 * @pre contains(key) must return true
-	 */
-	inline Section &operator[](const std::string &key)
-	{
-		assert(contains(key));
-
-		return *find(key);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param key the key
-	 * @return the section
-	 * @pre contains(key) must return true
-	 */
-	inline const Section &operator[](const std::string &key) const
-	{
-		assert(contains(key));
-
-		return *find(key);
-	}
-
-	/**
-	 * Find a section by key and return an iterator.
-	 *
-	 * @param key the key
-	 * @return the iterator or end() if not found
-	 */
-	inline iterator find(const std::string &key) noexcept
-	{
-		return std::find_if(begin(), end(), [&] (const auto &o) {
-			return o.key() == key;
-		});
-	}
-
-	/**
-	 * Find a section by key and return an iterator.
-	 *
-	 * @param key the key
-	 * @return the iterator or end() if not found
-	 */
-	inline const_iterator find(const std::string &key) const noexcept
-	{
-		return std::find_if(cbegin(), cend(), [&] (const auto &o) {
-			return o.key() == key;
-		});
-	}
-
-	/**
-	 * Inherited operators.
-	 */
-	using std::vector<Section>::operator[];
-};
-
-} // !ini
-
-#endif // !_INI_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Ini/ini.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,445 @@
+/*
+ * ini.cpp -- .ini file parsing
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cctype>
+#include <cstring>
+#include <iostream>
+#include <iterator>
+#include <fstream>
+#include <sstream>
+#include <stdexcept>
+
+#if defined(_WIN32)
+#  include <Shlwapi.h>	// for PathIsRelative
+#endif
+
+#include "ini.h"
+
+namespace {
+
+using namespace ini;
+
+using StreamIterator = std::istreambuf_iterator<char>;
+using TokenIterator = std::vector<Token>::const_iterator;
+
+inline bool isAbsolute(const std::string &path) noexcept
+{
+#if defined(_WIN32)
+	return !PathIsRelative(path.c_str());
+#else
+	return path.size() > 0 && path[0] == '/';
+#endif
+}
+
+inline bool isQuote(char c) noexcept
+{
+	return c == '\'' || c == '"';
+}
+
+inline bool isSpace(char c) noexcept
+{
+	/* Custom version because std::isspace includes \n as space */
+	return c == ' ' || c == '\t';
+}
+
+inline bool isList(char c) noexcept
+{
+	return c == '(' || c == ')' || c == ',';
+}
+
+inline bool isReserved(char c) noexcept
+{
+	return isList(c) || isQuote(c) || c == '[' || c == ']' || c == '@' || c == '#' || c == '=';
+}
+
+void analyzeLine(int &line, int &column, StreamIterator &it) noexcept
+{
+	assert(*it == '\n');
+
+	++ line;
+	++ it;
+	column = 0;
+}
+
+void analyzeComment(int &column, StreamIterator &it, StreamIterator end) noexcept
+{
+	assert(*it == '#');
+
+	while (it != end && *it != '\n') {
+		++ column;
+		++ it;
+	}
+}
+
+void analyzeSpaces(int &column, StreamIterator &it, StreamIterator end) noexcept
+{
+	assert(isSpace(*it));
+
+	while (it != end && isSpace(*it)) {
+		++ column;
+		++ it;
+	}
+}
+
+void analyzeList(Tokens &list, int line, int &column, StreamIterator &it) noexcept
+{
+	assert(isList(*it));
+
+	switch (*it++) {
+	case '(':
+		list.emplace_back(Token::ListBegin, line, column++);
+		break;
+	case ')':
+		list.emplace_back(Token::ListEnd, line, column++);
+		break;
+	case ',':
+		list.emplace_back(Token::Comma, line, column++);
+		break;
+	default:
+		break;
+	}
+}
+
+void analyzeSection(Tokens &list, int &line, int &column, StreamIterator &it, StreamIterator end)
+{
+	assert(*it == '[');
+
+	std::string value;
+	int save = column;
+
+	/* Read section name */
+	++ it;
+	while (it != end && *it != ']') {
+		if (*it == '\n') {
+			throw Error{line, column, "section not terminated, missing ']'"};
+		}
+		if (isReserved(*it)) {
+			throw Error{line, column, "section name expected after '[', got '" + std::string(1, *it) + "'"};
+		}
+		++ column;
+		value += *it++;
+	}
+
+	if (it == end) {
+		throw Error{line, column, "section name expected after '[', got <EOF>"};
+	}
+	if (value.empty()) {
+		throw Error{line, column, "empty section name"};
+	}
+
+	/* Remove ']' */
+	++ it;
+
+	list.emplace_back(Token::Section, line, save, std::move(value));
+}
+
+void analyzeAssign(Tokens &list, int &line, int &column, StreamIterator &it)
+{
+	assert(*it == '=');
+
+	list.push_back({ Token::Assign, line, column++ });
+	++ it;
+}
+
+void analyzeQuotedWord(Tokens &list, int &line, int &column, StreamIterator &it, StreamIterator end)
+{
+	std::string value;
+	int save = column;
+	char quote = *it++;
+
+	while (it != end && *it != quote) {
+		// TODO: escape sequence
+		++ column;
+		value += *it++;
+	}
+
+	if (it == end) {
+		throw Error{line, column, "undisclosed '" + std::string(1, quote) + "', got <EOF>"};
+	}
+
+	/* Remove quote */
+	++ it;
+
+	list.push_back({ Token::QuotedWord, line, save, std::move(value) });
+}
+
+void analyzeWord(Tokens &list, int &line, int &column, StreamIterator &it, StreamIterator end)
+{
+	assert(!isReserved(*it));
+
+	std::string value;
+	int save = column;
+
+	while (it != end && !std::isspace(*it) && !isReserved(*it)) {
+		++ column;
+		value += *it++;
+	}
+
+	list.push_back({ Token::Word, line, save, std::move(value) });
+}
+
+void analyzeInclude(Tokens &list, int &line, int &column, StreamIterator &it, StreamIterator end)
+{
+	assert(*it == '@');
+
+	std::string include;
+	int save = column;
+
+	/* Read include */
+	++ it;
+	while (it != end && !isSpace(*it)) {
+		++ column;
+		include += *it++;
+	}
+
+	if (include != "include") {
+		throw Error{line, column, "expected include after '@' token"};
+	}
+
+	list.push_back({ Token::Include, line, save });
+}
+
+Tokens analyze(StreamIterator &it, StreamIterator end)
+{
+	Tokens list;
+	int line = 1;
+	int column = 0;
+
+	while (it != end) {
+		if (*it == '\n') {
+			analyzeLine(line, column, it);
+		} else if (*it == '#') {
+			analyzeComment(column, it, end);
+		} else if (*it == '[') {
+			analyzeSection(list, line, column, it, end);
+		} else if (*it == '=') {
+			analyzeAssign(list, line, column, it);
+		} else if (isSpace(*it)) {
+			analyzeSpaces(column, it, end);
+		} else if (*it == '@') {
+			analyzeInclude(list, line, column, it, end);
+		} else if (isQuote(*it)) {
+			analyzeQuotedWord(list, line, column, it, end);
+		} else if (isList(*it)) {
+			analyzeList(list, line, column, it);
+		} else {
+			analyzeWord(list, line, column, it, end);
+		}
+	}
+
+	return list;
+}
+
+void parseOptionValueSimple(Option &option, TokenIterator &it)
+{
+	assert(it->type() == Token::Word || it->type() == Token::QuotedWord);
+
+	option.push_back((it++)->value());
+}
+
+void parseOptionValueList(Option &option, TokenIterator &it, TokenIterator end)
+{
+	assert(it->type() == Token::ListBegin);
+
+	TokenIterator save = it++;
+
+	while (it != end && it->type() != Token::ListEnd) {
+		switch (it->type()) {
+		case Token::Comma:
+			/* Previous must be a word */
+			if (it[-1].type() != Token::Word && it[-1].type() != Token::QuotedWord) {
+				throw Error{it->line(), it->column(), "unexpected comma after '" + it[-1].value() + "'"};
+			}
+
+			++ it;
+			break;
+		case Token::Word:
+		case Token::QuotedWord:
+			option.push_back((it++)->value());
+			break;
+		default:
+			throw Error{it->line(), it->column(), "unexpected '" + it[-1].value() + "' in list construct"};
+			break;
+		}
+	}
+
+	if (it == end) {
+		throw Error{save->line(), save->column(), "unterminated list construct"};
+	}
+
+	/* Remove ) */
+	++ it;
+}
+
+void parseOption(Section &sc, TokenIterator &it, TokenIterator end)
+{
+	Option option{it->value()};
+
+	TokenIterator save = it;
+
+	/* No '=' or something else? */
+	if (++it == end) {
+		throw Error{save->line(), save->column(), "expected '=' assignment, got <EOF>"};
+	}
+	if (it->type() != Token::Assign) {
+		throw Error{it->line(), it->column(), "expected '=' assignment, got " + it->value()};
+	}
+
+	/* Empty options are allowed so just test for words */
+	if (++it != end) {
+		if (it->type() == Token::Word || it->type() == Token::QuotedWord) {
+			parseOptionValueSimple(option, it);
+		} else if (it->type() == Token::ListBegin) {
+			parseOptionValueList(option, it, end);
+		}
+	}
+
+	sc.push_back(std::move(option));
+}
+
+void parseInclude(Document &doc, TokenIterator &it, TokenIterator end)
+{
+	TokenIterator save = it;
+
+	if (++it == end) {
+		throw Error{save->line(), save->column(), "expected file name after '@include' statement, got <EOF>"};
+	}
+
+	if (it->type() != Token::Word && it->type() != Token::QuotedWord) {
+		throw Error{it->line(), it->column(), "expected file name after '@include' statement, got " + it->value()};
+	}
+
+	if (doc.path().empty()) {
+		throw Error{it->line(), it->column(), "'@include' statement invalid with buffer documents"};
+	}
+
+	std::string value = (it++)->value();
+	std::string file;
+
+	if (!isAbsolute(value)) {
+#if defined(_WIN32)
+		file = doc.path() + "\\" + value;
+#else
+		file = doc.path() + "/" + value;
+#endif
+	} else {
+		file = value;
+	}
+
+	Document child{File{file}};
+
+	for (const auto &sc : child) {
+		doc.push_back(sc);
+	}
+}
+
+void parseSection(Document &doc, TokenIterator &it, TokenIterator end)
+{
+	Section sc{it->value()};
+
+	/* Skip [section] */
+	++ it;
+
+	/* Read until next section */
+	while (it != end && it->type() != Token::Section) {
+		if (it->type() != Token::Word) {
+			throw Error{it->line(), it->column(), "unexpected token '" + it->value() + "' in section definition"};
+		}
+
+		parseOption(sc, it, end);
+	}
+
+	doc.push_back(std::move(sc));
+}
+
+void parse(Document &doc, const Tokens &tokens)
+{
+	TokenIterator it = tokens.cbegin();
+	TokenIterator end = tokens.cend();
+
+	while (it != end) {
+		/* Just ignore this */
+		switch (it->type()) {
+		case Token::Include:
+			parseInclude(doc, it, end);
+			break;
+		case Token::Section:
+			parseSection(doc, it, end);
+			break;
+		default:
+			throw Error{it->line(), it->column(), "unexpected '" + it->value() + "' on root document"};
+		}
+	}
+}
+
+} // !namespace
+
+namespace ini {
+
+Tokens Document::analyze(const File &file)
+{
+	std::fstream stream{file.path};
+
+	if (!stream) {
+		throw std::runtime_error{std::strerror(errno)};
+	}
+
+	std::istreambuf_iterator<char> it{stream};
+	std::istreambuf_iterator<char> end{};
+
+	return ::analyze(it, end);
+}
+
+Tokens Document::analyze(const Buffer &buffer)
+{
+	std::istringstream stream{buffer.text};
+	std::istreambuf_iterator<char> it{stream};
+	std::istreambuf_iterator<char> end{};
+
+	return ::analyze(it, end);
+}
+
+Document::Document(const File &file)
+	: m_path{file.path}
+{
+	/* Update path */
+	auto pos = m_path.find_last_of("/\\");
+
+	if (pos != std::string::npos) {
+		m_path.erase(pos);
+	} else {
+		m_path = ".";
+	}
+
+	parse(*this, analyze(file));
+}
+
+Document::Document(const Buffer &buffer)
+{
+	parse(*this, analyze(buffer));
+}
+
+void Document::dump(const Tokens &tokens)
+{
+	for (const Token &token: tokens) {
+		// TODO: add better description
+		std::cout << token.line() << ":" << token.column() << ": " << token.value() << std::endl;
+	}
+}
+
+} // !ini
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Ini/ini.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,546 @@
+/*
+ * ini.h -- .ini file parsing
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _INI_H_
+#define _INI_H_
+
+/**
+ * @file ini.h
+ * @brief Configuration file parser.
+ */
+
+#include <algorithm>
+#include <cassert>
+#include <exception>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+/**
+ * Namespace for ini related classes.
+ */
+namespace ini {
+
+class Document;
+
+/**
+ * @class Error
+ * @brief Error in a file
+ */
+class Error : public std::exception {
+private:
+	int m_line;		//!< line number
+	int m_column;		//!< line column
+	std::string m_message;	//!< error message
+
+public:
+	/**
+	 * Constructor.
+	 *
+	 * @param l the line
+	 * @param c the column
+	 * @param m the message
+	 */
+	inline Error(int l, int c, std::string m) noexcept
+		: m_line{l}
+		, m_column{c}
+		, m_message{std::move(m)}
+	{
+	}
+
+	/**
+	 * Get the line number.
+	 *
+	 * @return the line
+	 */
+	inline int line() const noexcept
+	{
+		return m_line;
+	}
+
+	/**
+	 * Get the column number.
+	 *
+	 * @return the column
+	 */
+	inline int column() const noexcept
+	{
+		return m_column;
+	}
+
+	/**
+	 * Return the raw error message (no line and column shown).
+	 *
+	 * @return the error message
+	 */
+	const char *what() const noexcept override
+	{
+		return m_message.c_str();
+	}
+};
+
+/**
+ * @class Token
+ * @brief Describe a token read in the .ini source
+ *
+ * This class can be used when you want to parse a .ini file yourself.
+ *
+ * @see Document::analyze
+ */
+class Token {
+public:
+	/**
+	 * @brief Token type
+	 */
+	enum Type {
+		Include,	//!< include statement
+		Section,	//!< [section]
+		Word,		//!< word without quotes
+		QuotedWord,	//!< word with quotes
+		Assign,		//!< = assignment
+		ListBegin,	//!< begin of list (
+		ListEnd,	//!< end of list )
+		Comma		//!< list separation
+	};
+
+private:
+	Type m_type;
+	int m_line;
+	int m_column;
+	std::string m_value;
+
+public:
+	/**
+	 * Construct a token.
+	 *
+	 * @param type the type
+	 * @param line the line
+	 * @param column the column
+	 * @param value the value
+	 */
+	Token(Type type, int line, int column, std::string value = "") noexcept
+		: m_type{type}
+		, m_line{line}
+		, m_column{column}
+	{
+		switch (type) {
+		case Include:
+			m_value = "@include";
+			break;
+		case Section:
+		case Word:
+		case QuotedWord:
+			m_value = value;
+			break;
+		case Assign:
+			m_value = "=";
+			break;
+		case ListBegin:
+			m_value = "(";
+			break;
+		case ListEnd:
+			m_value = ")";
+			break;
+		case Comma:
+			m_value = ",";
+			break;
+		default:
+			break;
+		}
+	}
+
+	/**
+	 * Get the type.
+	 *
+	 * @return the type
+	 */
+	inline Type type() const noexcept
+	{
+		return m_type;
+	}
+
+	/**
+	 * Get the line.
+	 *
+	 * @return the line
+	 */
+	inline int line() const noexcept
+	{
+		return m_line;
+	}
+
+	/**
+	 * Get the column.
+	 *
+	 * @return the column
+	 */
+	inline int column() const noexcept
+	{
+		return m_column;
+	}
+
+	/**
+	 * Get the value. For words, quoted words and section, the value is the content. Otherwise it's the
+	 * characters parsed.
+	 *
+	 * @return the value
+	 */
+	inline const std::string &value() const noexcept
+	{
+		return m_value;
+	}
+};
+
+/**
+ * List of tokens in order they are analyzed.
+ */
+using Tokens = std::vector<Token>;
+
+/**
+ * @class Option
+ * @brief Option definition.
+ */
+class Option : public std::vector<std::string> {
+private:
+	std::string m_key;
+
+public:
+	/**
+	 * Construct an empty option.
+	 *
+	 * @param key the key
+	 * @param value the value
+	 */
+	inline Option(std::string key) noexcept
+		: std::vector<std::string>{}
+		, m_key{std::move(key)}
+	{
+	}
+
+	/**
+	 * Construct a single option.
+	 *
+	 * @param key the key
+	 * @param value the value
+	 */
+	inline Option(std::string key, std::string value) noexcept
+		: m_key{std::move(key)}
+	{
+		push_back(std::move(value));
+	}
+
+	/**
+	 * Construct a list option.
+	 *
+	 * @param key the key
+	 * @param values the values
+	 */
+	inline Option(std::string key, std::vector<std::string> values) noexcept
+		: std::vector<std::string>{std::move(values)}
+		, m_key{std::move(key)}
+	{
+	}
+
+	/**
+	 * Get the option key.
+	 *
+	 * @return the key
+	 */
+	inline const std::string &key() const noexcept
+	{
+		return m_key;
+	}
+
+	/**
+	 * Get the option value.
+	 *
+	 * @return the value
+	 */
+	inline const std::string &value() const noexcept
+	{
+		static std::string dummy;
+
+		return empty() ? dummy : (*this)[0];
+	}
+};
+
+/**
+ * @class Section
+ * @brief Section that contains one or more options.
+ */
+class Section : public std::vector<Option> {
+private:
+	std::string m_key;
+
+public:
+	/**
+	 * Construct a section with its name.
+	 *
+	 * @param key the key
+	 * @pre key must not be empty
+	 */
+	inline Section(std::string key) noexcept
+		: m_key{std::move(key)}
+	{
+		assert(!m_key.empty());
+	}
+
+	/**
+	 * Get the section key.
+	 *
+	 * @return the key
+	 */
+	inline const std::string &key() const noexcept
+	{
+		return m_key;
+	}
+
+	/**
+	 * Check if the section contains a specific option.
+	 *
+	 * @param key the option key
+	 * @return true if the option exists
+	 */
+	inline bool contains(const std::string &key) const noexcept
+	{
+		return find(key) != end();
+	}
+
+	/**
+	 * Access an option at the specified key.
+	 *
+	 * @param key the key
+	 * @return the option
+	 * @pre contains(key) must return true
+	 */
+	inline Option &operator[](const std::string &key)
+	{
+		assert(contains(key));
+
+		return *find(key);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param key the key
+	 * @return the option
+	 * @pre contains(key) must return true
+	 */
+	inline const Option &operator[](const std::string &key) const
+	{
+		assert(contains(key));
+
+		return *find(key);
+	}
+
+	/**
+	 * Find an option by key and return an iterator.
+	 *
+	 * @param key the key
+	 * @return the iterator or end() if not found
+	 */
+	inline iterator find(const std::string &key) noexcept
+	{
+		return std::find_if(begin(), end(), [&] (const auto &o) {
+			return o.key() == key;
+		});
+	}
+
+	/**
+	 * Find an option by key and return an iterator.
+	 *
+	 * @param key the key
+	 * @return the iterator or end() if not found
+	 */
+	inline const_iterator find(const std::string &key) const noexcept
+	{
+		return std::find_if(cbegin(), cend(), [&] (const auto &o) {
+			return o.key() == key;
+		});
+	}
+
+	/**
+	 * Inherited operators.
+	 */
+	using std::vector<Option>::operator[];
+};
+
+/**
+ * @class File
+ * @brief Source for reading .ini files.
+ */
+class File {
+public:
+	/**
+	 * Path to the file.
+	 */
+	std::string path;
+};
+
+/**
+ * @class Buffer
+ * @brief Source for reading ini from text.
+ * @note the include statement is not supported with buffers.
+ */
+class Buffer {
+public:
+	/**
+	 * The ini content.
+	 */
+	std::string text;
+};
+
+/**
+ * @class Document
+ * @brief Ini config file loader
+ */
+class Document : public std::vector<Section> {
+private:
+	std::string m_path;
+
+public:
+	/**
+	 * Analyze a file and extract tokens. If the function succeeds, that does not mean the content is valid,
+	 * it just means that there are no syntax error.
+	 *
+	 * For example, this class does not allow adding options under no sections and this function will not
+	 * detect that issue.
+	 *
+	 * @param file the file to read
+	 * @return the list of tokens
+	 * @throws Error on errors
+	 */
+	static Tokens analyze(const File &file);
+
+	/**
+	 * Overloaded function for buffers.
+	 *
+	 * @param buffer the buffer to read
+	 * @return the list of tokens
+	 * @throws Error on errors
+	 */
+	static Tokens analyze(const Buffer &buffer);
+
+	/**
+	 * Show all tokens and their description.
+	 *
+	 * @param tokens the tokens
+	 */
+	static void dump(const Tokens &tokens);
+
+	/**
+	 * Construct a document from a file.
+	 *
+	 * @param file the file to read
+	 * @throws Error on errors
+	 */
+	Document(const File &file);
+
+	/**
+	 * Overloaded constructor for buffers.
+	 *
+	 * @param buffer the buffer to read
+	 * @throws Error on errors
+	 */
+	Document(const Buffer &buffer);
+
+	/**
+	 * Get the current document path, only useful when constructed from File source.
+	 *
+	 * @return the path
+	 */
+	inline const std::string &path() const noexcept
+	{
+		return m_path;
+	}
+
+	/**
+	 * Check if a document has a specific section.
+	 *
+	 * @param key the key
+	 * @return true if the document contains the section
+	 */
+	inline bool contains(const std::string &key) const noexcept
+	{
+		return std::find_if(begin(), end(), [&] (const auto &sc) { return sc.key() == key; }) != end();
+	}
+
+	/**
+	 * Access a section at the specified key.
+	 *
+	 * @param key the key
+	 * @return the section
+	 * @pre contains(key) must return true
+	 */
+	inline Section &operator[](const std::string &key)
+	{
+		assert(contains(key));
+
+		return *find(key);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param key the key
+	 * @return the section
+	 * @pre contains(key) must return true
+	 */
+	inline const Section &operator[](const std::string &key) const
+	{
+		assert(contains(key));
+
+		return *find(key);
+	}
+
+	/**
+	 * Find a section by key and return an iterator.
+	 *
+	 * @param key the key
+	 * @return the iterator or end() if not found
+	 */
+	inline iterator find(const std::string &key) noexcept
+	{
+		return std::find_if(begin(), end(), [&] (const auto &o) {
+			return o.key() == key;
+		});
+	}
+
+	/**
+	 * Find a section by key and return an iterator.
+	 *
+	 * @param key the key
+	 * @return the iterator or end() if not found
+	 */
+	inline const_iterator find(const std::string &key) const noexcept
+	{
+		return std::find_if(cbegin(), cend(), [&] (const auto &o) {
+			return o.key() == key;
+		});
+	}
+
+	/**
+	 * Inherited operators.
+	 */
+	using std::vector<Section>::operator[];
+};
+
+} // !ini
+
+#endif // !_INI_H_
--- a/C++/modules/Js/Js.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Js.cpp -- JavaScript C++14 wrapper for Duktape
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "Js.h"
-
-using namespace std::string_literals;
-
-namespace js {
-
-ErrorInfo Context::error(int index)
-{
-	ErrorInfo error;
-
-	index = duk_normalize_index(m_handle.get(), index);
-
-	duk_get_prop_string(m_handle.get(), index, "name");
-	error.name = duk_to_string(m_handle.get(), -1);
-	duk_get_prop_string(m_handle.get(), index, "message");
-	error.message = duk_to_string(m_handle.get(), -1);
-	duk_get_prop_string(m_handle.get(), index, "fileName");
-	error.fileName = duk_to_string(m_handle.get(), -1);
-	duk_get_prop_string(m_handle.get(), index, "lineNumber");
-	error.lineNumber = duk_to_int(m_handle.get(), -1);
-	duk_get_prop_string(m_handle.get(), index, "stack");
-	error.stack = duk_to_string(m_handle.get(), -1);
-	duk_pop_n(m_handle.get(), 5);
-
-	return error;
-}
-
-void Context::pcall(unsigned nargs)
-{
-	if (duk_pcall(m_handle.get(), nargs) != 0) {
-		ErrorInfo info = error(-1);
-		duk_pop(m_handle.get());
-
-		throw info;
-	}
-}
-
-void Context::peval()
-{
-	if (duk_peval(m_handle.get()) != 0) {
-		ErrorInfo info = error(-1);
-		duk_pop(m_handle.get());
-
-		throw info;
-	}
-}
-
-void TypeInfo<Function>::push(Context &ctx, Function fn)
-{
-	/* 1. Push function wrapper */
-	duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
-		Context context{ctx};
-
-		duk_push_current_function(ctx);
-		duk_get_prop_string(ctx, -1, "\xff""\xff""js-func");
-		Function *f = static_cast<Function *>(duk_to_pointer(ctx, -1));
-		duk_pop_2(ctx);
-
-		return static_cast<duk_ret_t>(f->function(context));
-	}, fn.nargs);
-
-	/* 2. Store the moved function */
-	duk_push_pointer(ctx, new Function(std::move(fn)));
-	duk_put_prop_string(ctx, -2, "\xff""\xff""js-func");
-
-	/* 3. Store deletion flags */
-	duk_push_boolean(ctx, false);
-	duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
-
-	/* 4. Push and set a finalizer */
-	duk_push_c_function(ctx, [] (duk_context *ctx) {
-		duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-
-		if (!duk_to_boolean(ctx, -1)) {
-			duk_push_boolean(ctx, true);
-			duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-			duk_get_prop_string(ctx, 0, "\xff""\xff""js-func");
-			delete static_cast<Function *>(duk_to_pointer(ctx, -1));
-			duk_pop(ctx);
-		}
-
-		duk_pop(ctx);
-
-		return 0;
-	}, 1);
-	duk_set_finalizer(ctx, -2);
-}
-
-} // !js
--- a/C++/modules/Js/Js.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2105 +0,0 @@
-/*
- * Js.h -- JavaScript C++14 wrapper for Duktape
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _JS_H_
-#define _JS_H_
-
-/**
- * @file Js.h
- * @brief Bring JavaScript using Duktape
- *
- * This file provides usual Duktape function renamed and placed into `js` namespace. It also replaces error
- * code with exceptions when possible.
- *
- * For convenience, this file also provides templated functions, overloads and much more.
- */
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include <duktape.h>
-
-/**
- * Duktape C++ namespace wrapper.
- */
-namespace js {
-
-class Context;
-
-/**
- * Typedef for readability.
- */
-using ContextPtr = duk_context *;
-
-/*
- * Basic types to manipulate with the stack
- * ------------------------------------------------------------------
- *
- * The following types can be used in some of the operations like Context::push or Context::is, they are defined
- * usually as empty classes to determine the appropriate action to execute.
- *
- * For example, `ctx.push(js::Object{})` will push an empty object into the stack.
- */
-
-/**
- * @class Object
- * @brief Empty class tag for push() function.
- */
-class Object {
-};
-
-/**
- * @class Array
- * @brief Empty class tag for push() function.
- */
-class Array {
-};
-
-/**
- * @class Global
- * @brief Empty class tag to push the global object.
- */
-class Global {
-};
-
-/**
- * @class Undefined
- * @brief Empty class tag to push undefined to the stack.
- */
-class Undefined {
-};
-
-/**
- * @class Null
- * @brief Empty class tag to push null to the stack.
- */
-class Null {
-};
-
-/**
- * @class This
- * @brief Empty class tag to push this binding to the stack.
- */
-class This {
-};
-
-/**
- * @class RawPointer
- * @brief Push a non-managed pointer to Duktape, the pointer will never be deleted.
- * @note For a managed pointer with prototype, see Pointer
- */
-template <typename T>
-class RawPointer {
-public:
-	/**
-	 * The pointer to push.
-	 */
-	T *object;
-};
-
-/*
- * Extended type manipulation
- * ------------------------------------------------------------------
- *
- * The following types are different as there are no equivalent in the native Duktape API, they are available for
- * convenience.
- */
-
-/**
- * @brief Manage shared_ptr from C++ and JavaScript
- *
- * This class allowed you to push and retrieve shared_ptr from C++ and JavaScript without taking care of ownership
- * and deletion.
- *
- * The only requirement is to have the function `void prototype(Context &ctx)` in your class T.
- */
-template <typename T>
-class Shared {
-public:
-	/**
-	 * The shared object.
-	 */
-	std::shared_ptr<T> object;
-};
-
-/**
- * @brief Manage pointers from C++ and JavaScript
- *
- * This class allowed you to push and retrieve C++ pointers from C++ and JavaScript. The object will be deleted when
- * the JavaScript garbage collectors collect them so never store a pointer created with this.
- *
- * The only requirement is to have the function `void prototype(Context &ctx)` in your class T.
- */
-template <typename T>
-class Pointer {
-public:
-	/**
-	 * The object.
-	 */
-	T *object{nullptr};
-};
-
-/**
- * @class Function
- * @brief Duktape/C function definition.
- *
- * This class wraps the std::function as a Duktape/C function by storing a copied pointer.
- */
-class Function {
-public:
-	/**
-	 * The function pointer, must not be null.
-	 */
-	std::function<int (Context &)> function;
-
-	/**
-	 * Number of args that the function takes
-	 */
-	int nargs{0};
-};
-
-/**
- * Map of functions to set on an object.
- */
-using FunctionMap = std::unordered_map<std::string, Function>;
-
-/**
- * Map of string to type, ideal for setting constants like enums.
- */
-template <typename Type>
-using Map = std::unordered_map<std::string, Type>;
-
-/**
- * @class ErrorInfo
- * @brief Error description.
- *
- * This class fills the fields got in an Error object.
- */
-class ErrorInfo : public std::exception {
-public:
-	std::string name;		//!< name of error
-	std::string message;		//!< error message
-	std::string stack;		//!< stack if available
-	std::string fileName;		//!< filename if applicable
-	int lineNumber{0};		//!< line number if applicable
-
-	/**
-	 * Get the error message. This effectively returns message field.
-	 *
-	 * @return the message
-	 */
-	const char *what() const noexcept override
-	{
-		return message.c_str();
-	}
-};
-
-/**
- * @class TypeInfo
- * @brief Type information to implement new types in JavaScript's context.
- *
- * This class depending on your needs may have the following functions:
- *
- * - `static void construct(Context &ctx, Type value)`
- * - `static Type get(Context &ctx, int index)`
- * - `static bool is(Context &ctx, int index)`
- * - `static Type optional(Context &ctx, int index, Type defaultValue)`
- * - `static void push(Context &ctx, Type value)`
- * - `static Type require(Context &ctx, int index)`
- *
- * The `construct` function is used in Context::construct to build a new value as this (e.g. constructors).
- *
- * The `get` function is used in Context::get, Context::getProperty, Context::getGlobal to retrieve a value from the
- * stack.
- *
- * The `is` function is used in Context::is to check if the value on the stack is of type `Type`.
- *
- * The `optional` function is used in Context::optional to get a value or a replacement if not applicable.
- *
- * The `push` function is used in Context::push to usually create a new value on the stack but some specializations
- * may not (e.g. FunctionMap).
- *
- * The `require` function is used in Context::require to get a value from the stack or raise a JavaScript exception if
- * not applicable.
- *
- * This class is fully specialized for: `bool`, `const char *`, `double`, `int`, `std::string`.
- *
- * It is also partially specialized for : `Global`, `Object`, `Array`, `Undefined`, `Null`, `std::vector<Type>`.
- */
-template <typename Type>
-class TypeInfo {
-};
-
-/**
- * @class File
- * @brief Evaluate script from file.
- * @see Context::eval
- * @see Context::peval
- */
-class File {
-public:
-	/**
-	 * Path to the file.
-	 */
-	std::string path;
-
-	/**
-	 * Evaluate the file.
-	 *
-	 * @param ctx the context
-	 */
-	inline void eval(duk_context *ctx)
-	{
-		duk_eval_file(ctx, path.c_str());
-	}
-
-	/**
-	 * Evaluate in protected mode the file.
-	 *
-	 * @param ctx the context
-	 */
-	inline int peval(duk_context *ctx)
-	{
-		return duk_peval_file(ctx, path.c_str());
-	}
-};
-
-/**
- * @class Script
- * @brief Evaluate script from raw text.
- * @see Context::eval
- * @see Context::peval
- */
-class Script {
-public:
-	/**
-	 * The script content.
-	 */
-	std::string text;
-
-	/**
-	 * Evaluate the script.
-	 *
-	 * @param ctx the context
-	 */
-	inline void eval(duk_context *ctx)
-	{
-		duk_eval_string(ctx, text.c_str());
-	}
-
-	/**
-	 * Evaluate in protected mode the script.
-	 *
-	 * @param ctx the context
-	 */
-	inline int peval(duk_context *ctx)
-	{
-		return duk_peval_string(ctx, text.c_str());
-	}
-};
-
-/**
- * @class Context
- * @brief RAII based Duktape handler.
- *
- * This class is implicitly convertible to duk_context for convenience.
- */
-class Context {
-private:
-	using Deleter = void (*)(duk_context *);
-	using Handle = std::unique_ptr<duk_context, Deleter>;
-
-	Handle m_handle;
-
-	/* Move and copy forbidden */
-	Context(const Context &) = delete;
-	Context &operator=(const Context &) = delete;
-	Context(const Context &&) = delete;
-	Context &operator=(const Context &&) = delete;
-
-public:
-	/**
-	 * Create default context.
-	 */
-	inline Context()
-		: m_handle{duk_create_heap_default(), duk_destroy_heap}
-	{
-	}
-
-	/**
-	 * Create borrowed context that will not be deleted.
-	 *
-	 * @param ctx the pointer to duk_context
-	 */
-	inline Context(ContextPtr ctx) noexcept
-		: m_handle{ctx, [] (ContextPtr) {}}
-	{
-	}
-
-	/**
-	 * Convert the context to the native Duktape/C type.
-	 *
-	 * @return the duk_context
-	 */
-	inline operator duk_context *() noexcept
-	{
-		return m_handle.get();
-	}
-
-	/**
-	 * Convert the context to the native Duktape/C type.
-	 *
-	 * @return the duk_context
-	 */
-	inline operator duk_context *() const noexcept
-	{
-		return m_handle.get();
-	}
-
-	/*
-	 * Basic functions
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions are just standard wrappers around the native Duktape C functions, they are
-	 * defined with the same signature except that for convenience some parameters have default sane values.
-	 */
-
-	/**
-	 * Call the object at the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param nargs the number of arguments
-	 * @note Non-protected
-	 */
-	inline void call(unsigned nargs = 0)
-	{
-		duk_call(m_handle.get(), nargs);
-	}
-
-	/**
-	 * Copy a value from from to to, overwriting the previous value. If either index is invalid, throws an error.
-	 *
-	 * @param from the from index
-	 * @param to the destination
-	 */
-	inline void copy(int from, int to)
-	{
-		duk_copy(m_handle.get(), from, to);
-	}
-
-	/**
-	 * Define a property.
-	 *
-	 * @param index the object index
-	 * @param flags the flags
-	 * @note Wrapper of duk_def_prop
-	 */
-	inline void defineProperty(int index, int flags)
-	{
-		duk_def_prop(m_handle.get(), index, flags);
-	}
-
-	/**
-	 * Delete a property.
-	 *
-	 * @param index the object index
-	 * @return true if deleted
-	 * @note Wrapper of duk_del_prop
-	 */
-	inline bool deleteProperty(int index)
-	{
-		return duk_del_prop(m_handle.get(), index);
-	}
-
-	/**
-	 * Delete a property by index.
-	 *
-	 * @param index the object index
-	 * @param position the property index
-	 * @return true if deleted
-	 * @note Wrapper of duk_del_prop_index
-	 */
-	inline bool deleteProperty(int index, int position)
-	{
-		return duk_del_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * Delete a property by name.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @return true if deleted
-	 * @note Wrapper of duk_del_prop_string
-	 */
-	inline bool deleteProperty(int index, const std::string &name)
-	{
-		return duk_del_prop_string(m_handle.get(), index, name.c_str());
-	}
-
-	/**
-	 * Push a duplicate of value at from_index to the stack. If from_index is invalid, throws an error.
-	 *
-	 * @param index the value to copy
-	 * @note Wrapper of duk_dup
-	 */
-	inline void dup(int index = -1)
-	{
-		duk_dup(m_handle.get(), index);
-	}
-
-	/**
-	 * Evaluate a non-protected chunk that is at the top of the stack.
-	 */
-	inline void eval()
-	{
-		duk_eval(m_handle.get());
-	}
-
-	/**
-	 * Check if the object as a property.
-	 *
-	 * @param index the object index
-	 * @return true if has
-	 * @note Wrapper of duk_has_prop
-	 */
-	inline bool hasProperty(int index)
-	{
-		return duk_has_prop(m_handle.get(), index);
-	}
-
-	/**
-	 * Check if the object as a property by index.
-	 *
-	 * @param index the object index
-	 * @param position the property index
-	 * @return true if has
-	 * @note Wrapper of duk_has_prop_index
-	 */
-	inline bool hasProperty(int index, int position)
-	{
-		return duk_has_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * Check if the object as a property by string
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @return true if has
-	 * @note Wrapper of duk_has_prop_string
-	 */
-	inline bool hasProperty(int index, const std::string &name)
-	{
-		return duk_has_prop_string(m_handle.get(), index, name.c_str());
-	}
-
-	/**
-	 * Check if idx1 is an instance of idx2.
-	 *
-	 * @param ctx the context
-	 * @param idx1 the value to test
-	 * @param idx2 the instance requested
-	 * @return true if idx1 is instance of idx2
-	 * @note Wrapper of duk_instanceof
-	 */
-	inline bool instanceof(int idx1, int idx2)
-	{
-		return duk_instanceof(m_handle.get(), idx1, idx2);
-	}
-
-	/**
-	 * Insert a value at to with a value popped from the stack top. The previous value at to and any values above
-	 * it are moved up the stack by a step. If to is an invalid index, throws an error.
-	 *
-	 * @note Negative indices are evaluated prior to popping the value at the stack top
-	 * @param to the destination
-	 * @note Wrapper of duk_insert
-	 */
-	inline void insert(int to)
-	{
-		duk_insert(m_handle.get(), to);
-	}
-
-	/**
-	 * Pop a certain number of values from the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param count the number of values to pop
-	 * @note Wrapper of duk_pop_n
-	 */
-	inline void pop(unsigned count = 1)
-	{
-		duk_pop_n(m_handle.get(), count);
-	}
-
-	/**
-	 * Remove value at index. Elements above index are shifted down the stack by a step. If to is an invalid index,
-	 * throws an error.
-	 *
-	 * @param index the value to remove
-	 * @note Wrapper of duk_remove
-	 */
-	inline void remove(int index)
-	{
-		duk_remove(m_handle.get(), index);
-	}
-
-	/**
-	 * Replace value at to_index with a value popped from the stack top. If to_index is an invalid index,
-	 * throws an error.
-	 *
-	 * @param index the value to replace by the value at the top of the stack
-	 * @note Negative indices are evaluated prior to popping the value at the stack top.
-	 * @note Wrapper of duk_replace
-	 */
-	inline void replace(int index)
-	{
-		duk_replace(m_handle.get(), index);
-	}
-
-	/**
-	 * Swap values at indices index1 and index2. If the indices are the same, the call is a no-op. If either index
-	 * is invalid, throws an error.
-	 *
-	 * @param index1 the first index
-	 * @param index2 the second index
-	 * @note Wrapper of duk_swap
-	 */
-	inline void swap(int index1, int index2)
-	{
-		duk_swap(m_handle.get(), index1, index2);
-	}
-
-	/**
-	 * Get the current stack size.
-	 *
-	 * @param ctx the context
-	 * @return the stack size
-	 * @note Wrapper of duk_get_top
-	 */
-	inline int top() noexcept
-	{
-		return duk_get_top(m_handle.get());
-	}
-
-	/**
-	 * Get the type of the value at the specified index.
-	 *
-	 * @param ctx the context
-	 * @param index the idnex
-	 * @return the type
-	 * @note Wrapper of duk_get_type
-	 */
-	inline int type(int index) noexcept
-	{
-		return duk_get_type(m_handle.get(), index);
-	}
-
-	/*
-	 * Extended native functions
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions have different behaviour than the original native Duktape C functions, see their
-	 * descriptions for more information
-	 */
-
-	/**
-	 * Call in protected mode the object at the top of the stack.
-	 *
-	 * @param nargs the number of arguments
-	 * @throw ErrorInfo on errors
-	 * @note Wrapper of duk_pcall
-	 */
-	void pcall(unsigned nargs = 0);
-
-	/**
-	 * Evaluate a non-protected source.
-	 *
-	 * @param source the source
-	 * @see File
-	 * @see Script
-	 * @note Wrapper of duk_eval
-	 */
-	template <typename Source>
-	inline void eval(Source &&source)
-	{
-		source.eval(m_handle.get());
-	}
-
-	/**
-	 * Evaluate a protected chunk that is at the top of the stack.
-	 *
-	 * @throw ErrorInfo the error
-	 * @note Wrapper of duk_peval
-	 */
-	void peval();
-
-	/**
-	 * Evaluate a protected source.
-	 *
-	 * @param source the source
-	 * @see File
-	 * @see Script
-	 * @throw ErrorInfo on failure
-	 * @note Wrapper of duk_peval
-	 */
-	template <typename Source>
-	inline void peval(Source &&source)
-	{
-		if (source.peval(m_handle.get()) != 0) {
-			ErrorInfo info = error(-1);
-			duk_pop(m_handle.get());
-
-			throw info;
-		}
-	}
-
-	/*
-	 * Push / Get / Require / Is / Optional
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions are used to push, get or check values from the stack. They use specialization
-	 * of TypeInfo class.
-	 */
-
-	/**
-	 * Push a value into the stack. Calls TypeInfo<T>::push(*this, value);
-	 *
-	 * @param value the value to forward
-	 */
-	template <typename Type>
-	inline void push(Type &&value)
-	{
-		TypeInfo<std::decay_t<Type>>::push(*this, std::forward<Type>(value));
-	}
-
-	/**
-	 * Generic template function to get a value from the stack.
-	 *
-	 * @param index the index
-	 * @return the value
-	 */
-	template <typename Type>
-	inline auto get(int index) -> decltype(TypeInfo<Type>::get(*this, 0))
-	{
-		return TypeInfo<Type>::get(*this, index);
-	}
-
-	/**
-	 * Require a type at the specified index.
-	 *
-	 * @param index the index
-	 * @return the value
-	 */
-	template <typename Type>
-	inline auto require(int index) -> decltype(TypeInfo<Type>::require(*this, 0))
-	{
-		return TypeInfo<Type>::require(*this, index);
-	}
-
-	/**
-	 * Check if a value is a type of T.
-	 *
-	 * The TypeInfo<T> must have `static bool is(ContextPtr ptr, int index)`.
-	 *
-	 * @param index the value index
-	 * @return true if is the type
-	 */
-	template <typename T>
-	inline bool is(int index)
-	{
-		return TypeInfo<T>::is(*this, index);
-	}
-
-	/**
-	 * Get an optional value from the stack, if the value is not available of not the correct type,
-	 * return defaultValue instead.
-	 *
-	 * The TypeInfo<T> must have `static T optional(Context &, int index, T &&defaultValue)`.
-	 *
-	 * @param index the value index
-	 * @param defaultValue the value replacement
-	 * @return the value or defaultValue
-	 */
-	template <typename Type>
-	inline auto optional(int index, Type &&defaultValue)
-	{
-		return TypeInfo<std::decay_t<Type>>::optional(*this, index, std::forward<Type>(defaultValue));
-	}
-
-	/*
-	 * Properties management
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions are used to read or set properties on objects or globals also using TypeInfo.
-	 */
-
-	/**
-	 * Get the property `name' as value from the object at the specified index.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @return the value
-	 * @note The stack is unchanged
-	 */
-	template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
-	inline auto getProperty(int index, const std::string &name) -> decltype(get<Type>(0))
-	{
-		duk_get_prop_string(m_handle.get(), index, name.c_str());
-		decltype(get<Type>(0)) value = get<Type>(-1);
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Get a property by index, for arrays.
-	 *
-	 * @param index the object index
-	 * @param position the position int the object
-	 * @return the value
-	 * @note The stack is unchanged
-	 */
-	template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
-	inline auto getProperty(int index, int position) -> decltype(get<Type>(0))
-	{
-		duk_get_prop_index(m_handle.get(), index, position);
-		decltype(get<Type>(0)) value = get<Type>(-1);
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Get the property `name' and push it to the stack from the object at the specified index.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @note The stack contains the property value
-	 */
-	template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
-	inline void getProperty(int index, const std::string &name)
-	{
-		duk_get_prop_string(m_handle.get(), index, name.c_str());
-	}
-
-	/**
-	 * Get the property by index and push it to the stack from the object at the specified index.
-	 *
-	 * @param index the object index
-	 * @param position the position in the object
-	 * @note The stack contains the property value
-	 */
-	template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
-	inline void getProperty(int index, int position)
-	{
-		duk_get_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * Get an optional property `name` from the object at the specified index.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @param def the default value
-	 * @return the value or def
-	 * @note The stack is unchanged
-	 */
-	template <typename Type, typename DefaultValue>
-	inline auto optionalProperty(int index, const std::string &name, DefaultValue &&def) -> decltype(optional<Type>(0, std::forward<DefaultValue>(def)))
-	{
-		duk_get_prop_string(m_handle.get(), index, name.c_str());
-		decltype(optional<Type>(0, std::forward<DefaultValue>(def))) value = optional<Type>(-1, std::forward<DefaultValue>(def));
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Get an optional property by index, for arrays
-	 *
-	 * @param index the object index
-	 * @param position the position int the object
-	 * @param def the default value
-	 * @return the value or def
-	 * @note The stack is unchanged
-	 */
-	template <typename Type, typename DefaultValue>
-	inline auto optionalProperty(int index, int position, DefaultValue &&def) -> decltype(optional<Type>(0, std::forward<DefaultValue>(def)))
-	{
-		duk_get_prop_index(m_handle.get(), index, position);
-		decltype(optional<Type>(0, std::forward<DefaultValue>(def))) value = optional<Type>(-1, std::forward<DefaultValue>(def));
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Set a property to the object at the specified index.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @param value the value to forward
-	 * @note The stack is unchanged
-	 */
-	template <typename Type>
-	void putProperty(int index, const std::string &name, Type &&value)
-	{
-		index = duk_normalize_index(m_handle.get(), index);
-
-		push(std::forward<Type>(value));
-		duk_put_prop_string(m_handle.get(), index, name.c_str());
-	}
-
-	/**
-	 * Set a property by index, for arrays.
-	 *
-	 * @param index the object index
-	 * @param position the position in the object
-	 * @param value the value to forward
-	 * @note The stack is unchanged
-	 */
-	template <typename Type>
-	void putProperty(int index, int position, Type &&value)
-	{
-		index = duk_normalize_index(m_handle.get(), index);
-
-		push(std::forward<Type>(value));
-		duk_put_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * Put the value that is at the top of the stack as property to the object.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 */
-	inline void putProperty(int index, const std::string &name)
-	{
-		duk_put_prop_string(m_handle.get(), index, name.c_str());
-	}
-
-	/**
-	 * Put the value that is at the top of the stack to the object as index.
-	 *
-	 * @param index the object index
-	 * @param position the position in the object
-	 */
-	inline void putProperty(int index, int position)
-	{
-		duk_put_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * Get a global value.
-	 *
-	 * @param name the name of the global variable
-	 * @return the value
-	 */
-	template <typename Type>
-	inline auto getGlobal(const std::string &name, std::enable_if_t<!std::is_void<Type>::value> * = nullptr) -> decltype(get<Type>(0))
-	{
-		duk_get_global_string(m_handle.get(), name.c_str());
-		decltype(get<Type>(0)) value = get<Type>(-1);
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Overload that push the value at the top of the stack instead of returning it.
-	 */
-	template <typename Type>
-	inline void getGlobal(const std::string &name, std::enable_if_t<std::is_void<Type>::value> * = nullptr) noexcept
-	{
-		duk_get_global_string(m_handle.get(), name.c_str());
-	}
-
-	/**
-	 * Set a global variable.
-	 *
-	 * @param name the name of the global variable
-	 * @param type the value to set
-	 */
-	template <typename Type>
-	inline void putGlobal(const std::string &name, Type&& type)
-	{
-		push(std::forward<Type>(type));
-		duk_put_global_string(m_handle.get(), name.c_str());
-	}
-
-	/**
-	 * Put the value at the top of the stack as global property.
-	 *
-	 * @param name the property name
-	 */
-	inline void putGlobal(const std::string &name)
-	{
-		duk_put_global_string(m_handle.get(), name.c_str());
-	}
-
-	/*
-	 * Extra functions
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions are implemented for convenience and do not exists in the native Duktape API.
-	 */
-
-	/**
-	 * Get the error object when a JavaScript error has been thrown (e.g. eval failure).
-	 *
-	 * @param index the index
-	 * @return the information
-	 */
-	ErrorInfo error(int index);
-
-	/**
-	 * Enumerate an object or an array at the specified index.
-	 *
-	 * @param index the object or array index
-	 * @param flags the optional flags to pass to duk_enum
-	 * @param getvalue set to true if you want to extract the value
-	 * @param func the function to call for each properties
-	 */
-	template <typename Func>
-	void enumerate(int index, duk_uint_t flags, duk_bool_t getvalue, Func&& func)
-	{
-		duk_enum(m_handle.get(), index, flags);
-
-		while (duk_next(m_handle.get(), -1, getvalue)) {
-			func(*this);
-			duk_pop_n(m_handle.get(), 1 + (getvalue ? 1 : 0));
-		}
-
-		duk_pop(m_handle.get());
-	}
-
-	/**
-	 * Return the this binding of the current function.
-	 *
-	 * @return the this binding as the template given
-	 */
-	template <typename T>
-	inline auto self() -> decltype(TypeInfo<T>::get(*this, 0))
-	{
-		duk_push_this(m_handle.get());
-		decltype(TypeInfo<T>::get(*this, 0)) value = TypeInfo<T>::get(*this, -1);
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Throw an ECMAScript exception.
-	 *
-	 * @param ex the exception
-	 */
-	template <typename Exception>
-	void raise(const Exception &ex)
-	{
-		ex.create(m_handle.get());
-
-		duk_push_string(m_handle.get(), ex.name().c_str());
-		duk_put_prop_string(m_handle.get(), -2, "name");
-		duk_throw(m_handle.get());
-	}
-
-	/**
-	 * Construct the object in place, setting value as this binding.
-	 *
-	 * The TypeInfo<T> must have the following requirements:
-	 *
-	 * - static void construct(Context &, T): must update this with the value and keep the stack unchanged
-	 *
-	 * @param value the value to forward
-	 * @see self
-	 */
-	template <typename T>
-	inline void construct(T &&value)
-	{
-		TypeInfo<std::decay_t<T>>::construct(*this, std::forward<T>(value));
-	}
-};
-
-/* ------------------------------------------------------------------
- * Exception handling
- * ------------------------------------------------------------------ */
-
-/**
- * @class Error
- * @brief Base ECMAScript error class.
- * @warning Override the function create for your own exceptions
- */
-class Error {
-protected:
-	std::string m_name;	//!< Name of exception (e.g RangeError)
-	std::string m_message;	//!< The message
-
-	/**
-	 * Constructor with a type of error specified, specially designed for derived errors.
-	 *
-	 * @param name the error name (e.g RangeError)
-	 * @param message the message
-	 */
-	inline Error(std::string name, std::string message) noexcept
-		: m_name{std::move(name)}
-		, m_message{std::move(message)}
-	{
-	}
-
-public:
-	/**
-	 * Constructor with a message.
-	 *
-	 * @param message the message
-	 */
-	inline Error(std::string message) noexcept
-		: m_name{"Error"}
-		, m_message{std::move(message)}
-	{
-	}
-
-	/**
-	 * Get the error type (e.g RangeError).
-	 *
-	 * @return the name
-	 */
-	inline const std::string &name() const noexcept
-	{
-		return m_name;
-	}
-
-	/**
-	 * Create the exception on the stack.
-	 *
-	 * @note the default implementation search for the global variables
-	 * @param ctx the context
-	 */
-	virtual void create(ContextPtr ctx) const noexcept
-	{
-		duk_get_global_string(ctx, m_name.c_str());
-		duk_push_string(ctx, m_message.c_str());
-		duk_new(ctx, 1);
-	}
-};
-
-/**
- * @class EvalError
- * @brief Error in eval() function.
- */
-class EvalError : public Error {
-public:
-	/**
-	 * Construct an EvalError.
-	 *
-	 * @param message the message
-	 */
-	inline EvalError(std::string message) noexcept
-		: Error{"EvalError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class RangeError
- * @brief Value is out of range.
- */
-class RangeError : public Error {
-public:
-	/**
-	 * Construct an RangeError.
-	 *
-	 * @param message the message
-	 */
-	inline RangeError(std::string message) noexcept
-		: Error{"RangeError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class ReferenceError
- * @brief Trying to use a variable that does not exist.
- */
-class ReferenceError : public Error {
-public:
-	/**
-	 * Construct an ReferenceError.
-	 *
-	 * @param message the message
-	 */
-	inline ReferenceError(std::string message) noexcept
-		: Error{"ReferenceError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class SyntaxError
- * @brief Syntax error in the script.
- */
-class SyntaxError : public Error {
-public:
-	/**
-	 * Construct an SyntaxError.
-	 *
-	 * @param message the message
-	 */
-	inline SyntaxError(std::string message) noexcept
-		: Error{"SyntaxError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class TypeError
- * @brief Invalid type given.
- */
-class TypeError : public Error {
-public:
-	/**
-	 * Construct an TypeError.
-	 *
-	 * @param message the message
-	 */
-	inline TypeError(std::string message) noexcept
-		: Error{"TypeError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class URIError
- * @brief URI manipulation failure.
- */
-class URIError : public Error {
-public:
-	/**
-	 * Construct an URIError.
-	 *
-	 * @param message the message
-	 */
-	inline URIError(std::string message) noexcept
-		: Error{"URIError", std::move(message)}
-	{
-	}
-};
-
-/* ------------------------------------------------------------------
- * Standard overloads for TypeInfo<T>
- * ------------------------------------------------------------------ */
-
-/**
- * @class TypeInfo<int>
- * @brief Default implementation for int.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeInfo<int> {
-public:
-	/**
-	 * Get an integer, return 0 if not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the integer
-	 */
-	static inline int get(Context &ctx, int index)
-	{
-		return duk_get_int(ctx, index);
-	}
-
-	/**
-	 * Check if value is an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if integer
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_number(ctx, index);
-	}
-
-	/**
-	 * Get an integer, return defaultValue if the value is not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the integer or defaultValue
-	 */
-	static inline int optional(Context &ctx, int index, int defaultValue)
-	{
-		if (!duk_is_number(ctx, index)) {
-			return defaultValue;
-		}
-
-		return duk_get_int(ctx, index);
-	}
-
-	/**
-	 * Push an integer.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, int value)
-	{
-		duk_push_int(ctx, value);
-	}
-
-	/**
-	 * Require an integer, throws a JavaScript exception if not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the integer
-	 */
-	static inline int require(Context &ctx, int index)
-	{
-		return duk_require_int(ctx, index);
-	}
-};
-
-/**
- * @class TypeInfo<bool>
- * @brief Default implementation for bool.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeInfo<bool> {
-public:
-	/**
-	 * Get a boolean, return 0 if not a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the boolean
-	 */
-	static inline bool get(Context &ctx, int index)
-	{
-		return duk_get_boolean(ctx, index);
-	}
-
-	/**
-	 * Check if value is a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if boolean
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_boolean(ctx, index);
-	}
-
-	/**
-	 * Get a bool, return defaultValue if the value is not a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the boolean or defaultValue
-	 */
-	static inline bool optional(Context &ctx, int index, bool defaultValue)
-	{
-		if (!duk_is_boolean(ctx, index)) {
-			return defaultValue;
-		}
-
-		return duk_get_boolean(ctx, index);
-	}
-
-	/**
-	 * Push a boolean.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, bool value)
-	{
-		duk_push_boolean(ctx, value);
-	}
-
-	/**
-	 * Require a boolean, throws a JavaScript exception if not a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the boolean
-	 */
-	static inline bool require(Context &ctx, int index)
-	{
-		return duk_require_boolean(ctx, index);
-	}
-};
-
-/**
- * @class TypeInfo<double>
- * @brief Default implementation for double.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeInfo<double> {
-public:
-	/**
-	 * Get a double, return 0 if not a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the double
-	 */
-	static inline double get(Context &ctx, int index)
-	{
-		return duk_get_number(ctx, index);
-	}
-
-	/**
-	 * Check if value is a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if double
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_number(ctx, index);
-	}
-
-	/**
-	 * Get a double, return defaultValue if the value is not a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the double or defaultValue
-	 */
-	static inline double optional(Context &ctx, int index, double defaultValue)
-	{
-		if (!duk_is_number(ctx, index)) {
-			return defaultValue;
-		}
-
-		return duk_get_number(ctx, index);
-	}
-
-	/**
-	 * Push a double.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, double value)
-	{
-		duk_push_number(ctx, value);
-	}
-
-	/**
-	 * Require a double, throws a JavaScript exception if not a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the double
-	 */
-	static inline double require(Context &ctx, int index)
-	{
-		return duk_require_number(ctx, index);
-	}
-};
-
-/**
- * @class TypeInfo<std::string>
- * @brief Default implementation for std::string.
- *
- * Provides: get, is, optional, push, require.
- *
- * Note: the functions allows embedded '\0'.
- */
-template <>
-class TypeInfo<std::string> {
-public:
-	/**
-	 * Get a string, return 0 if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline std::string get(Context &ctx, int index)
-	{
-		duk_size_t size;
-		const char *text = duk_get_lstring(ctx, index, &size);
-
-		return std::string{text, size};
-	}
-
-	/**
-	 * Check if value is a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if string
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_string(ctx, index);
-	}
-
-	/**
-	 * Get a string, return defaultValue if the value is not an string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the string or defaultValue
-	 */
-	static inline std::string optional(Context &ctx, int index, std::string defaultValue)
-	{
-		if (!duk_is_string(ctx, index)) {
-			return defaultValue;
-		}
-
-		return get(ctx, index);
-	}
-
-	/**
-	 * Push a string.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, const std::string &value)
-	{
-		duk_push_lstring(ctx, value.c_str(), value.length());
-	}
-
-	/**
-	 * Require a string, throws a JavaScript exception if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline std::string require(Context &ctx, int index)
-	{
-		duk_size_t size;
-		const char *text = duk_require_lstring(ctx, index, &size);
-
-		return std::string{text, size};
-	}
-};
-
-/**
- * @class TypeInfo<const char *>
- * @brief Default implementation for const char literals.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeInfo<const char *> {
-public:
-	/**
-	 * Get a string, return 0 if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline const char *get(Context &ctx, int index)
-	{
-		return duk_get_string(ctx, index);
-	}
-
-	/**
-	 * Check if value is a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if string
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_string(ctx, index);
-	}
-
-	/**
-	 * Get an integer, return defaultValue if the value is not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the integer or defaultValue
-	 */
-	static inline const char *optional(Context &ctx, int index, const char *defaultValue)
-	{
-		if (!duk_is_string(ctx, index)) {
-			return defaultValue;
-		}
-
-		return duk_get_string(ctx, index);
-	}
-
-	/**
-	 * Push a string.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, const char *value)
-	{
-		duk_push_string(ctx, value);
-	}
-
-	/**
-	 * Require a string, throws a JavaScript exception if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline const char *require(Context &ctx, int index)
-	{
-		return duk_require_string(ctx, index);
-	}
-};
-
-/**
- * @brief Implementation for non-managed pointers.
- *
- * Provides: get, is, optional, push, require.
- */
-template <typename T>
-class TypeInfo<RawPointer<T>> {
-public:
-	/**
-	 * Get a pointer, return nullptr if not a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the pointer
-	 */
-	static inline T *get(Context &ctx, int index)
-	{
-		return static_cast<T *>(duk_to_pointer(ctx, index));
-	}
-
-	/**
-	 * Check if value is a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if pointer
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_pointer(ctx, index);
-	}
-
-	/**
-	 * Get a pointer, return defaultValue if the value is not a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the pointer or defaultValue
-	 */
-	static inline T *optional(Context &ctx, int index, RawPointer<T> defaultValue)
-	{
-		if (!duk_is_pointer(ctx, index)) {
-			return defaultValue.object;
-		}
-
-		return static_cast<T *>(duk_to_pointer(ctx, index));
-	}
-
-	/**
-	 * Push a pointer.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, const RawPointer<T> &value)
-	{
-		duk_push_pointer(ctx, value.object);
-	}
-
-	/**
-	 * Require a pointer, throws a JavaScript exception if not a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the pointer
-	 */
-	static inline T *require(Context &ctx, int index)
-	{
-		return static_cast<T *>(duk_require_pointer(ctx, index));
-	}
-};
-
-/**
- * @class TypeInfo<Function>
- * @brief Push C++ function to the stack.
- *
- * Provides: push.
- *
- * This implementation push a Duktape/C function that is wrapped as C++ for convenience.
- */
-template <>
-class TypeInfo<Function> {
-public:
-	/**
-	 * Push the C++ function, it is wrapped as Duktape/C function and allocated on the heap by moving the
-	 * std::function.
-	 *
-	 * @param ctx the context
-	 * @param fn the function
-	 */
-	static void push(Context &ctx, Function fn);
-};
-
-/**
- * @class TypeInfo<FunctionMap>
- * @brief Put the functions to the object at the top of the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeInfo<FunctionMap> {
-public:
-	/**
-	 * Push a map of function to the object at the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param map the map of function
-	 */
-	static inline void push(Context &ctx, const FunctionMap &map)
-	{
-		for (const auto &entry : map) {
-			ctx.putProperty(-1, entry.first, entry.second);
-		}
-	}
-};
-
-/**
- * @class TypeInfo<Object>
- * @brief Push empty object to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeInfo<Object> {
-public:
-	/**
-	 * Check if value is an object.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if object
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_object(ctx, index);
-	}
-
-	/**
-	 * Create an empty object on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Object &)
-	{
-		duk_push_object(ctx);
-	}
-};
-
-/**
- * @class TypeInfo<Array>
- * @brief Push empty array to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeInfo<Array> {
-public:
-	/**
-	 * Check if value is a array.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if array
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_array(ctx, index);
-	}
-
-	/**
-	 * Create an empty array on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Array &)
-	{
-		duk_push_array(ctx);
-	}
-};
-
-/**
- * @class TypeInfo<Undefined>
- * @brief Push undefined value to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeInfo<Undefined> {
-public:
-	/**
-	 * Check if value is undefined.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if undefined
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_undefined(ctx, index);
-	}
-
-	/**
-	 * Push undefined value on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Undefined &)
-	{
-		duk_push_undefined(ctx);
-	}
-};
-
-/**
- * @class TypeInfo<Null>
- * @brief Push null value to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeInfo<Null> {
-public:
-	/**
-	 * Check if value is null.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if null
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_null(ctx, index);
-	}
-
-	/**
-	 * Push null value on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Null &)
-	{
-		duk_push_null(ctx);
-	}
-};
-
-/**
- * @brief Push this binding into the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeInfo<This> {
-public:
-	/**
-	 * Push this function into the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const This &)
-	{
-		duk_push_this(ctx);
-	}
-};
-
-/**
- * @class TypeInfo<Global>
- * @brief Push the global object to the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeInfo<Global> {
-public:
-	/**
-	 * Push the global object into the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Global &)
-	{
-		duk_push_global_object(ctx);
-	}
-};
-
-/**
- * @brief Push a map of key-value pair as objects.
- *
- * Provides: push.
- *
- * This class is convenient for settings constants such as enums, string and such.
- */
-template <typename T>
-class TypeInfo<std::unordered_map<std::string, T>> {
-public:
-	/**
-	 * Put all values from the map as properties to the object at the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param map the values
-	 * @note You need an object at the top of the stack before calling this function
-	 */
-	static void push(Context &ctx, const std::unordered_map<std::string, T> &map)
-	{
-		for (const auto &pair : map) {
-			TypeInfo<T>::push(ctx, pair.second);
-			duk_put_prop_string(ctx, -2, pair.first.c_str());
-		}
-	}
-};
-
-/**
- * @brief Push or get vectors as JavaScript arrays.
- *
- * Provides: get, push.
- */
-template <typename T>
-class TypeInfo<std::vector<T>> {
-public:
-	/**
-	 * Get an array from the stack.
-	 *
-	 * @param ctx the context
-	 * @param index the array index
-	 * @return the array or empty array if the value is not an array
-	 */
-	static std::vector<T> get(Context &ctx, int index)
-	{
-		std::vector<T> result;
-
-		if (!duk_is_array(ctx, -1)) {
-			return result;
-		}
-
-		int total = duk_get_length(ctx, index);
-		for (int i = 0; i < total; ++i) {
-			result.push_back(ctx.getProperty<T>(index, i));
-		}
-
-		return result;
-	}
-
-	/**
-	 * Create an array with the specified values.
-	 *
-	 * @param ctx the context
-	 * @param array the values
-	 */
-	static void push(Context &ctx, const std::vector<T> &array)
-	{
-		duk_push_array(ctx);
-
-		int i = 0;
-		for (const auto &v : array) {
-			TypeInfo<T>::push(ctx, v);
-			duk_put_prop_index(ctx, -2, i++);
-		}
-	}
-};
-
-/**
- * @brief Implementation of managed shared_ptr
- * @see Shared
- */
-template <typename T>
-class TypeInfo<Shared<T>> {
-private:
-	static void apply(Context &ctx, std::shared_ptr<T> value)
-	{
-		duk_push_boolean(ctx, false);
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
-		duk_push_pointer(ctx, new std::shared_ptr<T>(value));
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-shared-ptr");
-		duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
-			duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-
-			if (!duk_to_boolean(ctx, -1)) {
-				duk_push_boolean(ctx, true);
-				duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-				duk_get_prop_string(ctx, 0, "\xff""\xff""js-shared-ptr");
-				delete static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
-				duk_pop(ctx);
-			}
-
-			duk_pop(ctx);
-
-			return 0;
-		}, 1);
-		duk_set_finalizer(ctx, -2);
-	}
-
-public:
-	/**
-	 * Construct the shared_ptr as this.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void construct(Context &ctx, Shared<T> value)
-	{
-		duk_push_this(ctx);
-		apply(ctx, std::move(value.object));
-		duk_pop(ctx);
-	}
-
-	/**
-	 * Push a managed shared_ptr as object.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void push(Context &ctx, Shared<T> value)
-	{
-		duk_push_object(ctx);
-		apply(ctx, value.object);
-		value.object->prototype(ctx);
-		duk_set_prototype(ctx, -2);
-	}
-
-	/**
-	 * Get a managed shared_ptr from the stack.
-	 *
-	 * @param ctx the context
-	 * @param index the object index
-	 * @return the shared_ptr
-	 */
-	static std::shared_ptr<T> get(Context &ctx, int index)
-	{
-		duk_get_prop_string(ctx, index, "\xff""\xff""js-shared-ptr");
-		std::shared_ptr<T> value = *static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
-		duk_pop(ctx);
-
-		return value;
-	}
-};
-
-/**
- * @brief Implementation of managed pointers
- * @see Pointer
- */
-template <typename T>
-class TypeInfo<Pointer<T>> {
-private:
-	static void apply(Context &ctx, T *value)
-	{
-		duk_push_boolean(ctx, false);
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
-		duk_push_pointer(ctx, value);
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-ptr");
-		duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
-			duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-
-			if (!duk_to_boolean(ctx, -1)) {
-				duk_push_boolean(ctx, true);
-				duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-				duk_get_prop_string(ctx, 0, "\xff""\xff""js-ptr");
-				delete static_cast<T *>(duk_to_pointer(ctx, -1));
-				duk_pop(ctx);
-			}
-
-			duk_pop(ctx);
-
-			return 0;
-		}, 1);
-		duk_set_finalizer(ctx, -2);
-	}
-
-public:
-	/**
-	 * Construct the pointer as this.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void construct(Context &ctx, Pointer<T> value)
-	{
-		duk_push_this(ctx);
-		apply(ctx, value.object);
-		duk_pop(ctx);
-	}
-
-	/**
-	 * Push a managed pointer as object.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void push(Context &ctx, Pointer<T> value)
-	{
-		duk_push_object(ctx);
-		apply(ctx, value.object);
-		value.object->prototype(ctx);
-		duk_set_prototype(ctx, -2);
-	}
-
-	/**
-	 * Get a managed pointer from the stack.
-	 *
-	 * @param ctx the context
-	 * @param index the object index
-	 * @return the pointer
-	 * @warning Do not store the pointer into the C++ side, the object can be deleted at any time
-	 */
-	static T *get(Context &ctx, int index)
-	{
-		duk_get_prop_string(ctx, index, "\xff""\xff""js-ptr");
-		T *value = static_cast<T *>(duk_to_pointer(ctx, -1));
-		duk_pop(ctx);
-
-		return value;
-	}
-};
-
-} // !js
-
-#endif // !_JS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Js/js.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,107 @@
+/*
+ * js.cpp -- JavaScript C++14 wrapper for Duktape
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "js.h"
+
+using namespace std::string_literals;
+
+namespace js {
+
+ErrorInfo Context::error(int index)
+{
+	ErrorInfo error;
+
+	index = duk_normalize_index(m_handle.get(), index);
+
+	duk_get_prop_string(m_handle.get(), index, "name");
+	error.name = duk_to_string(m_handle.get(), -1);
+	duk_get_prop_string(m_handle.get(), index, "message");
+	error.message = duk_to_string(m_handle.get(), -1);
+	duk_get_prop_string(m_handle.get(), index, "fileName");
+	error.fileName = duk_to_string(m_handle.get(), -1);
+	duk_get_prop_string(m_handle.get(), index, "lineNumber");
+	error.lineNumber = duk_to_int(m_handle.get(), -1);
+	duk_get_prop_string(m_handle.get(), index, "stack");
+	error.stack = duk_to_string(m_handle.get(), -1);
+	duk_pop_n(m_handle.get(), 5);
+
+	return error;
+}
+
+void Context::pcall(unsigned nargs)
+{
+	if (duk_pcall(m_handle.get(), nargs) != 0) {
+		ErrorInfo info = error(-1);
+		duk_pop(m_handle.get());
+
+		throw info;
+	}
+}
+
+void Context::peval()
+{
+	if (duk_peval(m_handle.get()) != 0) {
+		ErrorInfo info = error(-1);
+		duk_pop(m_handle.get());
+
+		throw info;
+	}
+}
+
+void TypeInfo<Function>::push(Context &ctx, Function fn)
+{
+	/* 1. Push function wrapper */
+	duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
+		Context context{ctx};
+
+		duk_push_current_function(ctx);
+		duk_get_prop_string(ctx, -1, "\xff""\xff""js-func");
+		Function *f = static_cast<Function *>(duk_to_pointer(ctx, -1));
+		duk_pop_2(ctx);
+
+		return static_cast<duk_ret_t>(f->function(context));
+	}, fn.nargs);
+
+	/* 2. Store the moved function */
+	duk_push_pointer(ctx, new Function(std::move(fn)));
+	duk_put_prop_string(ctx, -2, "\xff""\xff""js-func");
+
+	/* 3. Store deletion flags */
+	duk_push_boolean(ctx, false);
+	duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
+
+	/* 4. Push and set a finalizer */
+	duk_push_c_function(ctx, [] (duk_context *ctx) {
+		duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+
+		if (!duk_to_boolean(ctx, -1)) {
+			duk_push_boolean(ctx, true);
+			duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+			duk_get_prop_string(ctx, 0, "\xff""\xff""js-func");
+			delete static_cast<Function *>(duk_to_pointer(ctx, -1));
+			duk_pop(ctx);
+		}
+
+		duk_pop(ctx);
+
+		return 0;
+	}, 1);
+	duk_set_finalizer(ctx, -2);
+}
+
+} // !js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Js/js.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,2105 @@
+/*
+ * js.h -- JavaScript C++14 wrapper for Duktape
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _JS_H_
+#define _JS_H_
+
+/**
+ * @file js.h
+ * @brief Bring JavaScript using Duktape
+ *
+ * This file provides usual Duktape function renamed and placed into `js` namespace. It also replaces error
+ * code with exceptions when possible.
+ *
+ * For convenience, this file also provides templated functions, overloads and much more.
+ */
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <duktape.h>
+
+/**
+ * Duktape C++ namespace wrapper.
+ */
+namespace js {
+
+class Context;
+
+/**
+ * Typedef for readability.
+ */
+using ContextPtr = duk_context *;
+
+/*
+ * Basic types to manipulate with the stack
+ * ------------------------------------------------------------------
+ *
+ * The following types can be used in some of the operations like Context::push or Context::is, they are defined
+ * usually as empty classes to determine the appropriate action to execute.
+ *
+ * For example, `ctx.push(js::Object{})` will push an empty object into the stack.
+ */
+
+/**
+ * @class Object
+ * @brief Empty class tag for push() function.
+ */
+class Object {
+};
+
+/**
+ * @class Array
+ * @brief Empty class tag for push() function.
+ */
+class Array {
+};
+
+/**
+ * @class Global
+ * @brief Empty class tag to push the global object.
+ */
+class Global {
+};
+
+/**
+ * @class Undefined
+ * @brief Empty class tag to push undefined to the stack.
+ */
+class Undefined {
+};
+
+/**
+ * @class Null
+ * @brief Empty class tag to push null to the stack.
+ */
+class Null {
+};
+
+/**
+ * @class This
+ * @brief Empty class tag to push this binding to the stack.
+ */
+class This {
+};
+
+/**
+ * @class RawPointer
+ * @brief Push a non-managed pointer to Duktape, the pointer will never be deleted.
+ * @note For a managed pointer with prototype, see Pointer
+ */
+template <typename T>
+class RawPointer {
+public:
+	/**
+	 * The pointer to push.
+	 */
+	T *object;
+};
+
+/*
+ * Extended type manipulation
+ * ------------------------------------------------------------------
+ *
+ * The following types are different as there are no equivalent in the native Duktape API, they are available for
+ * convenience.
+ */
+
+/**
+ * @brief Manage shared_ptr from C++ and JavaScript
+ *
+ * This class allowed you to push and retrieve shared_ptr from C++ and JavaScript without taking care of ownership
+ * and deletion.
+ *
+ * The only requirement is to have the function `void prototype(Context &ctx)` in your class T.
+ */
+template <typename T>
+class Shared {
+public:
+	/**
+	 * The shared object.
+	 */
+	std::shared_ptr<T> object;
+};
+
+/**
+ * @brief Manage pointers from C++ and JavaScript
+ *
+ * This class allowed you to push and retrieve C++ pointers from C++ and JavaScript. The object will be deleted when
+ * the JavaScript garbage collectors collect them so never store a pointer created with this.
+ *
+ * The only requirement is to have the function `void prototype(Context &ctx)` in your class T.
+ */
+template <typename T>
+class Pointer {
+public:
+	/**
+	 * The object.
+	 */
+	T *object{nullptr};
+};
+
+/**
+ * @class Function
+ * @brief Duktape/C function definition.
+ *
+ * This class wraps the std::function as a Duktape/C function by storing a copied pointer.
+ */
+class Function {
+public:
+	/**
+	 * The function pointer, must not be null.
+	 */
+	std::function<int (Context &)> function;
+
+	/**
+	 * Number of args that the function takes
+	 */
+	int nargs{0};
+};
+
+/**
+ * Map of functions to set on an object.
+ */
+using FunctionMap = std::unordered_map<std::string, Function>;
+
+/**
+ * Map of string to type, ideal for setting constants like enums.
+ */
+template <typename Type>
+using Map = std::unordered_map<std::string, Type>;
+
+/**
+ * @class ErrorInfo
+ * @brief Error description.
+ *
+ * This class fills the fields got in an Error object.
+ */
+class ErrorInfo : public std::exception {
+public:
+	std::string name;		//!< name of error
+	std::string message;		//!< error message
+	std::string stack;		//!< stack if available
+	std::string fileName;		//!< filename if applicable
+	int lineNumber{0};		//!< line number if applicable
+
+	/**
+	 * Get the error message. This effectively returns message field.
+	 *
+	 * @return the message
+	 */
+	const char *what() const noexcept override
+	{
+		return message.c_str();
+	}
+};
+
+/**
+ * @class TypeInfo
+ * @brief Type information to implement new types in JavaScript's context.
+ *
+ * This class depending on your needs may have the following functions:
+ *
+ * - `static void construct(Context &ctx, Type value)`
+ * - `static Type get(Context &ctx, int index)`
+ * - `static bool is(Context &ctx, int index)`
+ * - `static Type optional(Context &ctx, int index, Type defaultValue)`
+ * - `static void push(Context &ctx, Type value)`
+ * - `static Type require(Context &ctx, int index)`
+ *
+ * The `construct` function is used in Context::construct to build a new value as this (e.g. constructors).
+ *
+ * The `get` function is used in Context::get, Context::getProperty, Context::getGlobal to retrieve a value from the
+ * stack.
+ *
+ * The `is` function is used in Context::is to check if the value on the stack is of type `Type`.
+ *
+ * The `optional` function is used in Context::optional to get a value or a replacement if not applicable.
+ *
+ * The `push` function is used in Context::push to usually create a new value on the stack but some specializations
+ * may not (e.g. FunctionMap).
+ *
+ * The `require` function is used in Context::require to get a value from the stack or raise a JavaScript exception if
+ * not applicable.
+ *
+ * This class is fully specialized for: `bool`, `const char *`, `double`, `int`, `std::string`.
+ *
+ * It is also partially specialized for : `Global`, `Object`, `Array`, `Undefined`, `Null`, `std::vector<Type>`.
+ */
+template <typename Type>
+class TypeInfo {
+};
+
+/**
+ * @class File
+ * @brief Evaluate script from file.
+ * @see Context::eval
+ * @see Context::peval
+ */
+class File {
+public:
+	/**
+	 * Path to the file.
+	 */
+	std::string path;
+
+	/**
+	 * Evaluate the file.
+	 *
+	 * @param ctx the context
+	 */
+	inline void eval(duk_context *ctx)
+	{
+		duk_eval_file(ctx, path.c_str());
+	}
+
+	/**
+	 * Evaluate in protected mode the file.
+	 *
+	 * @param ctx the context
+	 */
+	inline int peval(duk_context *ctx)
+	{
+		return duk_peval_file(ctx, path.c_str());
+	}
+};
+
+/**
+ * @class Script
+ * @brief Evaluate script from raw text.
+ * @see Context::eval
+ * @see Context::peval
+ */
+class Script {
+public:
+	/**
+	 * The script content.
+	 */
+	std::string text;
+
+	/**
+	 * Evaluate the script.
+	 *
+	 * @param ctx the context
+	 */
+	inline void eval(duk_context *ctx)
+	{
+		duk_eval_string(ctx, text.c_str());
+	}
+
+	/**
+	 * Evaluate in protected mode the script.
+	 *
+	 * @param ctx the context
+	 */
+	inline int peval(duk_context *ctx)
+	{
+		return duk_peval_string(ctx, text.c_str());
+	}
+};
+
+/**
+ * @class Context
+ * @brief RAII based Duktape handler.
+ *
+ * This class is implicitly convertible to duk_context for convenience.
+ */
+class Context {
+private:
+	using Deleter = void (*)(duk_context *);
+	using Handle = std::unique_ptr<duk_context, Deleter>;
+
+	Handle m_handle;
+
+	/* Move and copy forbidden */
+	Context(const Context &) = delete;
+	Context &operator=(const Context &) = delete;
+	Context(const Context &&) = delete;
+	Context &operator=(const Context &&) = delete;
+
+public:
+	/**
+	 * Create default context.
+	 */
+	inline Context()
+		: m_handle{duk_create_heap_default(), duk_destroy_heap}
+	{
+	}
+
+	/**
+	 * Create borrowed context that will not be deleted.
+	 *
+	 * @param ctx the pointer to duk_context
+	 */
+	inline Context(ContextPtr ctx) noexcept
+		: m_handle{ctx, [] (ContextPtr) {}}
+	{
+	}
+
+	/**
+	 * Convert the context to the native Duktape/C type.
+	 *
+	 * @return the duk_context
+	 */
+	inline operator duk_context *() noexcept
+	{
+		return m_handle.get();
+	}
+
+	/**
+	 * Convert the context to the native Duktape/C type.
+	 *
+	 * @return the duk_context
+	 */
+	inline operator duk_context *() const noexcept
+	{
+		return m_handle.get();
+	}
+
+	/*
+	 * Basic functions
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions are just standard wrappers around the native Duktape C functions, they are
+	 * defined with the same signature except that for convenience some parameters have default sane values.
+	 */
+
+	/**
+	 * Call the object at the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param nargs the number of arguments
+	 * @note Non-protected
+	 */
+	inline void call(unsigned nargs = 0)
+	{
+		duk_call(m_handle.get(), nargs);
+	}
+
+	/**
+	 * Copy a value from from to to, overwriting the previous value. If either index is invalid, throws an error.
+	 *
+	 * @param from the from index
+	 * @param to the destination
+	 */
+	inline void copy(int from, int to)
+	{
+		duk_copy(m_handle.get(), from, to);
+	}
+
+	/**
+	 * Define a property.
+	 *
+	 * @param index the object index
+	 * @param flags the flags
+	 * @note Wrapper of duk_def_prop
+	 */
+	inline void defineProperty(int index, int flags)
+	{
+		duk_def_prop(m_handle.get(), index, flags);
+	}
+
+	/**
+	 * Delete a property.
+	 *
+	 * @param index the object index
+	 * @return true if deleted
+	 * @note Wrapper of duk_del_prop
+	 */
+	inline bool deleteProperty(int index)
+	{
+		return duk_del_prop(m_handle.get(), index);
+	}
+
+	/**
+	 * Delete a property by index.
+	 *
+	 * @param index the object index
+	 * @param position the property index
+	 * @return true if deleted
+	 * @note Wrapper of duk_del_prop_index
+	 */
+	inline bool deleteProperty(int index, int position)
+	{
+		return duk_del_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * Delete a property by name.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @return true if deleted
+	 * @note Wrapper of duk_del_prop_string
+	 */
+	inline bool deleteProperty(int index, const std::string &name)
+	{
+		return duk_del_prop_string(m_handle.get(), index, name.c_str());
+	}
+
+	/**
+	 * Push a duplicate of value at from_index to the stack. If from_index is invalid, throws an error.
+	 *
+	 * @param index the value to copy
+	 * @note Wrapper of duk_dup
+	 */
+	inline void dup(int index = -1)
+	{
+		duk_dup(m_handle.get(), index);
+	}
+
+	/**
+	 * Evaluate a non-protected chunk that is at the top of the stack.
+	 */
+	inline void eval()
+	{
+		duk_eval(m_handle.get());
+	}
+
+	/**
+	 * Check if the object as a property.
+	 *
+	 * @param index the object index
+	 * @return true if has
+	 * @note Wrapper of duk_has_prop
+	 */
+	inline bool hasProperty(int index)
+	{
+		return duk_has_prop(m_handle.get(), index);
+	}
+
+	/**
+	 * Check if the object as a property by index.
+	 *
+	 * @param index the object index
+	 * @param position the property index
+	 * @return true if has
+	 * @note Wrapper of duk_has_prop_index
+	 */
+	inline bool hasProperty(int index, int position)
+	{
+		return duk_has_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * Check if the object as a property by string
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @return true if has
+	 * @note Wrapper of duk_has_prop_string
+	 */
+	inline bool hasProperty(int index, const std::string &name)
+	{
+		return duk_has_prop_string(m_handle.get(), index, name.c_str());
+	}
+
+	/**
+	 * Check if idx1 is an instance of idx2.
+	 *
+	 * @param ctx the context
+	 * @param idx1 the value to test
+	 * @param idx2 the instance requested
+	 * @return true if idx1 is instance of idx2
+	 * @note Wrapper of duk_instanceof
+	 */
+	inline bool instanceof(int idx1, int idx2)
+	{
+		return duk_instanceof(m_handle.get(), idx1, idx2);
+	}
+
+	/**
+	 * Insert a value at to with a value popped from the stack top. The previous value at to and any values above
+	 * it are moved up the stack by a step. If to is an invalid index, throws an error.
+	 *
+	 * @note Negative indices are evaluated prior to popping the value at the stack top
+	 * @param to the destination
+	 * @note Wrapper of duk_insert
+	 */
+	inline void insert(int to)
+	{
+		duk_insert(m_handle.get(), to);
+	}
+
+	/**
+	 * Pop a certain number of values from the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param count the number of values to pop
+	 * @note Wrapper of duk_pop_n
+	 */
+	inline void pop(unsigned count = 1)
+	{
+		duk_pop_n(m_handle.get(), count);
+	}
+
+	/**
+	 * Remove value at index. Elements above index are shifted down the stack by a step. If to is an invalid index,
+	 * throws an error.
+	 *
+	 * @param index the value to remove
+	 * @note Wrapper of duk_remove
+	 */
+	inline void remove(int index)
+	{
+		duk_remove(m_handle.get(), index);
+	}
+
+	/**
+	 * Replace value at to_index with a value popped from the stack top. If to_index is an invalid index,
+	 * throws an error.
+	 *
+	 * @param index the value to replace by the value at the top of the stack
+	 * @note Negative indices are evaluated prior to popping the value at the stack top.
+	 * @note Wrapper of duk_replace
+	 */
+	inline void replace(int index)
+	{
+		duk_replace(m_handle.get(), index);
+	}
+
+	/**
+	 * Swap values at indices index1 and index2. If the indices are the same, the call is a no-op. If either index
+	 * is invalid, throws an error.
+	 *
+	 * @param index1 the first index
+	 * @param index2 the second index
+	 * @note Wrapper of duk_swap
+	 */
+	inline void swap(int index1, int index2)
+	{
+		duk_swap(m_handle.get(), index1, index2);
+	}
+
+	/**
+	 * Get the current stack size.
+	 *
+	 * @param ctx the context
+	 * @return the stack size
+	 * @note Wrapper of duk_get_top
+	 */
+	inline int top() noexcept
+	{
+		return duk_get_top(m_handle.get());
+	}
+
+	/**
+	 * Get the type of the value at the specified index.
+	 *
+	 * @param ctx the context
+	 * @param index the idnex
+	 * @return the type
+	 * @note Wrapper of duk_get_type
+	 */
+	inline int type(int index) noexcept
+	{
+		return duk_get_type(m_handle.get(), index);
+	}
+
+	/*
+	 * Extended native functions
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions have different behaviour than the original native Duktape C functions, see their
+	 * descriptions for more information
+	 */
+
+	/**
+	 * Call in protected mode the object at the top of the stack.
+	 *
+	 * @param nargs the number of arguments
+	 * @throw ErrorInfo on errors
+	 * @note Wrapper of duk_pcall
+	 */
+	void pcall(unsigned nargs = 0);
+
+	/**
+	 * Evaluate a non-protected source.
+	 *
+	 * @param source the source
+	 * @see File
+	 * @see Script
+	 * @note Wrapper of duk_eval
+	 */
+	template <typename Source>
+	inline void eval(Source &&source)
+	{
+		source.eval(m_handle.get());
+	}
+
+	/**
+	 * Evaluate a protected chunk that is at the top of the stack.
+	 *
+	 * @throw ErrorInfo the error
+	 * @note Wrapper of duk_peval
+	 */
+	void peval();
+
+	/**
+	 * Evaluate a protected source.
+	 *
+	 * @param source the source
+	 * @see File
+	 * @see Script
+	 * @throw ErrorInfo on failure
+	 * @note Wrapper of duk_peval
+	 */
+	template <typename Source>
+	inline void peval(Source &&source)
+	{
+		if (source.peval(m_handle.get()) != 0) {
+			ErrorInfo info = error(-1);
+			duk_pop(m_handle.get());
+
+			throw info;
+		}
+	}
+
+	/*
+	 * Push / Get / Require / Is / Optional
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions are used to push, get or check values from the stack. They use specialization
+	 * of TypeInfo class.
+	 */
+
+	/**
+	 * Push a value into the stack. Calls TypeInfo<T>::push(*this, value);
+	 *
+	 * @param value the value to forward
+	 */
+	template <typename Type>
+	inline void push(Type &&value)
+	{
+		TypeInfo<std::decay_t<Type>>::push(*this, std::forward<Type>(value));
+	}
+
+	/**
+	 * Generic template function to get a value from the stack.
+	 *
+	 * @param index the index
+	 * @return the value
+	 */
+	template <typename Type>
+	inline auto get(int index) -> decltype(TypeInfo<Type>::get(*this, 0))
+	{
+		return TypeInfo<Type>::get(*this, index);
+	}
+
+	/**
+	 * Require a type at the specified index.
+	 *
+	 * @param index the index
+	 * @return the value
+	 */
+	template <typename Type>
+	inline auto require(int index) -> decltype(TypeInfo<Type>::require(*this, 0))
+	{
+		return TypeInfo<Type>::require(*this, index);
+	}
+
+	/**
+	 * Check if a value is a type of T.
+	 *
+	 * The TypeInfo<T> must have `static bool is(ContextPtr ptr, int index)`.
+	 *
+	 * @param index the value index
+	 * @return true if is the type
+	 */
+	template <typename T>
+	inline bool is(int index)
+	{
+		return TypeInfo<T>::is(*this, index);
+	}
+
+	/**
+	 * Get an optional value from the stack, if the value is not available of not the correct type,
+	 * return defaultValue instead.
+	 *
+	 * The TypeInfo<T> must have `static T optional(Context &, int index, T &&defaultValue)`.
+	 *
+	 * @param index the value index
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename Type>
+	inline auto optional(int index, Type &&defaultValue)
+	{
+		return TypeInfo<std::decay_t<Type>>::optional(*this, index, std::forward<Type>(defaultValue));
+	}
+
+	/*
+	 * Properties management
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions are used to read or set properties on objects or globals also using TypeInfo.
+	 */
+
+	/**
+	 * Get the property `name' as value from the object at the specified index.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @return the value
+	 * @note The stack is unchanged
+	 */
+	template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
+	inline auto getProperty(int index, const std::string &name) -> decltype(get<Type>(0))
+	{
+		duk_get_prop_string(m_handle.get(), index, name.c_str());
+		decltype(get<Type>(0)) value = get<Type>(-1);
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Get a property by index, for arrays.
+	 *
+	 * @param index the object index
+	 * @param position the position int the object
+	 * @return the value
+	 * @note The stack is unchanged
+	 */
+	template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
+	inline auto getProperty(int index, int position) -> decltype(get<Type>(0))
+	{
+		duk_get_prop_index(m_handle.get(), index, position);
+		decltype(get<Type>(0)) value = get<Type>(-1);
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Get the property `name' and push it to the stack from the object at the specified index.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @note The stack contains the property value
+	 */
+	template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
+	inline void getProperty(int index, const std::string &name)
+	{
+		duk_get_prop_string(m_handle.get(), index, name.c_str());
+	}
+
+	/**
+	 * Get the property by index and push it to the stack from the object at the specified index.
+	 *
+	 * @param index the object index
+	 * @param position the position in the object
+	 * @note The stack contains the property value
+	 */
+	template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
+	inline void getProperty(int index, int position)
+	{
+		duk_get_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * Get an optional property `name` from the object at the specified index.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @param def the default value
+	 * @return the value or def
+	 * @note The stack is unchanged
+	 */
+	template <typename Type, typename DefaultValue>
+	inline auto optionalProperty(int index, const std::string &name, DefaultValue &&def) -> decltype(optional<Type>(0, std::forward<DefaultValue>(def)))
+	{
+		duk_get_prop_string(m_handle.get(), index, name.c_str());
+		decltype(optional<Type>(0, std::forward<DefaultValue>(def))) value = optional<Type>(-1, std::forward<DefaultValue>(def));
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Get an optional property by index, for arrays
+	 *
+	 * @param index the object index
+	 * @param position the position int the object
+	 * @param def the default value
+	 * @return the value or def
+	 * @note The stack is unchanged
+	 */
+	template <typename Type, typename DefaultValue>
+	inline auto optionalProperty(int index, int position, DefaultValue &&def) -> decltype(optional<Type>(0, std::forward<DefaultValue>(def)))
+	{
+		duk_get_prop_index(m_handle.get(), index, position);
+		decltype(optional<Type>(0, std::forward<DefaultValue>(def))) value = optional<Type>(-1, std::forward<DefaultValue>(def));
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Set a property to the object at the specified index.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @param value the value to forward
+	 * @note The stack is unchanged
+	 */
+	template <typename Type>
+	void putProperty(int index, const std::string &name, Type &&value)
+	{
+		index = duk_normalize_index(m_handle.get(), index);
+
+		push(std::forward<Type>(value));
+		duk_put_prop_string(m_handle.get(), index, name.c_str());
+	}
+
+	/**
+	 * Set a property by index, for arrays.
+	 *
+	 * @param index the object index
+	 * @param position the position in the object
+	 * @param value the value to forward
+	 * @note The stack is unchanged
+	 */
+	template <typename Type>
+	void putProperty(int index, int position, Type &&value)
+	{
+		index = duk_normalize_index(m_handle.get(), index);
+
+		push(std::forward<Type>(value));
+		duk_put_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * Put the value that is at the top of the stack as property to the object.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 */
+	inline void putProperty(int index, const std::string &name)
+	{
+		duk_put_prop_string(m_handle.get(), index, name.c_str());
+	}
+
+	/**
+	 * Put the value that is at the top of the stack to the object as index.
+	 *
+	 * @param index the object index
+	 * @param position the position in the object
+	 */
+	inline void putProperty(int index, int position)
+	{
+		duk_put_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * Get a global value.
+	 *
+	 * @param name the name of the global variable
+	 * @return the value
+	 */
+	template <typename Type>
+	inline auto getGlobal(const std::string &name, std::enable_if_t<!std::is_void<Type>::value> * = nullptr) -> decltype(get<Type>(0))
+	{
+		duk_get_global_string(m_handle.get(), name.c_str());
+		decltype(get<Type>(0)) value = get<Type>(-1);
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Overload that push the value at the top of the stack instead of returning it.
+	 */
+	template <typename Type>
+	inline void getGlobal(const std::string &name, std::enable_if_t<std::is_void<Type>::value> * = nullptr) noexcept
+	{
+		duk_get_global_string(m_handle.get(), name.c_str());
+	}
+
+	/**
+	 * Set a global variable.
+	 *
+	 * @param name the name of the global variable
+	 * @param type the value to set
+	 */
+	template <typename Type>
+	inline void putGlobal(const std::string &name, Type&& type)
+	{
+		push(std::forward<Type>(type));
+		duk_put_global_string(m_handle.get(), name.c_str());
+	}
+
+	/**
+	 * Put the value at the top of the stack as global property.
+	 *
+	 * @param name the property name
+	 */
+	inline void putGlobal(const std::string &name)
+	{
+		duk_put_global_string(m_handle.get(), name.c_str());
+	}
+
+	/*
+	 * Extra functions
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions are implemented for convenience and do not exists in the native Duktape API.
+	 */
+
+	/**
+	 * Get the error object when a JavaScript error has been thrown (e.g. eval failure).
+	 *
+	 * @param index the index
+	 * @return the information
+	 */
+	ErrorInfo error(int index);
+
+	/**
+	 * Enumerate an object or an array at the specified index.
+	 *
+	 * @param index the object or array index
+	 * @param flags the optional flags to pass to duk_enum
+	 * @param getvalue set to true if you want to extract the value
+	 * @param func the function to call for each properties
+	 */
+	template <typename Func>
+	void enumerate(int index, duk_uint_t flags, duk_bool_t getvalue, Func&& func)
+	{
+		duk_enum(m_handle.get(), index, flags);
+
+		while (duk_next(m_handle.get(), -1, getvalue)) {
+			func(*this);
+			duk_pop_n(m_handle.get(), 1 + (getvalue ? 1 : 0));
+		}
+
+		duk_pop(m_handle.get());
+	}
+
+	/**
+	 * Return the this binding of the current function.
+	 *
+	 * @return the this binding as the template given
+	 */
+	template <typename T>
+	inline auto self() -> decltype(TypeInfo<T>::get(*this, 0))
+	{
+		duk_push_this(m_handle.get());
+		decltype(TypeInfo<T>::get(*this, 0)) value = TypeInfo<T>::get(*this, -1);
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Throw an ECMAScript exception.
+	 *
+	 * @param ex the exception
+	 */
+	template <typename Exception>
+	void raise(const Exception &ex)
+	{
+		ex.create(m_handle.get());
+
+		duk_push_string(m_handle.get(), ex.name().c_str());
+		duk_put_prop_string(m_handle.get(), -2, "name");
+		duk_throw(m_handle.get());
+	}
+
+	/**
+	 * Construct the object in place, setting value as this binding.
+	 *
+	 * The TypeInfo<T> must have the following requirements:
+	 *
+	 * - static void construct(Context &, T): must update this with the value and keep the stack unchanged
+	 *
+	 * @param value the value to forward
+	 * @see self
+	 */
+	template <typename T>
+	inline void construct(T &&value)
+	{
+		TypeInfo<std::decay_t<T>>::construct(*this, std::forward<T>(value));
+	}
+};
+
+/* ------------------------------------------------------------------
+ * Exception handling
+ * ------------------------------------------------------------------ */
+
+/**
+ * @class Error
+ * @brief Base ECMAScript error class.
+ * @warning Override the function create for your own exceptions
+ */
+class Error {
+protected:
+	std::string m_name;	//!< Name of exception (e.g RangeError)
+	std::string m_message;	//!< The message
+
+	/**
+	 * Constructor with a type of error specified, specially designed for derived errors.
+	 *
+	 * @param name the error name (e.g RangeError)
+	 * @param message the message
+	 */
+	inline Error(std::string name, std::string message) noexcept
+		: m_name{std::move(name)}
+		, m_message{std::move(message)}
+	{
+	}
+
+public:
+	/**
+	 * Constructor with a message.
+	 *
+	 * @param message the message
+	 */
+	inline Error(std::string message) noexcept
+		: m_name{"Error"}
+		, m_message{std::move(message)}
+	{
+	}
+
+	/**
+	 * Get the error type (e.g RangeError).
+	 *
+	 * @return the name
+	 */
+	inline const std::string &name() const noexcept
+	{
+		return m_name;
+	}
+
+	/**
+	 * Create the exception on the stack.
+	 *
+	 * @note the default implementation search for the global variables
+	 * @param ctx the context
+	 */
+	virtual void create(ContextPtr ctx) const noexcept
+	{
+		duk_get_global_string(ctx, m_name.c_str());
+		duk_push_string(ctx, m_message.c_str());
+		duk_new(ctx, 1);
+	}
+};
+
+/**
+ * @class EvalError
+ * @brief Error in eval() function.
+ */
+class EvalError : public Error {
+public:
+	/**
+	 * Construct an EvalError.
+	 *
+	 * @param message the message
+	 */
+	inline EvalError(std::string message) noexcept
+		: Error{"EvalError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class RangeError
+ * @brief Value is out of range.
+ */
+class RangeError : public Error {
+public:
+	/**
+	 * Construct an RangeError.
+	 *
+	 * @param message the message
+	 */
+	inline RangeError(std::string message) noexcept
+		: Error{"RangeError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class ReferenceError
+ * @brief Trying to use a variable that does not exist.
+ */
+class ReferenceError : public Error {
+public:
+	/**
+	 * Construct an ReferenceError.
+	 *
+	 * @param message the message
+	 */
+	inline ReferenceError(std::string message) noexcept
+		: Error{"ReferenceError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class SyntaxError
+ * @brief Syntax error in the script.
+ */
+class SyntaxError : public Error {
+public:
+	/**
+	 * Construct an SyntaxError.
+	 *
+	 * @param message the message
+	 */
+	inline SyntaxError(std::string message) noexcept
+		: Error{"SyntaxError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class TypeError
+ * @brief Invalid type given.
+ */
+class TypeError : public Error {
+public:
+	/**
+	 * Construct an TypeError.
+	 *
+	 * @param message the message
+	 */
+	inline TypeError(std::string message) noexcept
+		: Error{"TypeError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class URIError
+ * @brief URI manipulation failure.
+ */
+class URIError : public Error {
+public:
+	/**
+	 * Construct an URIError.
+	 *
+	 * @param message the message
+	 */
+	inline URIError(std::string message) noexcept
+		: Error{"URIError", std::move(message)}
+	{
+	}
+};
+
+/* ------------------------------------------------------------------
+ * Standard overloads for TypeInfo<T>
+ * ------------------------------------------------------------------ */
+
+/**
+ * @class TypeInfo<int>
+ * @brief Default implementation for int.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeInfo<int> {
+public:
+	/**
+	 * Get an integer, return 0 if not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the integer
+	 */
+	static inline int get(Context &ctx, int index)
+	{
+		return duk_get_int(ctx, index);
+	}
+
+	/**
+	 * Check if value is an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if integer
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_number(ctx, index);
+	}
+
+	/**
+	 * Get an integer, return defaultValue if the value is not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the integer or defaultValue
+	 */
+	static inline int optional(Context &ctx, int index, int defaultValue)
+	{
+		if (!duk_is_number(ctx, index)) {
+			return defaultValue;
+		}
+
+		return duk_get_int(ctx, index);
+	}
+
+	/**
+	 * Push an integer.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, int value)
+	{
+		duk_push_int(ctx, value);
+	}
+
+	/**
+	 * Require an integer, throws a JavaScript exception if not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the integer
+	 */
+	static inline int require(Context &ctx, int index)
+	{
+		return duk_require_int(ctx, index);
+	}
+};
+
+/**
+ * @class TypeInfo<bool>
+ * @brief Default implementation for bool.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeInfo<bool> {
+public:
+	/**
+	 * Get a boolean, return 0 if not a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the boolean
+	 */
+	static inline bool get(Context &ctx, int index)
+	{
+		return duk_get_boolean(ctx, index);
+	}
+
+	/**
+	 * Check if value is a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if boolean
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_boolean(ctx, index);
+	}
+
+	/**
+	 * Get a bool, return defaultValue if the value is not a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the boolean or defaultValue
+	 */
+	static inline bool optional(Context &ctx, int index, bool defaultValue)
+	{
+		if (!duk_is_boolean(ctx, index)) {
+			return defaultValue;
+		}
+
+		return duk_get_boolean(ctx, index);
+	}
+
+	/**
+	 * Push a boolean.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, bool value)
+	{
+		duk_push_boolean(ctx, value);
+	}
+
+	/**
+	 * Require a boolean, throws a JavaScript exception if not a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the boolean
+	 */
+	static inline bool require(Context &ctx, int index)
+	{
+		return duk_require_boolean(ctx, index);
+	}
+};
+
+/**
+ * @class TypeInfo<double>
+ * @brief Default implementation for double.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeInfo<double> {
+public:
+	/**
+	 * Get a double, return 0 if not a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the double
+	 */
+	static inline double get(Context &ctx, int index)
+	{
+		return duk_get_number(ctx, index);
+	}
+
+	/**
+	 * Check if value is a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if double
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_number(ctx, index);
+	}
+
+	/**
+	 * Get a double, return defaultValue if the value is not a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the double or defaultValue
+	 */
+	static inline double optional(Context &ctx, int index, double defaultValue)
+	{
+		if (!duk_is_number(ctx, index)) {
+			return defaultValue;
+		}
+
+		return duk_get_number(ctx, index);
+	}
+
+	/**
+	 * Push a double.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, double value)
+	{
+		duk_push_number(ctx, value);
+	}
+
+	/**
+	 * Require a double, throws a JavaScript exception if not a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the double
+	 */
+	static inline double require(Context &ctx, int index)
+	{
+		return duk_require_number(ctx, index);
+	}
+};
+
+/**
+ * @class TypeInfo<std::string>
+ * @brief Default implementation for std::string.
+ *
+ * Provides: get, is, optional, push, require.
+ *
+ * Note: the functions allows embedded '\0'.
+ */
+template <>
+class TypeInfo<std::string> {
+public:
+	/**
+	 * Get a string, return 0 if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline std::string get(Context &ctx, int index)
+	{
+		duk_size_t size;
+		const char *text = duk_get_lstring(ctx, index, &size);
+
+		return std::string{text, size};
+	}
+
+	/**
+	 * Check if value is a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if string
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_string(ctx, index);
+	}
+
+	/**
+	 * Get a string, return defaultValue if the value is not an string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the string or defaultValue
+	 */
+	static inline std::string optional(Context &ctx, int index, std::string defaultValue)
+	{
+		if (!duk_is_string(ctx, index)) {
+			return defaultValue;
+		}
+
+		return get(ctx, index);
+	}
+
+	/**
+	 * Push a string.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, const std::string &value)
+	{
+		duk_push_lstring(ctx, value.c_str(), value.length());
+	}
+
+	/**
+	 * Require a string, throws a JavaScript exception if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline std::string require(Context &ctx, int index)
+	{
+		duk_size_t size;
+		const char *text = duk_require_lstring(ctx, index, &size);
+
+		return std::string{text, size};
+	}
+};
+
+/**
+ * @class TypeInfo<const char *>
+ * @brief Default implementation for const char literals.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeInfo<const char *> {
+public:
+	/**
+	 * Get a string, return 0 if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline const char *get(Context &ctx, int index)
+	{
+		return duk_get_string(ctx, index);
+	}
+
+	/**
+	 * Check if value is a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if string
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_string(ctx, index);
+	}
+
+	/**
+	 * Get an integer, return defaultValue if the value is not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the integer or defaultValue
+	 */
+	static inline const char *optional(Context &ctx, int index, const char *defaultValue)
+	{
+		if (!duk_is_string(ctx, index)) {
+			return defaultValue;
+		}
+
+		return duk_get_string(ctx, index);
+	}
+
+	/**
+	 * Push a string.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, const char *value)
+	{
+		duk_push_string(ctx, value);
+	}
+
+	/**
+	 * Require a string, throws a JavaScript exception if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline const char *require(Context &ctx, int index)
+	{
+		return duk_require_string(ctx, index);
+	}
+};
+
+/**
+ * @brief Implementation for non-managed pointers.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <typename T>
+class TypeInfo<RawPointer<T>> {
+public:
+	/**
+	 * Get a pointer, return nullptr if not a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the pointer
+	 */
+	static inline T *get(Context &ctx, int index)
+	{
+		return static_cast<T *>(duk_to_pointer(ctx, index));
+	}
+
+	/**
+	 * Check if value is a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if pointer
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_pointer(ctx, index);
+	}
+
+	/**
+	 * Get a pointer, return defaultValue if the value is not a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the pointer or defaultValue
+	 */
+	static inline T *optional(Context &ctx, int index, RawPointer<T> defaultValue)
+	{
+		if (!duk_is_pointer(ctx, index)) {
+			return defaultValue.object;
+		}
+
+		return static_cast<T *>(duk_to_pointer(ctx, index));
+	}
+
+	/**
+	 * Push a pointer.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, const RawPointer<T> &value)
+	{
+		duk_push_pointer(ctx, value.object);
+	}
+
+	/**
+	 * Require a pointer, throws a JavaScript exception if not a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the pointer
+	 */
+	static inline T *require(Context &ctx, int index)
+	{
+		return static_cast<T *>(duk_require_pointer(ctx, index));
+	}
+};
+
+/**
+ * @class TypeInfo<Function>
+ * @brief Push C++ function to the stack.
+ *
+ * Provides: push.
+ *
+ * This implementation push a Duktape/C function that is wrapped as C++ for convenience.
+ */
+template <>
+class TypeInfo<Function> {
+public:
+	/**
+	 * Push the C++ function, it is wrapped as Duktape/C function and allocated on the heap by moving the
+	 * std::function.
+	 *
+	 * @param ctx the context
+	 * @param fn the function
+	 */
+	static void push(Context &ctx, Function fn);
+};
+
+/**
+ * @class TypeInfo<FunctionMap>
+ * @brief Put the functions to the object at the top of the stack.
+ *
+ * Provides: push.
+ */
+template <>
+class TypeInfo<FunctionMap> {
+public:
+	/**
+	 * Push a map of function to the object at the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param map the map of function
+	 */
+	static inline void push(Context &ctx, const FunctionMap &map)
+	{
+		for (const auto &entry : map) {
+			ctx.putProperty(-1, entry.first, entry.second);
+		}
+	}
+};
+
+/**
+ * @class TypeInfo<Object>
+ * @brief Push empty object to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeInfo<Object> {
+public:
+	/**
+	 * Check if value is an object.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if object
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_object(ctx, index);
+	}
+
+	/**
+	 * Create an empty object on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Object &)
+	{
+		duk_push_object(ctx);
+	}
+};
+
+/**
+ * @class TypeInfo<Array>
+ * @brief Push empty array to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeInfo<Array> {
+public:
+	/**
+	 * Check if value is a array.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if array
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_array(ctx, index);
+	}
+
+	/**
+	 * Create an empty array on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Array &)
+	{
+		duk_push_array(ctx);
+	}
+};
+
+/**
+ * @class TypeInfo<Undefined>
+ * @brief Push undefined value to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeInfo<Undefined> {
+public:
+	/**
+	 * Check if value is undefined.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if undefined
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_undefined(ctx, index);
+	}
+
+	/**
+	 * Push undefined value on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Undefined &)
+	{
+		duk_push_undefined(ctx);
+	}
+};
+
+/**
+ * @class TypeInfo<Null>
+ * @brief Push null value to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeInfo<Null> {
+public:
+	/**
+	 * Check if value is null.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if null
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_null(ctx, index);
+	}
+
+	/**
+	 * Push null value on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Null &)
+	{
+		duk_push_null(ctx);
+	}
+};
+
+/**
+ * @brief Push this binding into the stack.
+ *
+ * Provides: push.
+ */
+template <>
+class TypeInfo<This> {
+public:
+	/**
+	 * Push this function into the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const This &)
+	{
+		duk_push_this(ctx);
+	}
+};
+
+/**
+ * @class TypeInfo<Global>
+ * @brief Push the global object to the stack.
+ *
+ * Provides: push.
+ */
+template <>
+class TypeInfo<Global> {
+public:
+	/**
+	 * Push the global object into the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Global &)
+	{
+		duk_push_global_object(ctx);
+	}
+};
+
+/**
+ * @brief Push a map of key-value pair as objects.
+ *
+ * Provides: push.
+ *
+ * This class is convenient for settings constants such as enums, string and such.
+ */
+template <typename T>
+class TypeInfo<std::unordered_map<std::string, T>> {
+public:
+	/**
+	 * Put all values from the map as properties to the object at the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param map the values
+	 * @note You need an object at the top of the stack before calling this function
+	 */
+	static void push(Context &ctx, const std::unordered_map<std::string, T> &map)
+	{
+		for (const auto &pair : map) {
+			TypeInfo<T>::push(ctx, pair.second);
+			duk_put_prop_string(ctx, -2, pair.first.c_str());
+		}
+	}
+};
+
+/**
+ * @brief Push or get vectors as JavaScript arrays.
+ *
+ * Provides: get, push.
+ */
+template <typename T>
+class TypeInfo<std::vector<T>> {
+public:
+	/**
+	 * Get an array from the stack.
+	 *
+	 * @param ctx the context
+	 * @param index the array index
+	 * @return the array or empty array if the value is not an array
+	 */
+	static std::vector<T> get(Context &ctx, int index)
+	{
+		std::vector<T> result;
+
+		if (!duk_is_array(ctx, -1)) {
+			return result;
+		}
+
+		int total = duk_get_length(ctx, index);
+		for (int i = 0; i < total; ++i) {
+			result.push_back(ctx.getProperty<T>(index, i));
+		}
+
+		return result;
+	}
+
+	/**
+	 * Create an array with the specified values.
+	 *
+	 * @param ctx the context
+	 * @param array the values
+	 */
+	static void push(Context &ctx, const std::vector<T> &array)
+	{
+		duk_push_array(ctx);
+
+		int i = 0;
+		for (const auto &v : array) {
+			TypeInfo<T>::push(ctx, v);
+			duk_put_prop_index(ctx, -2, i++);
+		}
+	}
+};
+
+/**
+ * @brief Implementation of managed shared_ptr
+ * @see Shared
+ */
+template <typename T>
+class TypeInfo<Shared<T>> {
+private:
+	static void apply(Context &ctx, std::shared_ptr<T> value)
+	{
+		duk_push_boolean(ctx, false);
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
+		duk_push_pointer(ctx, new std::shared_ptr<T>(value));
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-shared-ptr");
+		duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
+			duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+
+			if (!duk_to_boolean(ctx, -1)) {
+				duk_push_boolean(ctx, true);
+				duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+				duk_get_prop_string(ctx, 0, "\xff""\xff""js-shared-ptr");
+				delete static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
+				duk_pop(ctx);
+			}
+
+			duk_pop(ctx);
+
+			return 0;
+		}, 1);
+		duk_set_finalizer(ctx, -2);
+	}
+
+public:
+	/**
+	 * Construct the shared_ptr as this.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void construct(Context &ctx, Shared<T> value)
+	{
+		duk_push_this(ctx);
+		apply(ctx, std::move(value.object));
+		duk_pop(ctx);
+	}
+
+	/**
+	 * Push a managed shared_ptr as object.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void push(Context &ctx, Shared<T> value)
+	{
+		duk_push_object(ctx);
+		apply(ctx, value.object);
+		value.object->prototype(ctx);
+		duk_set_prototype(ctx, -2);
+	}
+
+	/**
+	 * Get a managed shared_ptr from the stack.
+	 *
+	 * @param ctx the context
+	 * @param index the object index
+	 * @return the shared_ptr
+	 */
+	static std::shared_ptr<T> get(Context &ctx, int index)
+	{
+		duk_get_prop_string(ctx, index, "\xff""\xff""js-shared-ptr");
+		std::shared_ptr<T> value = *static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
+		duk_pop(ctx);
+
+		return value;
+	}
+};
+
+/**
+ * @brief Implementation of managed pointers
+ * @see Pointer
+ */
+template <typename T>
+class TypeInfo<Pointer<T>> {
+private:
+	static void apply(Context &ctx, T *value)
+	{
+		duk_push_boolean(ctx, false);
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
+		duk_push_pointer(ctx, value);
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-ptr");
+		duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
+			duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+
+			if (!duk_to_boolean(ctx, -1)) {
+				duk_push_boolean(ctx, true);
+				duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+				duk_get_prop_string(ctx, 0, "\xff""\xff""js-ptr");
+				delete static_cast<T *>(duk_to_pointer(ctx, -1));
+				duk_pop(ctx);
+			}
+
+			duk_pop(ctx);
+
+			return 0;
+		}, 1);
+		duk_set_finalizer(ctx, -2);
+	}
+
+public:
+	/**
+	 * Construct the pointer as this.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void construct(Context &ctx, Pointer<T> value)
+	{
+		duk_push_this(ctx);
+		apply(ctx, value.object);
+		duk_pop(ctx);
+	}
+
+	/**
+	 * Push a managed pointer as object.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void push(Context &ctx, Pointer<T> value)
+	{
+		duk_push_object(ctx);
+		apply(ctx, value.object);
+		value.object->prototype(ctx);
+		duk_set_prototype(ctx, -2);
+	}
+
+	/**
+	 * Get a managed pointer from the stack.
+	 *
+	 * @param ctx the context
+	 * @param index the object index
+	 * @return the pointer
+	 * @warning Do not store the pointer into the C++ side, the object can be deleted at any time
+	 */
+	static T *get(Context &ctx, int index)
+	{
+		duk_get_prop_string(ctx, index, "\xff""\xff""js-ptr");
+		T *value = static_cast<T *>(duk_to_pointer(ctx, -1));
+		duk_pop(ctx);
+
+		return value;
+	}
+};
+
+} // !js
+
+#endif // !_JS_H_
--- a/C++/modules/Json/Json.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,372 +0,0 @@
-/*
- * Json.cpp -- C++14 JSON manipulation using jansson parser
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-#include <jansson.h>
-
-#include <sstream>
-
-#include "Json.h"
-
-namespace json {
-
-namespace {
-
-void readObject(Value &parent, json_t *object);
-void readArray(Value &parent, json_t *array);
-
-Value readValue(json_t *v)
-{
-	if (json_is_null(v)) {
-		return Value{nullptr};
-	}
-	if (json_is_string(v)) {
-		return Value{json_string_value(v)};
-	}
-	if (json_is_real(v)) {
-		return Value{json_number_value(v)};
-	}
-	if (json_is_integer(v)) {
-		return Value{static_cast<int>(json_integer_value(v))};
-	}
-	if (json_is_boolean(v)) {
-		return Value{json_boolean_value(v)};
-	}
-	if (json_is_object(v)) {
-		Value object{Type::Object};
-
-		readObject(object, v);
-
-		return object;
-	}
-	if (json_is_array(v)) {
-		Value array{Type::Array};
-
-		readArray(array, v);
-
-		return array;
-	}
-
-	return Value{};
-}
-
-void readObject(Value &parent, json_t *object)
-{
-	const char *key;
-	json_t *value;
-
-	json_object_foreach(object, key, value) {
-		parent.insert(key, readValue(value));
-	}
-}
-
-void readArray(Value &parent, json_t *array)
-{
-	size_t index;
-	json_t *value;
-
-	json_array_foreach(array, index, value) {
-		parent.append(readValue(value));
-	}
-}
-
-template <typename Func, typename... Args>
-Value convert(Func fn, Args&&... args)
-{
-	json_error_t error;
-	json_t *json = fn(std::forward<Args>(args)..., &error);
-
-	if (json == nullptr) {
-		throw Error{error.text, error.source, error.line, error.column, error.position};
-	}
-
-	Value value;
-
-	if (json_is_object(json)) {
-		value = Value{Type::Object};
-		readObject(value, json);
-	} else {
-		value = Value{Type::Array};
-		readArray(value, json);
-	}
-
-	json_decref(json);
-
-	return value;
-}
-
-std::string indent(int param, int level)
-{
-	std::string str;
-
-	if (param < 0) {
-		str = std::string(level, '\t');
-	} else if (param > 0) {
-		str = std::string(param * level, ' ');
-	}
-
-	return str;
-}
-
-} // !namespace
-
-void Value::copy(const Value &other)
-{
-	switch (other.m_type) {
-	case Type::Array:
-		new (&m_array) std::deque<Value>(other.m_array);
-		break;
-	case Type::Boolean:
-		m_boolean = other.m_boolean;
-		break;
-	case Type::Int:
-		m_integer = other.m_integer;
-		break;
-	case Type::Object:
-		new (&m_object) std::map<std::string, Value>(other.m_object);
-		break;
-	case Type::Real:
-		m_number = other.m_number;
-		break;
-	case Type::String:
-		new (&m_string) std::string(other.m_string);
-		break;
-	default:
-		break;
-	}
-
-	m_type = other.m_type;
-}
-
-void Value::move(Value &&other)
-{
-	switch (other.m_type) {
-	case Type::Array:
-		new (&m_array) std::deque<Value>(std::move(other.m_array));
-		break;
-	case Type::Boolean:
-		m_boolean = other.m_boolean;
-		break;
-	case Type::Int:
-		m_integer = other.m_integer;
-		break;
-	case Type::Object:
-		new (&m_object) std::map<std::string, Value>(std::move(other.m_object));
-		break;
-	case Type::Real:
-		m_number = other.m_number;
-		break;
-	case Type::String:
-		new (&m_string) std::string(std::move(other.m_string));
-		break;
-	default:
-		break;
-	}
-
-	m_type = other.m_type;
-}
-
-Value::Value(Type type)
-	: m_type{type}
-{
-	switch (m_type) {
-	case Type::Array:
-		new (&m_array) std::deque<Value>();
-		break;
-	case Type::Boolean:
-		m_boolean = false;
-		break;
-	case Type::Int:
-		m_integer = 0;
-		break;
-	case Type::Object:
-		new (&m_object) std::map<std::string, Value>();
-		break;
-	case Type::Real:
-		m_number = 0;
-		break;
-	case Type::String:
-		new (&m_string) std::string();
-		break;
-	default:
-		break;
-	}
-}
-
-Value::~Value()
-{
-	switch (m_type) {
-	case Type::Array:
-		m_array.~deque<Value>();
-		break;
-	case Type::Object:
-		m_object.~map<std::string, Value>();
-		break;
-	case Type::String:
-		m_string.~basic_string();
-		break;
-	default:
-		break;
-	}
-}
-
-bool Value::toBool() const noexcept
-{
-	if (m_type != Type::Boolean) {
-		return false;
-	}
-
-	return m_boolean;
-}
-
-double Value::toReal() const noexcept
-{
-	if (m_type != Type::Real) {
-		return 0;
-	}
-
-	return m_number;
-}
-
-int Value::toInt() const noexcept
-{
-	if (m_type != Type::Int) {
-		return 0;
-	}
-
-	return m_integer;
-}
-
-std::string Value::toString() const noexcept
-{
-	if (m_type != Type::String) {
-		return "";
-	}
-
-	return m_string;
-}
-
-Value::Value(const Buffer &buffer)
-{
-	*this = convert(json_loads, buffer.text.c_str(), 0);
-}
-
-Value::Value(const File &file)
-{
-	*this = convert(json_load_file, file.path.c_str(), 0);
-}
-
-std::string Value::toJson(int level, int current) const
-{
-	std::ostringstream oss;
-
-	switch (m_type) {
-	case Type::Array: {
-		oss << '[' << (level != 0 ? "\n" : "");
-
-		unsigned total = m_array.size();
-		unsigned i = 0;
-		for (const auto &v : m_array) {
-			oss << indent(level, current + 1) << v.toJson(level, current + 1);
-			oss << (++i < total ? "," : "");
-			oss << (level != 0 ? "\n" : "");
-		}
-
-		oss << (level != 0 ? indent(level, current) : "") << ']';
-		break;
-	}
-	case Type::Boolean:
-		oss << (m_boolean ? true : false);
-		break;
-	case Type::Int:
-		oss << m_integer;
-		break;
-	case Type::Object: {
-		oss << '{' << (level != 0 ? "\n" : "");
-
-		unsigned total = m_object.size();
-		unsigned i = 0;
-		for (const auto &pair : m_object) {
-			oss << indent(level, current + 1);
-
-			/* Key and : */
-			oss << "\"" << pair.first << "\":" << (level != 0 ? " " : "");
-
-			/* Value */
-			oss << pair.second.toJson(level, current + 1);
-
-			/* Comma, new line if needed */
-			oss << (++i < total ? "," : "") << (level != 0 ? "\n" : "");
-		}
-
-		oss << (level != 0 ? indent(level, current) : "") << '}';
-		break;
-	}
-	case Type::Real:
-		oss << m_number;
-		break;
-	case Type::String:
-		oss << "\"" << escape(m_string) << "\"";
-		break;
-	default:
-		break;
-	}
-
-	return oss.str();
-}
-
-std::string escape(const std::string &value)
-{
-	std::string result;
-
-	for (auto it = value.begin(); it != value.end(); ++it) {
-		switch (*it) {
-		case '\\':
-			result += "\\\\";
-			break;
-		case '/':
-			result += "\\/";
-			break;
-		case '"':
-			result += "\\\"";
-			break;
-		case '\b':
-			result += "\\b";
-			break;
-		case '\f':
-			result += "\\f";
-			break;
-		case '\n':
-			result += "\\n";
-			break;
-		case '\r':
-			result += "\\r";
-			break;
-		case '\t':
-			result += "\\t";
-			break;
-		default:
-			result += *it;
-			break;
-		}
-	}
-
-	return result;
-}
-
-} // !json
--- a/C++/modules/Json/Json.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1161 +0,0 @@
-/*
- * Json.h -- C++14 JSON manipulation using jansson parser
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _JSON_H_
-#define _JSON_H_
-
-/**
- * @file Json.h
- * @brief Jansson C++14 wrapper
- *
- * These classes can be used to build or parse JSON documents using jansson library. It is designed to be safe
- * and explicit. It does not implement implicit sharing like jansson so when you access (e.g. Value::toObject) values
- * you get real copies, thus when you read big documents it can has a performance cost.
- */
-
-#include <cassert>
-#include <exception>
-#include <initializer_list>
-#include <map>
-#include <string>
-#include <utility>
-#include <deque>
-
-/**
- * Json namespace.
- */
-namespace json {
-
-/**
- * @enum Type
- * @brief Type of Value.
- */
-enum class Type {
-	Array,		//!< Value is an array []
-	Boolean,	//!< Value is boolean
-	Int,		//!< Value is integer
-	Real,		//!< Value is float
-	Object,		//!< Value is object {}
-	String,		//!< Value is unicode string
-	Null		//!< Value is defined to null
-};
-
-/**
- * @class Error
- * @brief Error description.
- */
-class Error : public std::exception {
-private:
-	std::string m_text;
-	std::string m_source;
-	int m_line;
-	int m_column;
-	int m_position;
-
-public:
-	/**
-	 * Create the error.
-	 *
-	 * @param text the text message
-	 * @param source the source (e.g. file name)
-	 * @param line the line number
-	 * @param column the column number
-	 * @param position the position
-	 */
-	inline Error(std::string text, std::string source, int line, int column, int position) noexcept
-		: m_text{std::move(text)}
-		, m_source{std::move(source)}
-		, m_line{line}
-		, m_column{column}
-		, m_position{position}
-	{
-	}
-
-	/**
-	 * Get the error message.
-	 *
-	 * @return the text
-	 */
-	inline const std::string &text() const noexcept
-	{
-		return m_text;
-	}
-
-	/**
-	 * Get the source (e.g. a file name).
-	 *
-	 * @return the source
-	 */
-	inline const std::string &source() const noexcept
-	{
-		return m_source;
-	}
-
-	/**
-	 * Get the line.
-	 *
-	 * @return the line
-	 */
-	inline int line() const noexcept
-	{
-		return m_line;
-	}
-
-	/**
-	 * Get the column.
-	 *
-	 * @return the column
-	 */
-	inline int column() const noexcept
-	{
-		return m_column;
-	}
-
-	/**
-	 * Get the position.
-	 *
-	 * @return the position
-	 */
-	inline int position() const noexcept
-	{
-		return m_position;
-	}
-
-	/**
-	 * Get the error message.
-	 *
-	 * @return the message
-	 */
-	const char *what() const noexcept override
-	{
-		return m_text.c_str();
-	}
-};
-
-/**
- * @class Buffer
- * @brief Open JSON document from text.
- */
-class Buffer {
-public:
-	std::string text;	//!< The JSON text
-};
-
-/**
- * @class File
- * @brief Open JSON document from a file.
- */
-class File {
-public:
-	std::string path;	//!< The path to the file
-};
-
-/**
- * @class Value
- * @brief Generic JSON value wrapper.
- */
-class Value {
-private:
-	Type m_type{Type::Null};
-
-	union {
-		double m_number;
-		bool m_boolean;
-		int m_integer;
-		std::string m_string;
-		std::deque<Value> m_array;
-		std::map<std::string, Value> m_object;
-	};
-
-	void copy(const Value &);
-	void move(Value &&);
-	std::string toJson(int indent, int current) const;
-
-	/**
-	 * @class BaseIterator
-	 * @brief This is the base class for iterator and const_iterator
-	 *
-	 * This iterator works for both arrays and objects. Because of that purpose, it is only available
-	 * as forward iterator.
-	 *
-	 * When iterator comes from an object, you can use key() otherwise you can use index().
-	 */
-	template <typename ValueType, typename ArrayIteratorType, typename ObjectIteratorType>
-	class BaseIterator : public std::iterator<std::forward_iterator_tag, ValueType> {
-	private:
-		friend class Value;
-
-		ValueType &m_value;
-		ArrayIteratorType m_ita;
-		ObjectIteratorType m_itm;
-
-		inline void increment()
-		{
-			if (m_value.isObject()) {
-				m_itm++;
-			} else {
-				m_ita++;
-			}
-		}
-
-		BaseIterator(ValueType &value, ObjectIteratorType it)
-			: m_value(value)
-			, m_itm(it)
-		{
-		}
-
-		BaseIterator(ValueType &value, ArrayIteratorType it)
-			: m_value(value)
-			, m_ita(it)
-		{
-		}
-
-	public:
-		/**
-		 * Get the iterator key (for objects).
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @pre iterator must come from object
-		 * @return the key
-		 */
-		inline const std::string &key() const noexcept
-		{
-			assert(m_value.isObject());
-			assert(m_itm != m_value.m_object.end());
-
-			return m_itm->first;
-		}
-
-		/**
-		 * Get the iterator position (for arrays).
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @pre iterator must come from arrays
-		 * @return the index
-		 */
-		inline unsigned index() const noexcept
-		{
-			assert(m_value.isArray());
-			assert(m_ita != m_value.m_array.end());
-
-			return std::distance(m_value.m_array.begin(), m_ita);
-		}
-
-		/**
-		 * Dereference the iterator.
-		 *
-		 * @pre iterator be dereferenceable
-		 * @return the value
-		 */
-		inline ValueType &operator*() noexcept
-		{
-			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
-			       (m_value.isObject() && m_itm != m_value.m_object.end()));
-
-			return (m_value.m_type == Type::Object) ? m_itm->second : *m_ita;
-		}
-
-		/**
-		 * Dereference the iterator as a pointer.
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @return the value
-		 */
-		inline ValueType *operator->() noexcept
-		{
-			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
-			       (m_value.isObject() && m_itm != m_value.m_object.end()));
-
-			return (m_value.m_type == Type::Object) ? &m_itm->second : &(*m_ita);
-		}
-
-		/**
-		 * Increment the iterator. (Prefix version).
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @return *this;
-		 */
-		inline BaseIterator &operator++() noexcept
-		{
-			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
-			       (m_value.isObject() && m_itm != m_value.m_object.end()));
-
-			increment();
-
-			return *this;
-		}
-
-		/**
-		 * Increment the iterator. (Postfix version).
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @return *this;
-		 */
-		inline BaseIterator &operator++(int) noexcept
-		{
-			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
-			       (m_value.isObject() && m_itm != m_value.m_object.end()));
-
-			increment();
-
-			return *this;
-		}
-
-		/**
-		 * Compare two iterators.
-		 *
-		 * @param it1 the first iterator
-		 * @param it2 the second iterator
-		 * @return true if they are same
-		 */
-		bool operator==(const BaseIterator &it) const noexcept
-		{
-			if (m_value.isObject() && it.m_value.isObject())
-				return m_itm == it.m_itm;
-			if (m_value.isArray() && it.m_value.isArray())
-				return m_ita == it.m_ita;
-
-			return false;
-		}
-
-		/**
-		 * Test if the iterator is different.
-		 *
-		 * @param it the iterator
-		 * @return true if they are different
-		 */
-		inline bool operator!=(const BaseIterator &it) const noexcept
-		{
-			return !(*this == it);
-		}
-	};
-
-public:
-	/**
-	 * Forward iterator.
-	 */
-	using iterator = BaseIterator<Value, typename std::deque<Value>::iterator, typename std::map<std::string, Value>::iterator>;
-
-	/**
-	 * Const forward iterator.
-	 */
-	using const_iterator = BaseIterator<const Value, typename std::deque<Value>::const_iterator, typename std::map<std::string, Value>::const_iterator>;
-
-	/**
-	 * Construct a null value.
-	 */
-	inline Value()
-	{
-	}
-
-	/**
-	 * Create a value with a specified type, this is usually only needed when you want to create an object or
-	 * an array.
-	 *
-	 * For any other types, initialize with sane default value.
-	 *
-	 * @param type the type
-	 */
-	Value(Type type);
-
-	/**
-	 * Construct a null value.
-	 */
-	inline Value(std::nullptr_t) noexcept
-		: m_type{Type::Null}
-	{
-	}
-
-	/**
-	 * Construct a boolean value.
-	 *
-	 * @param value the boolean value
-	 */
-	inline Value(bool value) noexcept
-		: m_type{Type::Boolean}
-		, m_boolean{value}
-	{
-	}
-
-	/**
-	 * Create value from integer.
-	 *
-	 * @param value the value
-	 */
-	inline Value(int value) noexcept
-		: m_type{Type::Int}
-		, m_integer{value}
-	{
-	}
-
-	/**
-	 * Construct a value from a C-string.
-	 *
-	 * @param value the C-string
-	 */
-	inline Value(const char *value)
-		: m_type{Type::String}
-	{
-		new (&m_string) std::string{value ? value : ""};
-	}
-
-	/**
-	 * Construct a number value.
-	 *
-	 * @param value the real value
-	 */
-	inline Value(double value) noexcept
-		: m_type{Type::Real}
-		, m_number{value}
-	{
-	}
-
-	/**
-	 * Construct a string value.
-	 *
-	 * @param value the string
-	 */
-	inline Value(std::string value) noexcept
-		: m_type{Type::String}
-	{
-		new (&m_string) std::string{std::move(value)};
-	}
-
-	/**
-	 * Create an object from a map.
-	 *
-	 * @param values the values
-	 * @see fromObject
-	 */
-	inline Value(std::map<std::string, Value> values)
-		: Value{Type::Object}
-	{
-		for (const auto &pair : values) {
-			insert(pair.first, pair.second);
-		}
-	}
-
-	/**
-	 * Create an array from a deque.
-	 *
-	 * @param values the values
-	 * @see fromArray
-	 */
-	inline Value(std::deque<Value> values)
-		: Value{Type::Array}
-	{
-		for (Value value : values) {
-			append(std::move(value));
-		}
-	}
-
-	/**
-	 * Construct a value from a buffer.
-	 *
-	 * @param buffer the text
-	 * @throw Error on errors
-	 */
-	Value(const Buffer &buffer);
-
-	/**
-	 * Construct a value from a file.
-	 *
-	 * @param file the file
-	 * @throw Error on errors
-	 */
-	Value(const File &file);
-
-	/**
-	 * Move constructor.
-	 *
-	 * @param other the value to move from
-	 */
-	inline Value(Value &&other)
-	{
-		move(std::move(other));
-	}
-
-	/**
-	 * Copy constructor.
-	 *
-	 * @param other the value to copy from
-	 */
-	inline Value(const Value &other)
-	{
-		copy(other);
-	}
-
-	/**
-	 * Copy operator.
-	 *
-	 * @param other the value to copy from
-	 * @return *this
-	 */
-	inline Value &operator=(const Value &other)
-	{
-		copy(other);
-
-		return *this;
-	}
-
-	/**
-	 * Move operator.
-	 *
-	 * @param other the value to move from
-	 */
-	inline Value &operator=(Value &&other)
-	{
-		move(std::move(other));
-
-		return *this;
-	}
-
-	/**
-	 * Destructor.
-	 */
-	~Value();
-
-	/**
-	 * Get an iterator to the beginning.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline iterator begin() noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? iterator(*this, m_object.begin()) : iterator(*this, m_array.begin());
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline const_iterator begin() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? const_iterator(*this, m_object.begin()) : const_iterator(*this, m_array.begin());
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline const_iterator cbegin() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? const_iterator(*this, m_object.cbegin()) : const_iterator(*this, m_array.cbegin());
-	}
-
-	/**
-	 * Get an iterator to the end.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline iterator end() noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? iterator(*this, m_object.end()) : iterator(*this, m_array.end());
-	}
-
-	/**
-	 * Get an iterator to the end.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline const_iterator end() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? const_iterator(*this, m_object.end()) : const_iterator(*this, m_array.end());
-	}
-
-	/**
-	 * Get an iterator to the end.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline const_iterator cend() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? const_iterator(*this, m_object.cend()) : const_iterator(*this, m_array.cend());
-	}
-
-	/**
-	 * Get the value type.
-	 *
-	 * @return the type
-	 */
-	inline Type typeOf() const noexcept
-	{
-		return m_type;
-	}
-
-	/**
-	 * Get the value as boolean.
-	 *
-	 * @return the value or false if not a boolean
-	 */
-	bool toBool() const noexcept;
-
-	/**
-	 * Get the value as integer.
-	 *
-	 * @return the value or 0 if not a integer
-	 */
-	int toInt() const noexcept;
-
-	/**
-	 * Get the value as real.
-	 *
-	 * @return the value or 0 if not a real
-	 */
-	double toReal() const noexcept;
-
-	/**
-	 * Get the value as string.
-	 *
-	 * @return the value or empty stirng if not a string
-	 */
-	std::string toString() const noexcept;
-
-	/**
-	 * Check if the value is boolean type.
-	 *
-	 * @return true if boolean
-	 */
-	inline bool isBool() const noexcept
-	{
-		return m_type == Type::Boolean;
-	}
-
-	/**
-	 * Check if the value is integer type.
-	 *
-	 * @return true if integer
-	 */
-	inline bool isInt() const noexcept
-	{
-		return m_type == Type::Int;
-	}
-
-	/**
-	 * Check if the value is object type.
-	 *
-	 * @return true if object
-	 */
-	inline bool isObject() const noexcept
-	{
-		return m_type == Type::Object;
-	}
-
-	/**
-	 * Check if the value is array type.
-	 *
-	 * @return true if array
-	 */
-	inline bool isArray() const noexcept
-	{
-		return m_type == Type::Array;
-	}
-
-	/**
-	 * Check if the value is integer or real type.
-	 *
-	 * @return true if integer or real
-	 * @see toInt
-	 * @see toReal
-	 */
-	inline bool isNumber() const noexcept
-	{
-		return m_type == Type::Real || m_type == Type::Int;
-	}
-
-	/**
-	 * Check if the value is real type.
-	 *
-	 * @return true if real
-	 */
-	inline bool isReal() const noexcept
-	{
-		return m_type == Type::Real;
-	}
-
-	/**
-	 * Check if the value is null type.
-	 *
-	 * @return true if null
-	 */
-	inline bool isNull() const noexcept
-	{
-		return m_type == Type::Null;
-	}
-
-	/**
-	 * Check if the value is string type.
-	 *
-	 * @return true if string
-	 */
-	inline bool isString() const noexcept
-	{
-		return m_type == Type::String;
-	}
-
-	/**
-	 * Get the array or object size.
-	 *
-	 * @pre must be an array or object
-	 * @return the size
-	 */
-	inline unsigned size() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		if (m_type == Type::Object) {
-			return m_object.size();
-		}
-
-		return m_array.size();
-	}
-
-	/**
-	 * Remove all the values.
-	 *
-	 * @pre must be an array or an object
-	 */
-	inline void clear() noexcept
-	{
-		assert(isArray() || isObject());
-
-		if (m_type == Type::Array) {
-			m_array.clear();
-		} else {
-			m_object.clear();
-		}
-	}
-
-	/*
-	 * Array functions
-	 * ----------------------------------------------------------
-	 */
-
-	/**
-	 * Get the value at the specified position or the defaultValue if position is out of bounds.
-	 *
-	 * @param position the position
-	 * @param defaultValue the value replacement
-	 * @return the value or defaultValue
-	 */
-	template <typename DefaultValue>
-	inline Value valueOr(unsigned position, DefaultValue &&defaultValue) const
-	{
-		if (m_type != Type::Array || position >= m_array.size()) {
-			return defaultValue;
-		}
-
-		return m_array[position];
-	}
-
-	/**
-	 * Get a value at the specified index.
-	 *
-	 * @pre must be an array
-	 * @param position the position
-	 * @return the value
-	 * @throw std::out_of_range if out of bounds
-	 */
-	inline const Value &at(unsigned position) const
-	{
-		assert(isArray());
-
-		return m_array.at(position);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @param position the position
-	 * @return the value
-	 * @throw std::out_of_range if out of bounds
-	 */
-	inline Value &at(unsigned position)
-	{
-		assert(isArray());
-
-		return m_array.at(position);
-	}
-
-	/**
-	 * Get a value at the specified index.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 * @return the value
-	 */
-	inline const Value &operator[](unsigned position) const
-	{
-		assert(isArray());
-		assert(position < m_array.size());
-
-		return m_array[position];
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 * @return the value
-	 */
-	inline Value &operator[](unsigned position)
-	{
-		assert(isArray());
-		assert(position < m_array.size());
-
-		return m_array[position];
-	}
-
-	/**
-	 * Push a value to the beginning of the array.
-	 *
-	 * @pre must be an array
-	 * @param value the value to push
-	 */
-	inline void push(const Value &value)
-	{
-		assert(isArray());
-
-		m_array.push_front(value);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @param value the value to push
-	 */
-	inline void push(Value &&value)
-	{
-		assert(isArray());
-
-		m_array.push_front(std::move(value));
-	}
-
-	/**
-	 * Insert a value at the specified position.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 * @param value the value to push
-	 */
-	inline void insert(unsigned position, const Value &value)
-	{
-		assert(isArray());
-		assert(position <= m_array.size());
-
-		m_array.insert(m_array.begin() + position, value);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 * @param value the value to push
-	 */
-	inline void insert(unsigned position, Value &&value)
-	{
-		assert(isArray());
-		assert(position <= m_array.size());
-
-		m_array.insert(m_array.begin() + position, std::move(value));
-	}
-
-	/**
-	 * Add a new value to the end.
-	 *
-	 * @pre must be an array
-	 * @param value the value to append
-	 */
-	inline void append(const Value &value)
-	{
-		assert(isArray());
-
-		m_array.push_back(value);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @param value the value to append
-	 */
-	inline void append(Value &&value)
-	{
-		assert(isArray());
-
-		m_array.push_back(std::move(value));
-	}
-
-	/**
-	 * Remove a value at the specified position.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 */
-	inline void erase(unsigned position)
-	{
-		assert(isArray());
-		assert(position < m_array.size());
-
-		m_array.erase(m_array.begin() + position);
-	}
-
-	/*
-	 * Object functions
-	 * ----------------------------------------------------------
-	 */
-
-	/**
-	 * Get the value at the specified key or the defaultValue if key is absent.
-	 *
-	 * @param name the name
-	 * @param defaultValue the value replacement
-	 * @return the value or defaultValue
-	 */
-	template <typename DefaultValue>
-	Value valueOr(const std::string &name, DefaultValue &&defaultValue) const
-	{
-		if (m_type != Type::Object) {
-			return defaultValue;
-		}
-
-		auto it = m_object.find(name);
-
-		if (it == m_object.end()) {
-			return defaultValue;
-		}
-
-		return it->second;
-	}
-
-	/**
-	 * Get a value from the object.
-	 *
-	 * @pre must be an object
-	 * @param name the value key
-	 * @return the value
-	 * @throw std::out_of_range if not found
-	 */
-	inline const Value &at(const std::string &name) const
-	{
-		assert(isObject());
-
-		return m_object.at(name);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an object
-	 * @param name the value key
-	 * @return the value
-	 * @throw std::out_of_range if not found
-	 */
-	inline Value &at(const std::string &name)
-	{
-		assert(isObject());
-
-		return m_object.at(name);
-	}
-
-	/**
-	 * Get a value from the object.
-	 *
-	 * @pre must be an object
-	 * @param name the value key
-	 * @return the value
-	 */
-	inline Value &operator[](const std::string &name)
-	{
-		assert(isObject());
-
-		return m_object[name];
-	}
-
-	/**
-	 * Get a value from the object.
-	 *
-	 * @pre must be an object
-	 * @param name the value key
-	 * @return the value
-	 */
-	inline const Value &operator[](const std::string &name) const
-	{
-		assert(isObject());
-
-		return m_object.at(name);
-	}
-
-	/**
-	 * Find a value by key.
-	 *
-	 * @pre must be an object
-	 * @param key the property key
-	 * @return the iterator or past the end if not found
-	 */
-	inline iterator find(const std::string &key)
-	{
-		assert(isObject());
-
-		return iterator(*this, m_object.find(key));
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an object
-	 * @param key the property key
-	 * @return the iterator or past the end if not found
-	 */
-	inline const_iterator find(const std::string &key) const
-	{
-		assert(isObject());
-
-		return const_iterator(*this, m_object.find(key));
-	}
-
-	/**
-	 * Insert a new value.
-	 *
-	 * @pre must be an object
-	 * @param name the key
-	 * @param value the value
-	 */
-	inline void insert(std::string name, const Value &value)
-	{
-		assert(isObject());
-
-		m_object.insert({std::move(name), value});
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an object
-	 * @param name the key
-	 * @param value the value
-	 */
-	inline void insert(std::string name, Value &&value)
-	{
-		assert(isObject());
-
-		m_object.insert({std::move(name), std::move(value)});
-	}
-
-	/**
-	 * Check if a value exists.
-	 *
-	 * @pre must be an object
-	 * @param key the key value
-	 * @return true if exists
-	 */
-	inline bool contains(const std::string &key) const noexcept
-	{
-		assert(isObject());
-
-		return m_object.find(key) != m_object.end();
-	}
-
-	/**
-	 * Remove a value of the specified key.
-	 *
-	 * @pre must be an object
-	 * @param key the value key
-	 */
-	inline void erase(const std::string &key)
-	{
-		assert(isObject());
-
-		m_object.erase(key);
-	}
-
-	/**
-	 * Return this value as JSon representation.
-	 *
-	 * @param indent, the indentation to use (0 == compact, < 0 == tabs, > 0 == number of spaces)
-	 * @param tabs, use tabs or not
-	 * @return the string
-	 */
-	inline std::string toJson(int indent = 2) const
-	{
-		return toJson(indent, 0);
-	}
-};
-
-/**
- * Escape the input.
- *
- * @param input the input
- * @return the escaped string
- */
-std::string escape(const std::string &input);
-
-/**
- * Convenient function for creating array from initializer list.
- *
- * @param values the values
- * @return the array
- */
-inline Value array(std::initializer_list<Value> values)
-{
-	return Value(std::deque<Value>(values.begin(), values.end()));
-}
-
-/**
- * Convenient function for creating object from initializer list.
- *
- * @param values the values
- * @return the object
- */
-inline Value object(std::initializer_list<std::pair<std::string, Value>> values)
-{
-	return Value(std::map<std::string, Value>(values.begin(), values.end()));
-}
-
-} // !json
-
-#endif // !_JSON_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Json/json.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,371 @@
+/*
+ * json.cpp -- C++14 JSON manipulation using jansson parser
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <jansson.h>
+
+#include <sstream>
+
+#include "json.h"
+
+namespace json {
+
+namespace {
+
+void readObject(Value &parent, json_t *object);
+void readArray(Value &parent, json_t *array);
+
+Value readValue(json_t *v)
+{
+	if (json_is_null(v)) {
+		return Value{nullptr};
+	}
+	if (json_is_string(v)) {
+		return Value{json_string_value(v)};
+	}
+	if (json_is_real(v)) {
+		return Value{json_number_value(v)};
+	}
+	if (json_is_integer(v)) {
+		return Value{static_cast<int>(json_integer_value(v))};
+	}
+	if (json_is_boolean(v)) {
+		return Value{json_boolean_value(v)};
+	}
+	if (json_is_object(v)) {
+		Value object{Type::Object};
+
+		readObject(object, v);
+
+		return object;
+	}
+	if (json_is_array(v)) {
+		Value array{Type::Array};
+
+		readArray(array, v);
+
+		return array;
+	}
+
+	return Value{};
+}
+
+void readObject(Value &parent, json_t *object)
+{
+	const char *key;
+	json_t *value;
+
+	json_object_foreach(object, key, value) {
+		parent.insert(key, readValue(value));
+	}
+}
+
+void readArray(Value &parent, json_t *array)
+{
+	size_t index;
+	json_t *value;
+
+	json_array_foreach(array, index, value) {
+		parent.append(readValue(value));
+	}
+}
+
+template <typename Func, typename... Args>
+Value convert(Func fn, Args&&... args)
+{
+	json_error_t error;
+	json_t *json = fn(std::forward<Args>(args)..., &error);
+
+	if (json == nullptr) {
+		throw Error{error.text, error.source, error.line, error.column, error.position};
+	}
+
+	Value value;
+
+	if (json_is_object(json)) {
+		value = Value{Type::Object};
+		readObject(value, json);
+	} else {
+		value = Value{Type::Array};
+		readArray(value, json);
+	}
+
+	json_decref(json);
+
+	return value;
+}
+
+std::string indent(int param, int level)
+{
+	std::string str;
+
+	if (param < 0) {
+		str = std::string(level, '\t');
+	} else if (param > 0) {
+		str = std::string(param * level, ' ');
+	}
+
+	return str;
+}
+
+} // !namespace
+
+void Value::copy(const Value &other)
+{
+	switch (other.m_type) {
+	case Type::Array:
+		new (&m_array) std::deque<Value>(other.m_array);
+		break;
+	case Type::Boolean:
+		m_boolean = other.m_boolean;
+		break;
+	case Type::Int:
+		m_integer = other.m_integer;
+		break;
+	case Type::Object:
+		new (&m_object) std::map<std::string, Value>(other.m_object);
+		break;
+	case Type::Real:
+		m_number = other.m_number;
+		break;
+	case Type::String:
+		new (&m_string) std::string(other.m_string);
+		break;
+	default:
+		break;
+	}
+
+	m_type = other.m_type;
+}
+
+void Value::move(Value &&other)
+{
+	switch (other.m_type) {
+	case Type::Array:
+		new (&m_array) std::deque<Value>(std::move(other.m_array));
+		break;
+	case Type::Boolean:
+		m_boolean = other.m_boolean;
+		break;
+	case Type::Int:
+		m_integer = other.m_integer;
+		break;
+	case Type::Object:
+		new (&m_object) std::map<std::string, Value>(std::move(other.m_object));
+		break;
+	case Type::Real:
+		m_number = other.m_number;
+		break;
+	case Type::String:
+		new (&m_string) std::string(std::move(other.m_string));
+		break;
+	default:
+		break;
+	}
+
+	m_type = other.m_type;
+}
+
+Value::Value(Type type)
+	: m_type{type}
+{
+	switch (m_type) {
+	case Type::Array:
+		new (&m_array) std::deque<Value>();
+		break;
+	case Type::Boolean:
+		m_boolean = false;
+		break;
+	case Type::Int:
+		m_integer = 0;
+		break;
+	case Type::Object:
+		new (&m_object) std::map<std::string, Value>();
+		break;
+	case Type::Real:
+		m_number = 0;
+		break;
+	case Type::String:
+		new (&m_string) std::string();
+		break;
+	default:
+		break;
+	}
+}
+
+Value::~Value()
+{
+	switch (m_type) {
+	case Type::Array:
+		m_array.~deque<Value>();
+		break;
+	case Type::Object:
+		m_object.~map<std::string, Value>();
+		break;
+	case Type::String:
+		m_string.~basic_string();
+		break;
+	default:
+		break;
+	}
+}
+
+bool Value::toBool() const noexcept
+{
+	if (m_type != Type::Boolean) {
+		return false;
+	}
+
+	return m_boolean;
+}
+
+double Value::toReal() const noexcept
+{
+	if (m_type != Type::Real) {
+		return 0;
+	}
+
+	return m_number;
+}
+
+int Value::toInt() const noexcept
+{
+	if (m_type != Type::Int) {
+		return 0;
+	}
+
+	return m_integer;
+}
+
+std::string Value::toString() const noexcept
+{
+	if (m_type != Type::String) {
+		return "";
+	}
+
+	return m_string;
+}
+
+Value::Value(const Buffer &buffer)
+{
+	*this = convert(json_loads, buffer.text.c_str(), 0);
+}
+
+Value::Value(const File &file)
+{
+	*this = convert(json_load_file, file.path.c_str(), 0);
+}
+
+std::string Value::toJson(int level, int current) const
+{
+	std::ostringstream oss;
+
+	switch (m_type) {
+	case Type::Array: {
+		oss << '[' << (level != 0 ? "\n" : "");
+
+		unsigned total = m_array.size();
+		unsigned i = 0;
+		for (const auto &v : m_array) {
+			oss << indent(level, current + 1) << v.toJson(level, current + 1);
+			oss << (++i < total ? "," : "");
+			oss << (level != 0 ? "\n" : "");
+		}
+
+		oss << (level != 0 ? indent(level, current) : "") << ']';
+		break;
+	}
+	case Type::Boolean:
+		oss << (m_boolean ? true : false);
+		break;
+	case Type::Int:
+		oss << m_integer;
+		break;
+	case Type::Object: {
+		oss << '{' << (level != 0 ? "\n" : "");
+
+		unsigned total = m_object.size();
+		unsigned i = 0;
+		for (const auto &pair : m_object) {
+			oss << indent(level, current + 1);
+
+			/* Key and : */
+			oss << "\"" << pair.first << "\":" << (level != 0 ? " " : "");
+
+			/* Value */
+			oss << pair.second.toJson(level, current + 1);
+
+			/* Comma, new line if needed */
+			oss << (++i < total ? "," : "") << (level != 0 ? "\n" : "");
+		}
+
+		oss << (level != 0 ? indent(level, current) : "") << '}';
+		break;
+	}
+	case Type::Real:
+		oss << m_number;
+		break;
+	case Type::String:
+		oss << "\"" << escape(m_string) << "\"";
+		break;
+	default:
+		break;
+	}
+
+	return oss.str();
+}
+
+std::string escape(const std::string &value)
+{
+	std::string result;
+
+	for (auto it = value.begin(); it != value.end(); ++it) {
+		switch (*it) {
+		case '\\':
+			result += "\\\\";
+			break;
+		case '/':
+			result += "\\/";
+			break;
+		case '"':
+			result += "\\\"";
+			break;
+		case '\b':
+			result += "\\b";
+			break;
+		case '\f':
+			result += "\\f";
+			break;
+		case '\n':
+			result += "\\n";
+			break;
+		case '\r':
+			result += "\\r";
+			break;
+		case '\t':
+			result += "\\t";
+			break;
+		default:
+			result += *it;
+			break;
+		}
+	}
+
+	return result;
+}
+
+} // !json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Json/json.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,1161 @@
+/*
+ * json.h -- C++14 JSON manipulation using jansson parser
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _JSON_H_
+#define _JSON_H_
+
+/**
+ * @file json.h
+ * @brief Jansson C++14 wrapper
+ *
+ * These classes can be used to build or parse JSON documents using jansson library. It is designed to be safe
+ * and explicit. It does not implement implicit sharing like jansson so when you access (e.g. Value::toObject) values
+ * you get real copies, thus when you read big documents it can has a performance cost.
+ */
+
+#include <cassert>
+#include <exception>
+#include <initializer_list>
+#include <map>
+#include <string>
+#include <utility>
+#include <deque>
+
+/**
+ * Json namespace.
+ */
+namespace json {
+
+/**
+ * @enum Type
+ * @brief Type of Value.
+ */
+enum class Type {
+	Array,		//!< Value is an array []
+	Boolean,	//!< Value is boolean
+	Int,		//!< Value is integer
+	Real,		//!< Value is float
+	Object,		//!< Value is object {}
+	String,		//!< Value is unicode string
+	Null		//!< Value is defined to null
+};
+
+/**
+ * @class Error
+ * @brief Error description.
+ */
+class Error : public std::exception {
+private:
+	std::string m_text;
+	std::string m_source;
+	int m_line;
+	int m_column;
+	int m_position;
+
+public:
+	/**
+	 * Create the error.
+	 *
+	 * @param text the text message
+	 * @param source the source (e.g. file name)
+	 * @param line the line number
+	 * @param column the column number
+	 * @param position the position
+	 */
+	inline Error(std::string text, std::string source, int line, int column, int position) noexcept
+		: m_text{std::move(text)}
+		, m_source{std::move(source)}
+		, m_line{line}
+		, m_column{column}
+		, m_position{position}
+	{
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the text
+	 */
+	inline const std::string &text() const noexcept
+	{
+		return m_text;
+	}
+
+	/**
+	 * Get the source (e.g. a file name).
+	 *
+	 * @return the source
+	 */
+	inline const std::string &source() const noexcept
+	{
+		return m_source;
+	}
+
+	/**
+	 * Get the line.
+	 *
+	 * @return the line
+	 */
+	inline int line() const noexcept
+	{
+		return m_line;
+	}
+
+	/**
+	 * Get the column.
+	 *
+	 * @return the column
+	 */
+	inline int column() const noexcept
+	{
+		return m_column;
+	}
+
+	/**
+	 * Get the position.
+	 *
+	 * @return the position
+	 */
+	inline int position() const noexcept
+	{
+		return m_position;
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the message
+	 */
+	const char *what() const noexcept override
+	{
+		return m_text.c_str();
+	}
+};
+
+/**
+ * @class Buffer
+ * @brief Open JSON document from text.
+ */
+class Buffer {
+public:
+	std::string text;	//!< The JSON text
+};
+
+/**
+ * @class File
+ * @brief Open JSON document from a file.
+ */
+class File {
+public:
+	std::string path;	//!< The path to the file
+};
+
+/**
+ * @class Value
+ * @brief Generic JSON value wrapper.
+ */
+class Value {
+private:
+	Type m_type{Type::Null};
+
+	union {
+		double m_number;
+		bool m_boolean;
+		int m_integer;
+		std::string m_string;
+		std::deque<Value> m_array;
+		std::map<std::string, Value> m_object;
+	};
+
+	void copy(const Value &);
+	void move(Value &&);
+	std::string toJson(int indent, int current) const;
+
+	/**
+	 * @class BaseIterator
+	 * @brief This is the base class for iterator and const_iterator
+	 *
+	 * This iterator works for both arrays and objects. Because of that purpose, it is only available
+	 * as forward iterator.
+	 *
+	 * When iterator comes from an object, you can use key() otherwise you can use index().
+	 */
+	template <typename ValueType, typename ArrayIteratorType, typename ObjectIteratorType>
+	class BaseIterator : public std::iterator<std::forward_iterator_tag, ValueType> {
+	private:
+		friend class Value;
+
+		ValueType &m_value;
+		ArrayIteratorType m_ita;
+		ObjectIteratorType m_itm;
+
+		inline void increment()
+		{
+			if (m_value.isObject()) {
+				m_itm++;
+			} else {
+				m_ita++;
+			}
+		}
+
+		BaseIterator(ValueType &value, ObjectIteratorType it)
+			: m_value(value)
+			, m_itm(it)
+		{
+		}
+
+		BaseIterator(ValueType &value, ArrayIteratorType it)
+			: m_value(value)
+			, m_ita(it)
+		{
+		}
+
+	public:
+		/**
+		 * Get the iterator key (for objects).
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @pre iterator must come from object
+		 * @return the key
+		 */
+		inline const std::string &key() const noexcept
+		{
+			assert(m_value.isObject());
+			assert(m_itm != m_value.m_object.end());
+
+			return m_itm->first;
+		}
+
+		/**
+		 * Get the iterator position (for arrays).
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @pre iterator must come from arrays
+		 * @return the index
+		 */
+		inline unsigned index() const noexcept
+		{
+			assert(m_value.isArray());
+			assert(m_ita != m_value.m_array.end());
+
+			return std::distance(m_value.m_array.begin(), m_ita);
+		}
+
+		/**
+		 * Dereference the iterator.
+		 *
+		 * @pre iterator be dereferenceable
+		 * @return the value
+		 */
+		inline ValueType &operator*() noexcept
+		{
+			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
+			       (m_value.isObject() && m_itm != m_value.m_object.end()));
+
+			return (m_value.m_type == Type::Object) ? m_itm->second : *m_ita;
+		}
+
+		/**
+		 * Dereference the iterator as a pointer.
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @return the value
+		 */
+		inline ValueType *operator->() noexcept
+		{
+			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
+			       (m_value.isObject() && m_itm != m_value.m_object.end()));
+
+			return (m_value.m_type == Type::Object) ? &m_itm->second : &(*m_ita);
+		}
+
+		/**
+		 * Increment the iterator. (Prefix version).
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @return *this;
+		 */
+		inline BaseIterator &operator++() noexcept
+		{
+			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
+			       (m_value.isObject() && m_itm != m_value.m_object.end()));
+
+			increment();
+
+			return *this;
+		}
+
+		/**
+		 * Increment the iterator. (Postfix version).
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @return *this;
+		 */
+		inline BaseIterator &operator++(int) noexcept
+		{
+			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
+			       (m_value.isObject() && m_itm != m_value.m_object.end()));
+
+			increment();
+
+			return *this;
+		}
+
+		/**
+		 * Compare two iterators.
+		 *
+		 * @param it1 the first iterator
+		 * @param it2 the second iterator
+		 * @return true if they are same
+		 */
+		bool operator==(const BaseIterator &it) const noexcept
+		{
+			if (m_value.isObject() && it.m_value.isObject())
+				return m_itm == it.m_itm;
+			if (m_value.isArray() && it.m_value.isArray())
+				return m_ita == it.m_ita;
+
+			return false;
+		}
+
+		/**
+		 * Test if the iterator is different.
+		 *
+		 * @param it the iterator
+		 * @return true if they are different
+		 */
+		inline bool operator!=(const BaseIterator &it) const noexcept
+		{
+			return !(*this == it);
+		}
+	};
+
+public:
+	/**
+	 * Forward iterator.
+	 */
+	using iterator = BaseIterator<Value, typename std::deque<Value>::iterator, typename std::map<std::string, Value>::iterator>;
+
+	/**
+	 * Const forward iterator.
+	 */
+	using const_iterator = BaseIterator<const Value, typename std::deque<Value>::const_iterator, typename std::map<std::string, Value>::const_iterator>;
+
+	/**
+	 * Construct a null value.
+	 */
+	inline Value()
+	{
+	}
+
+	/**
+	 * Create a value with a specified type, this is usually only needed when you want to create an object or
+	 * an array.
+	 *
+	 * For any other types, initialize with sane default value.
+	 *
+	 * @param type the type
+	 */
+	Value(Type type);
+
+	/**
+	 * Construct a null value.
+	 */
+	inline Value(std::nullptr_t) noexcept
+		: m_type{Type::Null}
+	{
+	}
+
+	/**
+	 * Construct a boolean value.
+	 *
+	 * @param value the boolean value
+	 */
+	inline Value(bool value) noexcept
+		: m_type{Type::Boolean}
+		, m_boolean{value}
+	{
+	}
+
+	/**
+	 * Create value from integer.
+	 *
+	 * @param value the value
+	 */
+	inline Value(int value) noexcept
+		: m_type{Type::Int}
+		, m_integer{value}
+	{
+	}
+
+	/**
+	 * Construct a value from a C-string.
+	 *
+	 * @param value the C-string
+	 */
+	inline Value(const char *value)
+		: m_type{Type::String}
+	{
+		new (&m_string) std::string{value ? value : ""};
+	}
+
+	/**
+	 * Construct a number value.
+	 *
+	 * @param value the real value
+	 */
+	inline Value(double value) noexcept
+		: m_type{Type::Real}
+		, m_number{value}
+	{
+	}
+
+	/**
+	 * Construct a string value.
+	 *
+	 * @param value the string
+	 */
+	inline Value(std::string value) noexcept
+		: m_type{Type::String}
+	{
+		new (&m_string) std::string{std::move(value)};
+	}
+
+	/**
+	 * Create an object from a map.
+	 *
+	 * @param values the values
+	 * @see fromObject
+	 */
+	inline Value(std::map<std::string, Value> values)
+		: Value{Type::Object}
+	{
+		for (const auto &pair : values) {
+			insert(pair.first, pair.second);
+		}
+	}
+
+	/**
+	 * Create an array from a deque.
+	 *
+	 * @param values the values
+	 * @see fromArray
+	 */
+	inline Value(std::deque<Value> values)
+		: Value{Type::Array}
+	{
+		for (Value value : values) {
+			append(std::move(value));
+		}
+	}
+
+	/**
+	 * Construct a value from a buffer.
+	 *
+	 * @param buffer the text
+	 * @throw Error on errors
+	 */
+	Value(const Buffer &buffer);
+
+	/**
+	 * Construct a value from a file.
+	 *
+	 * @param file the file
+	 * @throw Error on errors
+	 */
+	Value(const File &file);
+
+	/**
+	 * Move constructor.
+	 *
+	 * @param other the value to move from
+	 */
+	inline Value(Value &&other)
+	{
+		move(std::move(other));
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the value to copy from
+	 */
+	inline Value(const Value &other)
+	{
+		copy(other);
+	}
+
+	/**
+	 * Copy operator.
+	 *
+	 * @param other the value to copy from
+	 * @return *this
+	 */
+	inline Value &operator=(const Value &other)
+	{
+		copy(other);
+
+		return *this;
+	}
+
+	/**
+	 * Move operator.
+	 *
+	 * @param other the value to move from
+	 */
+	inline Value &operator=(Value &&other)
+	{
+		move(std::move(other));
+
+		return *this;
+	}
+
+	/**
+	 * Destructor.
+	 */
+	~Value();
+
+	/**
+	 * Get an iterator to the beginning.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline iterator begin() noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? iterator(*this, m_object.begin()) : iterator(*this, m_array.begin());
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator begin() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(*this, m_object.begin()) : const_iterator(*this, m_array.begin());
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator cbegin() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(*this, m_object.cbegin()) : const_iterator(*this, m_array.cbegin());
+	}
+
+	/**
+	 * Get an iterator to the end.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline iterator end() noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? iterator(*this, m_object.end()) : iterator(*this, m_array.end());
+	}
+
+	/**
+	 * Get an iterator to the end.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator end() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(*this, m_object.end()) : const_iterator(*this, m_array.end());
+	}
+
+	/**
+	 * Get an iterator to the end.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator cend() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(*this, m_object.cend()) : const_iterator(*this, m_array.cend());
+	}
+
+	/**
+	 * Get the value type.
+	 *
+	 * @return the type
+	 */
+	inline Type typeOf() const noexcept
+	{
+		return m_type;
+	}
+
+	/**
+	 * Get the value as boolean.
+	 *
+	 * @return the value or false if not a boolean
+	 */
+	bool toBool() const noexcept;
+
+	/**
+	 * Get the value as integer.
+	 *
+	 * @return the value or 0 if not a integer
+	 */
+	int toInt() const noexcept;
+
+	/**
+	 * Get the value as real.
+	 *
+	 * @return the value or 0 if not a real
+	 */
+	double toReal() const noexcept;
+
+	/**
+	 * Get the value as string.
+	 *
+	 * @return the value or empty stirng if not a string
+	 */
+	std::string toString() const noexcept;
+
+	/**
+	 * Check if the value is boolean type.
+	 *
+	 * @return true if boolean
+	 */
+	inline bool isBool() const noexcept
+	{
+		return m_type == Type::Boolean;
+	}
+
+	/**
+	 * Check if the value is integer type.
+	 *
+	 * @return true if integer
+	 */
+	inline bool isInt() const noexcept
+	{
+		return m_type == Type::Int;
+	}
+
+	/**
+	 * Check if the value is object type.
+	 *
+	 * @return true if object
+	 */
+	inline bool isObject() const noexcept
+	{
+		return m_type == Type::Object;
+	}
+
+	/**
+	 * Check if the value is array type.
+	 *
+	 * @return true if array
+	 */
+	inline bool isArray() const noexcept
+	{
+		return m_type == Type::Array;
+	}
+
+	/**
+	 * Check if the value is integer or real type.
+	 *
+	 * @return true if integer or real
+	 * @see toInt
+	 * @see toReal
+	 */
+	inline bool isNumber() const noexcept
+	{
+		return m_type == Type::Real || m_type == Type::Int;
+	}
+
+	/**
+	 * Check if the value is real type.
+	 *
+	 * @return true if real
+	 */
+	inline bool isReal() const noexcept
+	{
+		return m_type == Type::Real;
+	}
+
+	/**
+	 * Check if the value is null type.
+	 *
+	 * @return true if null
+	 */
+	inline bool isNull() const noexcept
+	{
+		return m_type == Type::Null;
+	}
+
+	/**
+	 * Check if the value is string type.
+	 *
+	 * @return true if string
+	 */
+	inline bool isString() const noexcept
+	{
+		return m_type == Type::String;
+	}
+
+	/**
+	 * Get the array or object size.
+	 *
+	 * @pre must be an array or object
+	 * @return the size
+	 */
+	inline unsigned size() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		if (m_type == Type::Object) {
+			return m_object.size();
+		}
+
+		return m_array.size();
+	}
+
+	/**
+	 * Remove all the values.
+	 *
+	 * @pre must be an array or an object
+	 */
+	inline void clear() noexcept
+	{
+		assert(isArray() || isObject());
+
+		if (m_type == Type::Array) {
+			m_array.clear();
+		} else {
+			m_object.clear();
+		}
+	}
+
+	/*
+	 * Array functions
+	 * ----------------------------------------------------------
+	 */
+
+	/**
+	 * Get the value at the specified position or the defaultValue if position is out of bounds.
+	 *
+	 * @param position the position
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	inline Value valueOr(unsigned position, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Array || position >= m_array.size()) {
+			return defaultValue;
+		}
+
+		return m_array[position];
+	}
+
+	/**
+	 * Get a value at the specified index.
+	 *
+	 * @pre must be an array
+	 * @param position the position
+	 * @return the value
+	 * @throw std::out_of_range if out of bounds
+	 */
+	inline const Value &at(unsigned position) const
+	{
+		assert(isArray());
+
+		return m_array.at(position);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @param position the position
+	 * @return the value
+	 * @throw std::out_of_range if out of bounds
+	 */
+	inline Value &at(unsigned position)
+	{
+		assert(isArray());
+
+		return m_array.at(position);
+	}
+
+	/**
+	 * Get a value at the specified index.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @return the value
+	 */
+	inline const Value &operator[](unsigned position) const
+	{
+		assert(isArray());
+		assert(position < m_array.size());
+
+		return m_array[position];
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @return the value
+	 */
+	inline Value &operator[](unsigned position)
+	{
+		assert(isArray());
+		assert(position < m_array.size());
+
+		return m_array[position];
+	}
+
+	/**
+	 * Push a value to the beginning of the array.
+	 *
+	 * @pre must be an array
+	 * @param value the value to push
+	 */
+	inline void push(const Value &value)
+	{
+		assert(isArray());
+
+		m_array.push_front(value);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @param value the value to push
+	 */
+	inline void push(Value &&value)
+	{
+		assert(isArray());
+
+		m_array.push_front(std::move(value));
+	}
+
+	/**
+	 * Insert a value at the specified position.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @param value the value to push
+	 */
+	inline void insert(unsigned position, const Value &value)
+	{
+		assert(isArray());
+		assert(position <= m_array.size());
+
+		m_array.insert(m_array.begin() + position, value);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @param value the value to push
+	 */
+	inline void insert(unsigned position, Value &&value)
+	{
+		assert(isArray());
+		assert(position <= m_array.size());
+
+		m_array.insert(m_array.begin() + position, std::move(value));
+	}
+
+	/**
+	 * Add a new value to the end.
+	 *
+	 * @pre must be an array
+	 * @param value the value to append
+	 */
+	inline void append(const Value &value)
+	{
+		assert(isArray());
+
+		m_array.push_back(value);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @param value the value to append
+	 */
+	inline void append(Value &&value)
+	{
+		assert(isArray());
+
+		m_array.push_back(std::move(value));
+	}
+
+	/**
+	 * Remove a value at the specified position.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 */
+	inline void erase(unsigned position)
+	{
+		assert(isArray());
+		assert(position < m_array.size());
+
+		m_array.erase(m_array.begin() + position);
+	}
+
+	/*
+	 * Object functions
+	 * ----------------------------------------------------------
+	 */
+
+	/**
+	 * Get the value at the specified key or the defaultValue if key is absent.
+	 *
+	 * @param name the name
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	Value valueOr(const std::string &name, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Object) {
+			return defaultValue;
+		}
+
+		auto it = m_object.find(name);
+
+		if (it == m_object.end()) {
+			return defaultValue;
+		}
+
+		return it->second;
+	}
+
+	/**
+	 * Get a value from the object.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 * @throw std::out_of_range if not found
+	 */
+	inline const Value &at(const std::string &name) const
+	{
+		assert(isObject());
+
+		return m_object.at(name);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 * @throw std::out_of_range if not found
+	 */
+	inline Value &at(const std::string &name)
+	{
+		assert(isObject());
+
+		return m_object.at(name);
+	}
+
+	/**
+	 * Get a value from the object.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 */
+	inline Value &operator[](const std::string &name)
+	{
+		assert(isObject());
+
+		return m_object[name];
+	}
+
+	/**
+	 * Get a value from the object.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 */
+	inline const Value &operator[](const std::string &name) const
+	{
+		assert(isObject());
+
+		return m_object.at(name);
+	}
+
+	/**
+	 * Find a value by key.
+	 *
+	 * @pre must be an object
+	 * @param key the property key
+	 * @return the iterator or past the end if not found
+	 */
+	inline iterator find(const std::string &key)
+	{
+		assert(isObject());
+
+		return iterator(*this, m_object.find(key));
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an object
+	 * @param key the property key
+	 * @return the iterator or past the end if not found
+	 */
+	inline const_iterator find(const std::string &key) const
+	{
+		assert(isObject());
+
+		return const_iterator(*this, m_object.find(key));
+	}
+
+	/**
+	 * Insert a new value.
+	 *
+	 * @pre must be an object
+	 * @param name the key
+	 * @param value the value
+	 */
+	inline void insert(std::string name, const Value &value)
+	{
+		assert(isObject());
+
+		m_object.insert({std::move(name), value});
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an object
+	 * @param name the key
+	 * @param value the value
+	 */
+	inline void insert(std::string name, Value &&value)
+	{
+		assert(isObject());
+
+		m_object.insert({std::move(name), std::move(value)});
+	}
+
+	/**
+	 * Check if a value exists.
+	 *
+	 * @pre must be an object
+	 * @param key the key value
+	 * @return true if exists
+	 */
+	inline bool contains(const std::string &key) const noexcept
+	{
+		assert(isObject());
+
+		return m_object.find(key) != m_object.end();
+	}
+
+	/**
+	 * Remove a value of the specified key.
+	 *
+	 * @pre must be an object
+	 * @param key the value key
+	 */
+	inline void erase(const std::string &key)
+	{
+		assert(isObject());
+
+		m_object.erase(key);
+	}
+
+	/**
+	 * Return this value as JSon representation.
+	 *
+	 * @param indent, the indentation to use (0 == compact, < 0 == tabs, > 0 == number of spaces)
+	 * @param tabs, use tabs or not
+	 * @return the string
+	 */
+	inline std::string toJson(int indent = 2) const
+	{
+		return toJson(indent, 0);
+	}
+};
+
+/**
+ * Escape the input.
+ *
+ * @param input the input
+ * @return the escaped string
+ */
+std::string escape(const std::string &input);
+
+/**
+ * Convenient function for creating array from initializer list.
+ *
+ * @param values the values
+ * @return the array
+ */
+inline Value array(std::initializer_list<Value> values)
+{
+	return Value(std::deque<Value>(values.begin(), values.end()));
+}
+
+/**
+ * Convenient function for creating object from initializer list.
+ *
+ * @param values the values
+ * @return the object
+ */
+inline Value object(std::initializer_list<std::pair<std::string, Value>> values)
+{
+	return Value(std::map<std::string, Value>(values.begin(), values.end()));
+}
+
+} // !json
+
+#endif // !_JSON_H_
--- a/C++/modules/OptionParser/OptionParser.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +0,0 @@
-/*
- * OptionParser.cpp -- parse Unix command line options
- *
- * Copyright (c) 2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <cassert>
-
-#include "OptionParser.h"
-
-namespace parser {
-
-namespace {
-
-using Iterator = std::vector<std::string>::iterator;
-using Args = std::vector<std::string>;
-
-inline bool isOption(const std::string &arg) noexcept
-{
-	return arg.size() >= 2 && arg[0] == '-';
-}
-
-inline bool isLongOption(const std::string &arg) noexcept
-{
-	assert(isOption(arg));
-
-	return arg.size() >= 3 && arg[1] == '-';
-}
-
-inline bool isShortSimple(const std::string &arg) noexcept
-{
-	assert(isOption(arg));
-	assert(!isLongOption(arg));
-
-	return arg.size() == 2;
-}
-
-void parseLongOption(Result &result, Args &args, Iterator &it, Iterator &end, const Options &definition)
-{
-	auto arg = *it++;
-	auto opt = definition.find(arg);
-
-	if (opt == definition.end()) {
-		throw InvalidOption{arg};
-	}
-
-	/* Need argument? */
-	if (opt->second) {
-		if (it == end || isOption(*it)) {
-			throw MissingValue{arg};
-		}
-
-		result.insert(std::make_pair(arg, *it++));
-		it = args.erase(args.begin(), it);
-		end = args.end();
-	} else {
-		result.insert(std::make_pair(arg, ""));
-		it = args.erase(args.begin());
-		end = args.end();
-	}
-}
-
-void parseShortOption(Result &result, Args &args, Iterator &it, Iterator &end, const Options &definition)
-{
-	if (isShortSimple(*it)) {
-		/*
-		 * Here two cases:
-		 *
-		 * -v (no option)
-		 * -c value
-		 */
-		auto arg = *it++;
-		auto opt = definition.find(arg);
-
-		if (opt == definition.end()) {
-			throw InvalidOption{arg};
-		}
-
-		/* Need argument? */
-		if (opt->second) {
-			if (it == end || isOption(*it)) {
-				throw MissingValue{arg};
-			}
-
-			result.insert(std::make_pair(arg, *it++));
-			it = args.erase(args.begin(), it);
-			end = args.end();
-		} else {
-			result.insert(std::make_pair(arg, ""));
-			it = args.erase(args.begin());
-			end = args.end();
-		}
-	} else {
-		/*
-		 * Here multiple scenarios:
-		 *
-		 * 1. -abc (-a -b -c if all are simple boolean arguments)
-		 * 2. -vc foo.conf (-v -c foo.conf if -c is argument dependant)
-		 * 3. -vcfoo.conf (-v -c foo.conf also)
-		 */
-		auto value = it->substr(1);
-		auto len = value.length();
-		int toremove = 1;
-
-		for (decltype(len) i = 0; i < len; ++i) {
-			auto arg = std::string{'-'} + value[i];
-			auto opt = definition.find(arg);
-
-			if (opt == definition.end()) {
-				throw InvalidOption{arg};
-			}
-
-			if (opt->second) {
-				if (i == (len - 1)) {
-					/* End of string, get the next argument (see 2.) */
-					if (++it == end || isOption(*it)) {
-						throw MissingValue{arg};
-					}
-
-					result.insert(std::make_pair(arg, *it));
-					toremove += 1;
-				} else {
-					result.insert(std::make_pair(arg, value.substr(i + 1)));
-					i = len;
-				}
-			} else {
-				result.insert(std::make_pair(arg, ""));
-			}
-		}
-
-		it = args.erase(args.begin(), args.begin() + toremove);
-		end = args.end();
-	}
-}
-
-} // !namespace
-
-Result read(std::vector<std::string> &args, const Options &definition)
-{
-	Result result;
-
-	auto it = args.begin();
-	auto end = args.end();
-
-	while (it != end) {
-		if (!isOption(*it)) {
-			break;
-		}
-
-		if (isLongOption(*it)) {
-			parseLongOption(result, args, it, end, definition);
-		} else {
-			parseShortOption(result, args, it, end, definition);
-		}
-	}
-
-	return result;
-}
-
-Result read(int &argc, char **&argv, const Options &definition)
-{
-	std::vector<std::string> args;
-
-	for (int i = 0; i < argc; ++i) {
-		args.push_back(argv[i]);
-	}
-
-	auto before = args.size();
-	auto result = read(args, definition);
-
-	argc -= before - args.size();
-	argv += before - args.size();
-
-	return result;
-}
-
-} // !parser
\ No newline at end of file
--- a/C++/modules/OptionParser/OptionParser.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * OptionParser.h -- parse Unix command line options
- *
- * Copyright (c) 2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _OPTION_PARSER_H_
-#define _OPTION_PARSER_H_
-
-#include <exception>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-/**
- * Namespace for options parsing.
- */
-namespace parser {
-
-/**
- * @class InvalidOption
- * @brief This exception is thrown when an invalid option has been found.
- */
-class InvalidOption : public std::exception {
-private:
-	std::string message;
-
-public:
-	/**
-	 * The invalid option given.
-	 */
-	std::string argument;
-
-	/**
-	 * Construct the exception.
-	 *
-	 * @param arg the argument missing
-	 */
-	inline InvalidOption(std::string arg)
-		: argument{std::move(arg)}
-	{
-		message = std::string{"invalid option: "} + argument;
-	}
-
-	/**
-	 * Get the error message.
-	 *
-	 * @return the error message
-	 */
-	const char *what() const noexcept override
-	{
-		return message.c_str();
-	}
-};
-
-/**
- * @class MissingValue
- * @brief This exception is thrown when an option requires a value and no value has been given
- */
-class MissingValue : public std::exception {
-private:
-	std::string message;
-
-public:
-	/**
-	 * The argument that requires a value.
-	 */
-	std::string argument;
-
-	/**
-	 * Construct the exception.
-	 *
-	 * @param arg the argument that requires a value
-	 */
-	inline MissingValue(std::string arg)
-		: argument{std::move(arg)}
-	{
-		message = std::string{"missing argument for: "} + argument;
-	}
-
-	/**
-	 * Get the error message.
-	 *
-	 * @return the error message
-	 */
-	const char *what() const noexcept override
-	{
-		return message.c_str();
-	}
-};
-
-/**
- * Packed multimap of options.
- */
-using Result = std::multimap<std::string, std::string>;
-
-/**
- * Define the allowed options.
- */
-using Options = std::map<std::string, bool>;
-
-/**
- * Extract the command line options and return a result.
- *
- * @param args the arguments
- * @param definition
- * @warning the arguments vector is modified in place to remove parsed options
- * @throw MissingValue
- * @throw InvalidOption
- */
-Result read(std::vector<std::string> &args, const Options &definition);
-
-/**
- * Overloaded function for usage with main() arguments.
- *
- * @param argc the number of arguments
- * @param argv the argument vector
- * @param definition
- * @note don't forget to remove the first argv[0] argument
- * @warning the argc and argv are modified in place to remove parsed options
- * @throw MissingValue
- * @throw InvalidOption
- */
-Result read(int &argc, char **&argv, const Options &definition);
-
-} // !parser
-
-#endif // !_OPTION_PARSER_H_
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/OptionParser/options.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,189 @@
+/*
+ * options.cpp -- parse Unix command line options
+ *
+ * Copyright (c) 2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cassert>
+
+#include "options.h"
+
+namespace option {
+
+namespace {
+
+using Iterator = std::vector<std::string>::iterator;
+using Args = std::vector<std::string>;
+
+inline bool isOption(const std::string &arg) noexcept
+{
+	return arg.size() >= 2 && arg[0] == '-';
+}
+
+inline bool isLongOption(const std::string &arg) noexcept
+{
+	assert(isOption(arg));
+
+	return arg.size() >= 3 && arg[1] == '-';
+}
+
+inline bool isShortSimple(const std::string &arg) noexcept
+{
+	assert(isOption(arg));
+	assert(!isLongOption(arg));
+
+	return arg.size() == 2;
+}
+
+void parseLongOption(Result &result, Args &args, Iterator &it, Iterator &end, const Options &definition)
+{
+	auto arg = *it++;
+	auto opt = definition.find(arg);
+
+	if (opt == definition.end()) {
+		throw InvalidOption{arg};
+	}
+
+	/* Need argument? */
+	if (opt->second) {
+		if (it == end || isOption(*it)) {
+			throw MissingValue{arg};
+		}
+
+		result.insert(std::make_pair(arg, *it++));
+		it = args.erase(args.begin(), it);
+		end = args.end();
+	} else {
+		result.insert(std::make_pair(arg, ""));
+		it = args.erase(args.begin());
+		end = args.end();
+	}
+}
+
+void parseShortOption(Result &result, Args &args, Iterator &it, Iterator &end, const Options &definition)
+{
+	if (isShortSimple(*it)) {
+		/*
+		 * Here two cases:
+		 *
+		 * -v (no option)
+		 * -c value
+		 */
+		auto arg = *it++;
+		auto opt = definition.find(arg);
+
+		if (opt == definition.end()) {
+			throw InvalidOption{arg};
+		}
+
+		/* Need argument? */
+		if (opt->second) {
+			if (it == end || isOption(*it)) {
+				throw MissingValue{arg};
+			}
+
+			result.insert(std::make_pair(arg, *it++));
+			it = args.erase(args.begin(), it);
+			end = args.end();
+		} else {
+			result.insert(std::make_pair(arg, ""));
+			it = args.erase(args.begin());
+			end = args.end();
+		}
+	} else {
+		/*
+		 * Here multiple scenarios:
+		 *
+		 * 1. -abc (-a -b -c if all are simple boolean arguments)
+		 * 2. -vc foo.conf (-v -c foo.conf if -c is argument dependant)
+		 * 3. -vcfoo.conf (-v -c foo.conf also)
+		 */
+		auto value = it->substr(1);
+		auto len = value.length();
+		int toremove = 1;
+
+		for (decltype(len) i = 0; i < len; ++i) {
+			auto arg = std::string{'-'} + value[i];
+			auto opt = definition.find(arg);
+
+			if (opt == definition.end()) {
+				throw InvalidOption{arg};
+			}
+
+			if (opt->second) {
+				if (i == (len - 1)) {
+					/* End of string, get the next argument (see 2.) */
+					if (++it == end || isOption(*it)) {
+						throw MissingValue{arg};
+					}
+
+					result.insert(std::make_pair(arg, *it));
+					toremove += 1;
+				} else {
+					result.insert(std::make_pair(arg, value.substr(i + 1)));
+					i = len;
+				}
+			} else {
+				result.insert(std::make_pair(arg, ""));
+			}
+		}
+
+		it = args.erase(args.begin(), args.begin() + toremove);
+		end = args.end();
+	}
+}
+
+} // !namespace
+
+Result read(std::vector<std::string> &args, const Options &definition)
+{
+	Result result;
+
+	auto it = args.begin();
+	auto end = args.end();
+
+	while (it != end) {
+		if (!isOption(*it)) {
+			break;
+		}
+
+		if (isLongOption(*it)) {
+			parseLongOption(result, args, it, end, definition);
+		} else {
+			parseShortOption(result, args, it, end, definition);
+		}
+	}
+
+	return result;
+}
+
+Result read(int &argc, char **&argv, const Options &definition)
+{
+	std::vector<std::string> args;
+
+	for (int i = 0; i < argc; ++i) {
+		args.push_back(argv[i]);
+	}
+
+	auto before = args.size();
+	auto result = read(args, definition);
+
+	argc -= before - args.size();
+	argv += before - args.size();
+
+	return result;
+}
+
+} // !option
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/OptionParser/options.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,141 @@
+/*
+ * options.h -- parse Unix command line options
+ *
+ * Copyright (c) 2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _OPTIONS_H_
+#define _OPTIONS_H_
+
+#include <exception>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+/**
+ * Namespace for options parsing.
+ */
+namespace option {
+
+/**
+ * @class InvalidOption
+ * @brief This exception is thrown when an invalid option has been found.
+ */
+class InvalidOption : public std::exception {
+private:
+	std::string message;
+
+public:
+	/**
+	 * The invalid option given.
+	 */
+	std::string argument;
+
+	/**
+	 * Construct the exception.
+	 *
+	 * @param arg the argument missing
+	 */
+	inline InvalidOption(std::string arg)
+		: argument{std::move(arg)}
+	{
+		message = std::string{"invalid option: "} + argument;
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the error message
+	 */
+	const char *what() const noexcept override
+	{
+		return message.c_str();
+	}
+};
+
+/**
+ * @class MissingValue
+ * @brief This exception is thrown when an option requires a value and no value has been given
+ */
+class MissingValue : public std::exception {
+private:
+	std::string message;
+
+public:
+	/**
+	 * The argument that requires a value.
+	 */
+	std::string argument;
+
+	/**
+	 * Construct the exception.
+	 *
+	 * @param arg the argument that requires a value
+	 */
+	inline MissingValue(std::string arg)
+		: argument{std::move(arg)}
+	{
+		message = std::string{"missing argument for: "} + argument;
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the error message
+	 */
+	const char *what() const noexcept override
+	{
+		return message.c_str();
+	}
+};
+
+/**
+ * Packed multimap of options.
+ */
+using Result = std::multimap<std::string, std::string>;
+
+/**
+ * Define the allowed options.
+ */
+using Options = std::map<std::string, bool>;
+
+/**
+ * Extract the command line options and return a result.
+ *
+ * @param args the arguments
+ * @param definition
+ * @warning the arguments vector is modified in place to remove parsed options
+ * @throw MissingValue
+ * @throw InvalidOption
+ */
+Result read(std::vector<std::string> &args, const Options &definition);
+
+/**
+ * Overloaded function for usage with main() arguments.
+ *
+ * @param argc the number of arguments
+ * @param argv the argument vector
+ * @param definition
+ * @note don't forget to remove the first argv[0] argument
+ * @warning the argc and argv are modified in place to remove parsed options
+ * @throw MissingValue
+ * @throw InvalidOption
+ */
+Result read(int &argc, char **&argv, const Options &definition);
+
+} // !option
+
+#endif // !_OPTIONS_H_
--- a/C++/modules/Socket/Sockets.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,709 +0,0 @@
-/*
- * Sockets.cpp -- portable C++ socket wrappers
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define TIMEOUT_MSG "operation timeout"
-
-#include <algorithm>
-#include <atomic>
-#include <cstring>
-#include <mutex>
-
-#include "Sockets.h"
-
-namespace net {
-
-/*
- * Portable constants
- * ------------------------------------------------------------------
- */
-
-/* {{{ Constants */
-
-#if defined(_WIN32)
-
-const Handle Invalid{INVALID_SOCKET};
-const int Failure{SOCKET_ERROR};
-
-#else
-
-const Handle Invalid{-1};
-const int Failure{-1};
-
-#endif
-
-/* }}} */
-
-/*
- * Portable functions
- * ------------------------------------------------------------------
- */
-
-/* {{{ Functions */
-
-#if defined(_WIN32)
-
-namespace {
-
-static std::mutex s_mutex;
-static std::atomic<bool> s_initialized{false};
-
-} // !namespace
-
-#endif // !_WIN32
-
-void init() noexcept
-{
-#if defined(_WIN32)
-	std::lock_guard<std::mutex> lock(s_mutex);
-
-	if (!s_initialized) {
-		s_initialized = true;
-
-		WSADATA wsa;
-		WSAStartup(MAKEWORD(2, 2), &wsa);
-
-		/*
-		 * If SOCKET_WSA_NO_INIT is not set then the user
-		 * must also call finish himself.
-		 */
-#if !defined(SOCKET_NO_AUTO_INIT)
-		atexit(finish);
-#endif
-	}
-#endif
-}
-
-void finish() noexcept
-{
-#if defined(_WIN32)
-	WSACleanup();
-#endif
-}
-
-std::string error(int errn)
-{
-#if defined(_WIN32)
-	LPSTR str = nullptr;
-	std::string errmsg = "Unknown error";
-
-	FormatMessageA(
-		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-		NULL,
-		errn,
-		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		(LPSTR)&str, 0, NULL);
-
-
-	if (str) {
-		errmsg = std::string(str);
-		LocalFree(str);
-	}
-
-	return errmsg;
-#else
-	return strerror(errn);
-#endif
-}
-
-std::string error()
-{
-#if defined(_WIN32)
-	return error(WSAGetLastError());
-#else
-	return error(errno);
-#endif
-}
-
-/* }}} */
-
-/*
- * SSL stuff
- * ------------------------------------------------------------------
- */
-
-/* {{{ SSL initialization */
-
-#if !defined(SOCKET_NO_SSL)
-
-namespace ssl {
-
-namespace {
-
-std::mutex mutex;
-std::atomic<bool> initialized{false};
-
-} // !namespace
-
-void finish() noexcept
-{
-	ERR_free_strings();
-}
-
-void init() noexcept
-{
-	std::lock_guard<std::mutex> lock{mutex};
-
-	if (!initialized) {
-		initialized = true;
-
-		SSL_library_init();
-		SSL_load_error_strings();
-		OpenSSL_add_all_algorithms();
-
-#if !defined(SOCKET_NO_AUTO_SSL_INIT)
-		atexit(finish);
-#endif // SOCKET_NO_AUTO_SSL_INIT
-	}
-}
-
-} // !ssl
-
-#endif // SOCKET_NO_SSL
-
-/* }}} */
-
-/*
- * Error class
- * ------------------------------------------------------------------
- */
-
-/* {{{ Error */
-
-Error::Error(Code code, std::string function)
-	: m_code{code}
-	, m_function{std::move(function)}
-	, m_error{error()}
-{
-}
-
-Error::Error(Code code, std::string function, int n)
-	: m_code{code}
-	, m_function{std::move(function)}
-	, m_error{error(n)}
-{
-}
-
-Error::Error(Code code, std::string function, std::string error)
-	: m_code{code}
-	, m_function{std::move(function)}
-	, m_error{std::move(error)}
-{
-}
-
-/* }}} */
-
-/*
- * Predefine addressed to be used
- * ------------------------------------------------------------------
- */
-
-/* {{{ Addresses */
-
-namespace address {
-
-/* Default domain */
-int Ip::m_default{AF_INET};
-
-Ip::Ip(Type domain) noexcept
-	: m_domain(static_cast<int>(domain))
-{
-	assert(m_domain == AF_INET6 || m_domain == AF_INET);
-
-	if (m_domain == AF_INET6) {
-		std::memset(&m_sin6, 0, sizeof (sockaddr_in6));
-	} else {
-		std::memset(&m_sin, 0, sizeof (sockaddr_in));
-	}
-}
-
-Ip::Ip(const std::string &host, int port, Type domain)
-	: m_domain(static_cast<int>(domain))
-{
-	assert(m_domain == AF_INET6 || m_domain == AF_INET);
-
-	if (host == "*") {
-		if (m_domain == AF_INET6) {
-			std::memset(&m_sin6, 0, sizeof (sockaddr_in6));
-
-			m_length = sizeof (sockaddr_in6);
-			m_sin6.sin6_addr = in6addr_any;
-			m_sin6.sin6_family = AF_INET6;
-			m_sin6.sin6_port = htons(port);
-		} else {
-			std::memset(&m_sin, 0, sizeof (sockaddr_in));
-
-			m_length = sizeof (sockaddr_in);
-			m_sin.sin_addr.s_addr = INADDR_ANY;
-			m_sin.sin_family = AF_INET;
-			m_sin.sin_port = htons(port);
-		}
-	} else {
-		addrinfo hints, *res;
-
-		std::memset(&hints, 0, sizeof (addrinfo));
-		hints.ai_family = domain;
-
-		auto error = getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res);
-		if (error != 0) {
-			throw Error{Error::System, "getaddrinfo", gai_strerror(error)};
-		}
-
-		if (m_domain == AF_INET6) {
-			std::memcpy(&m_sin6, res->ai_addr, res->ai_addrlen);
-		} else {
-			std::memcpy(&m_sin, res->ai_addr, res->ai_addrlen);
-		}
-
-		m_length = res->ai_addrlen;
-		freeaddrinfo(res);
-	}
-}
-
-Ip::Ip(const sockaddr_storage *ss, socklen_t length) noexcept
-	: m_length{length}
-	, m_domain{ss->ss_family}
-{
-	assert(ss->ss_family == AF_INET6 || ss->ss_family == AF_INET);
-
-	if (ss->ss_family == AF_INET6) {
-		std::memcpy(&m_sin6, ss, length);
-	} else if (ss->ss_family == AF_INET) {
-		std::memcpy(&m_sin, ss, length);
-	}
-}
-
-#if !defined(_WIN32)
-
-Local::Local() noexcept
-{
-	std::memset(&m_sun, 0, sizeof (sockaddr_un));
-}
-
-Local::Local(std::string path, bool rm) noexcept
-	: m_path{std::move(path)}
-{
-	/* Silently remove the file even if it fails */
-	if (rm) {
-		::remove(m_path.c_str());
-	}
-
-	/* Copy the path */
-	std::memset(m_sun.sun_path, 0, sizeof (m_sun.sun_path));
-	std::strncpy(m_sun.sun_path, m_path.c_str(), sizeof (m_sun.sun_path) - 1);
-
-	/* Set the parameters */
-	m_sun.sun_family = AF_LOCAL;
-}
-
-Local::Local(const sockaddr_storage *ss, socklen_t length) noexcept
-{
-	assert(ss->ss_family == AF_LOCAL);
-
-	if (ss->ss_family == AF_LOCAL) {
-		std::memcpy(&m_sun, ss, length);
-		m_path = reinterpret_cast<const sockaddr_un &>(m_sun).sun_path;
-	}
-}
-
-#endif // !_WIN32
-
-} // !address
-
-/* }}} */
-
-/*
- * Select
- * ------------------------------------------------------------------
- */
-
-/* {{{ Select */
-
-std::vector<ListenerStatus> Select::wait(const ListenerTable &table, int ms)
-{
-	timeval maxwait, *towait;
-	fd_set readset;
-	fd_set writeset;
-
-	FD_ZERO(&readset);
-	FD_ZERO(&writeset);
-
-	Handle max = 0;
-
-	for (const auto &pair : table) {
-		if ((pair.second & Condition::Readable) == Condition::Readable) {
-			FD_SET(pair.first, &readset);
-		}
-		if ((pair.second & Condition::Writable) == Condition::Writable) {
-			FD_SET(pair.first, &writeset);
-		}
-
-		if (pair.first > max) {
-			max = pair.first;
-		}
-	}
-
-	maxwait.tv_sec = 0;
-	maxwait.tv_usec = ms * 1000;
-
-	// Set to nullptr for infinite timeout.
-	towait = (ms < 0) ? nullptr : &maxwait;
-
-	auto error = ::select(max + 1, &readset, &writeset, nullptr, towait);
-	if (error == Failure) {
-		throw Error{Error::System, "select"};
-	}
-	if (error == 0) {
-		throw Error{Error::Timeout, "select", TIMEOUT_MSG};
-	}
-
-	std::vector<ListenerStatus> sockets;
-
-	for (const auto &pair : table) {
-		if (FD_ISSET(pair.first, &readset)) {
-			sockets.push_back(ListenerStatus{pair.first, Condition::Readable});
-		}
-		if (FD_ISSET(pair.first, &writeset)) {
-			sockets.push_back(ListenerStatus{pair.first, Condition::Writable});
-		}
-	}
-
-	return sockets;
-}
-
-/* }}} */
-
-/*
- * Poll
- * ------------------------------------------------------------------
- */
-
-/* {{{ Poll */
-
-/*
- * Poll implementation
- * ------------------------------------------------------------------
- */
-
-#if defined(SOCKET_HAVE_POLL)
-
-#if defined(_WIN32)
-#  define poll WSAPoll
-#endif
-
-short Poll::toPoll(Condition condition) const noexcept
-{
-	short result(0);
-
-	if ((condition & Condition::Readable) == Condition::Readable) {
-		result |= POLLIN;
-	}
-	if ((condition & Condition::Writable) == Condition::Writable) {
-		result |= POLLOUT;
-	}
-
-	return result;
-}
-
-Condition Poll::toCondition(short &event) const noexcept
-{
-	Condition condition{Condition::None};
-
-	/*
-	 * Poll implementations mark the socket differently regarding
-	 * the disconnection of a socket.
-	 *
-	 * At least, even if POLLHUP or POLLIN is set, recv() always
-	 * return 0 so we mark the socket as readable.
-	 */
-	if ((event & POLLIN) || (event & POLLHUP)) {
-		condition |= Condition::Readable;
-	}
-	if (event & POLLOUT) {
-		condition |= Condition::Writable;
-	}
-
-	/* Reset event for safety */
-	event = 0;
-
-	return condition;
-}
-
-void Poll::set(const ListenerTable &, Handle h, Condition condition, bool add)
-{
-	if (add) {
-		m_fds.push_back(pollfd{h, toPoll(condition), 0});
-	} else {
-		auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const pollfd &pfd) {
-			return pfd.fd == h;
-		});
-
-		it->events |= toPoll(condition);
-	}
-}
-
-void Poll::unset(const ListenerTable &, Handle h, Condition condition, bool remove)
-{
-	auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const pollfd &pfd) {
-		return pfd.fd == h;
-	});
-
-	if (remove) {
-		m_fds.erase(it);
-	} else {
-		it->events &= ~(toPoll(condition));
-	}
-}
-
-std::vector<ListenerStatus> Poll::wait(const ListenerTable &, int ms)
-{
-	auto result = poll(m_fds.data(), m_fds.size(), ms);
-	if (result == 0) {
-		throw Error{Error::Timeout, "select", TIMEOUT_MSG};
-	}
-	if (result < 0) {
-		throw Error{Error::System, "poll"};
-	}
-
-	std::vector<ListenerStatus> sockets;
-	for (auto &fd : m_fds) {
-		if (fd.revents != 0) {
-			sockets.push_back(ListenerStatus{fd.fd, toCondition(fd.revents)});
-		}
-	}
-
-	return sockets;
-}
-
-#endif // !SOCKET_HAVE_POLL
-
-/* }}} */
-
-/*
- * Epoll implementation
- * ------------------------------------------------------------------
- */
-
-/* {{{ Epoll */
-
-#if defined(SOCKET_HAVE_EPOLL)
-
-uint32_t Epoll::toEpoll(Condition condition) const noexcept
-{
-	uint32_t events = 0;
-
-	if ((condition & Condition::Readable) == Condition::Readable) {
-		events |= EPOLLIN;
-	}
-	if ((condition & Condition::Writable) == Condition::Writable) {
-		events |= EPOLLOUT;
-	}
-
-	return events;
-}
-
-Condition Epoll::toCondition(uint32_t events) const noexcept
-{
-	Condition condition{Condition::None};
-
-	if ((events & EPOLLIN) || (events & EPOLLHUP)) {
-		condition |= Condition::Readable;
-	}
-	if (events & EPOLLOUT) {
-		condition |= Condition::Writable;
-	}
-
-	return condition;
-}
-
-void Epoll::update(Handle h, int op, int eflags)
-{
-	epoll_event ev;
-
-	std::memset(&ev, 0, sizeof (epoll_event));
-
-	ev.events = eflags;
-	ev.data.fd = h;
-
-	if (epoll_ctl(m_handle, op, h, &ev) < 0) {
-		throw Error{Error::System, "epoll_ctl"};
-	}
-}
-
-Epoll::Epoll()
-	: m_handle{epoll_create1(0)}
-{
-	if (m_handle < 0) {
-		throw Error{Error::System, "epoll_create"};
-	}
-}
-
-Epoll::~Epoll()
-{
-	close(m_handle);
-}
-
-/*
- * For set and unset, we need to apply the whole flags required, so if the socket
- * was set to Connection::Readable and user add Connection::Writable, we must
- * place both.
- */
-void Epoll::set(const ListenerTable &table, Handle sc, Condition condition, bool add)
-{
-	if (add) {
-		update(sc, EPOLL_CTL_ADD, toEpoll(condition));
-		m_events.resize(m_events.size() + 1);
-	} else {
-		update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) | condition));
-	}
-}
-
-/*
- * Unset is a bit complicated case because Listener tells us which
- * flag to remove but to update epoll descriptor we need to pass
- * the effective flags that we want to be applied.
- *
- * So we put the same flags that are currently effective and remove the
- * requested one.
- */
-void Epoll::unset(const ListenerTable &table, Handle sc, Condition condition, bool remove)
-{
-	if (remove) {
-		update(sc, EPOLL_CTL_DEL, 0);
-		m_events.resize(m_events.size() - 1);
-	} else {
-		update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) & ~(condition)));
-	}
-}
-
-std::vector<ListenerStatus> Epoll::wait(const ListenerTable &, int ms)
-{
-	int ret = epoll_wait(m_handle, m_events.data(), m_events.size(), ms);
-	std::vector<ListenerStatus> result;
-
-	if (ret == 0) {
-		throw Error{Error::Timeout, "epoll_wait", TIMEOUT_MSG};
-	}
-	if (ret < 0) {
-		throw Error{Error::System, "epoll_wait"};
-	}
-
-	for (int i = 0; i < ret; ++i) {
-		result.push_back(ListenerStatus{m_events[i].data.fd, toCondition(m_events[i].events)});
-	}
-
-	return result;
-}
-
-#endif // !SOCKET_HAVE_EPOLL
-
-/* }}} */
-
-/*
- * Kqueue implementation
- * ------------------------------------------------------------------
- */
-
-/* {{{ Kqueue */
-
-#if defined(SOCKET_HAVE_KQUEUE)
-
-Kqueue::Kqueue()
-	: m_handle(kqueue())
-{
-	if (m_handle < 0) {
-		throw Error{Error::System, "kqueue"};
-	}
-}
-
-Kqueue::~Kqueue()
-{
-	close(m_handle);
-}
-
-void Kqueue::update(Handle h, int filter, int kflags)
-{
-	struct kevent ev;
-
-	EV_SET(&ev, h, filter, kflags, 0, 0, nullptr);
-
-	if (kevent(m_handle, &ev, 1, nullptr, 0, nullptr) < 0) {
-		throw Error{Error::System, "kevent"};
-	}
-}
-
-void Kqueue::set(const ListenerTable &, Handle h, Condition condition, bool add)
-{
-	if ((condition & Condition::Readable) == Condition::Readable) {
-		update(h, EVFILT_READ, EV_ADD | EV_ENABLE);
-	}
-	if ((condition & Condition::Writable) == Condition::Writable) {
-		update(h, EVFILT_WRITE, EV_ADD | EV_ENABLE);
-	}
-
-	if (add) {
-		m_result.resize(m_result.size() + 1);
-	}
-}
-
-void Kqueue::unset(const ListenerTable &, Handle h, Condition condition, bool remove)
-{
-	if ((condition & Condition::Readable) == Condition::Readable) {
-		update(h, EVFILT_READ, EV_DELETE);
-	}
-	if ((condition & Condition::Writable) == Condition::Writable) {
-		update(h, EVFILT_WRITE, EV_DELETE);
-	}
-
-	if (remove) {
-		m_result.resize(m_result.size() - 1);
-	}
-}
-
-std::vector<ListenerStatus> Kqueue::wait(const ListenerTable &, int ms)
-{
-	std::vector<ListenerStatus> sockets;
-	timespec ts = { 0, 0 };
-	timespec *pts = (ms <= 0) ? nullptr : &ts;
-
-	ts.tv_sec = ms / 1000;
-	ts.tv_nsec = (ms % 1000) * 1000000;
-
-	int nevents = kevent(m_handle, nullptr, 0, &m_result[0], m_result.capacity(), pts);
-
-	if (nevents == 0) {
-		throw Error{Error::Timeout, "kevent", TIMEOUT_MSG};
-	}
-	if (nevents < 0) {
-		throw Error{Error::System, "kevent"};
-	}
-
-	for (int i = 0; i < nevents; ++i) {
-		sockets.push_back(ListenerStatus{
-			static_cast<Handle>(m_result[i].ident),
-			m_result[i].filter == EVFILT_READ ? Condition::Readable : Condition::Writable
-		});
-	}
-
-	return sockets;
-}
-
-#endif // !SOCKET_HAVE_KQUEUE
-
-/* }}} */
-
-} // !net
--- a/C++/modules/Socket/Sockets.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4063 +0,0 @@
-/*
- * Sockets.h -- portable C++ socket wrappers
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _SOCKETS_H_
-#define _SOCKETS_H_
-
-/**
- * @file Sockets.h
- * @brief Portable socket abstraction
- *
- * # Introduction
- *
- * This file is a portable networking library.
- *
- * ## Options
- *
- * The user may set the following variables before compiling these files:
- *
- * ### General options
- *
- * - **SOCKET_NO_AUTO_INIT**: (bool) Set to 0 if you don't want Socket class to
- * automatically calls net::init function and net::finish functions.
- * - **SOCKET_NO_SSL**: (bool) Set to 0 if you don't have access to OpenSSL library.
- * - **SOCKET_NO_AUTO_SSL_INIT**: (bool) Set to 0 if you don't want Socket class with Tls to automatically init
- * the OpenSSL library. You will need to call net::ssl::init and net::ssl::finish.
- *
- * ### Options for Listener class
- *
- * Feature detection, multiple implementations may be avaible, for example, Linux has poll, select and epoll.
- *
- * We assume that `select(2)` is always available.
- *
- * Of course, you can set the variables yourself if you test it with your build system.
- *
- * - **SOCKET_HAVE_POLL**: Defined on all BSD, Linux. Also defined on Windows
- *   if _WIN32_WINNT is set to 0x0600 or greater.
- * - **SOCKET_HAVE_KQUEUE**: Defined on all BSD and Apple.
- * - **SOCKET_HAVE_EPOLL**: Defined on Linux only.
- * - **SOCKET_DEFAULT_BACKEND**: Which backend to use (e.g. `Select`).
- *
- * The preference priority is ordered from left to right.
- *
- * | System        | Backend                 | Class name   |
- * |---------------|-------------------------|--------------|
- * | Linux         | epoll(7)                | Epoll        |
- * | *BSD          | kqueue(2)               | Kqueue       |
- * | Windows       | poll(2), select(2)      | Poll, Select |
- * | Mac OS X      | kqueue(2)               | Kqueue       |
- */
-
-#if defined(_WIN32)
-#  if _WIN32_WINNT >= 0x0600 && !defined(SOCKET_HAVE_POLL)
-#    define SOCKET_HAVE_POLL
-#  endif
-#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
-#  if !defined(SOCKET_HAVE_KQUEUE)
-#    define SOCKET_HAVE_KQUEUE
-#  endif
-#  if !defined(SOCKET_HAVE_POLL)
-#    define SOCKET_HAVE_POLL
-#  endif
-#elif defined(__linux__)
-#  if !defined(SOCKET_HAVE_EPOLL)
-#    define SOCKET_HAVE_EPOLL
-#  endif
-#  if !defined(SOCKET_HAVE_POLL)
-#    define SOCKET_HAVE_POLL
-#  endif
-#endif
-
-/*
- * Define SOCKET_DEFAULT_BACKEND
- * ------------------------------------------------------------------
- */
-
-/**
- * Defines the default Listener backend to use.
- *
- * @note Do not rely on the value shown in doxygen.
- */
-#if defined(_WIN32)
-#  if !defined(SOCKET_DEFAULT_BACKEND)
-#    if defined(SOCKET_HAVE_POLL)
-#      define SOCKET_DEFAULT_BACKEND Poll
-#    else
-#      define SOCKET_DEFAULT_BACKEND Select
-#    endif
-#  endif
-#elif defined(__linux__)
-#  include <sys/epoll.h>
-
-#  if !defined(SOCKET_DEFAULT_BACKEND)
-#    define SOCKET_DEFAULT_BACKEND Epoll
-#  endif
-#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
-#  include <sys/types.h>
-#  include <sys/event.h>
-#  include <sys/time.h>
-
-#  if !defined(SOCKET_DEFAULT_BACKEND)
-#    define SOCKET_DEFAULT_BACKEND Kqueue
-#  endif
-#else
-#  if !defined(SOCKET_DEFAULT_BACKEND)
-#    define SOCKET_DEFAULT_BACKEND Select
-#  endif
-#endif
-
-#if defined(SOCKET_HAVE_POLL) && !defined(_WIN32)
-#  include <poll.h>
-#endif
-
-/*
- * Headers to include
- * ------------------------------------------------------------------
- */
-
-#if defined(_WIN32)
-#  include <cstdlib>
-
-#  include <WinSock2.h>
-#  include <WS2tcpip.h>
-#else
-#  include <cerrno>
-
-#  include <sys/ioctl.h>
-#  include <sys/types.h>
-#  include <sys/socket.h>
-#  include <sys/un.h>
-
-#  include <arpa/inet.h>
-
-#  include <netinet/in.h>
-#  include <netinet/tcp.h>
-
-#  include <fcntl.h>
-#  include <netdb.h>
-#  include <unistd.h>
-#endif
-
-#if !defined(SOCKET_NO_SSL)
-#  include <openssl/err.h>
-#  include <openssl/evp.h>
-#  include <openssl/ssl.h>
-#endif
-
-#include <cassert>
-#include <chrono>
-#include <cstdlib>
-#include <cstring>
-#include <exception>
-#include <functional>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-/**
- * General network namespace.
- */
-namespace net {
-
-/*
- * Portables types
- * ------------------------------------------------------------------
- *
- * The following types are defined differently between Unix and Windows.
- */
-
-/* {{{ Protocols */
-
-#if defined(_WIN32)
-
-/**
- * Socket type, SOCKET.
- */
-using Handle	= SOCKET;
-
-/**
- * Argument to pass to set.
- */
-using ConstArg	= const char *;
-
-/**
- * Argument to pass to get.
- */
-using Arg	= char *;
-
-#else
-
-/**
- * Socket type, int.
- */
-using Handle	= int;
-
-/**
- * Argument to pass to set.
- */
-using ConstArg	= const void *;
-
-/**
- * Argument to pass to get.
- */
-using Arg	= void *;
-
-#endif
-
-/* }}} */
-
-/*
- * Portable constants
- * ------------------------------------------------------------------
- *
- * These constants are needed to check functions return codes, they are rarely needed in end user code.
- */
-
-/* {{{ Constants */
-
-/*
- * The following constants are defined differently from Unix
- * to Windows.
- */
-#if defined(_WIN32)
-
-/**
- * Socket creation failure or invalidation.
- */
-extern const Handle Invalid;
-
-/**
- * Socket operation failure.
- */
-extern const int Failure;
-
-#else
-
-/**
- * Socket creation failure or invalidation.
- */
-extern const int Invalid;
-
-/**
- * Socket operation failure.
- */
-extern const int Failure;
-
-#endif
-
-#if !defined(SOCKET_NO_SSL)
-
-namespace ssl {
-
-/**
- * @enum Method
- * @brief Which OpenSSL method to use.
- */
-enum Method {
-	Tlsv1,		//!< TLS v1.2 (recommended)
-	Sslv3		//!< SSLv3
-};
-
-} // !ssl
-
-#endif
-
-/* }}} */
-
-/*
- * Portable functions
- * ------------------------------------------------------------------
- *
- * The following free functions can be used to initialize the library or to get the last system error.
- */
-
-/* {{{ Functions */
-
-/**
- * Initialize the socket library. Except if you defined SOCKET_NO_AUTO_INIT, you don't need to call this
- * function manually.
- */
-void init() noexcept;
-
-/**
- * Close the socket library.
- */
-void finish() noexcept;
-
-#if !defined(SOCKET_NO_SSL)
-
-/**
- * OpenSSL namespace.
- */
-namespace ssl {
-
-/**
- * Initialize the OpenSSL library. Except if you defined SOCKET_NO_AUTO_SSL_INIT, you don't need to call this function
- * manually.
- */
-void init() noexcept;
-
-/**
- * Close the OpenSSL library.
- */
-void finish() noexcept;
-
-} // !ssl
-
-#endif // SOCKET_NO_SSL
-
-/**
- * Get the last socket system error. The error is set from errno or from
- * WSAGetLastError on Windows.
- *
- * @return a string message
- */
-std::string error();
-
-/**
- * Get the last system error.
- *
- * @param errn the error number (errno or WSAGetLastError)
- * @return the error
- */
-std::string error(int errn);
-
-/* }}} */
-
-/*
- * Error class
- * ------------------------------------------------------------------
- *
- * This is the main exception thrown on socket operations.
- */
-
-/* {{{ Error */
-
-/**
- * @class Error
- * @brief Base class for sockets error
- */
-class Error : public std::exception {
-public:
-	/**
-	 * @enum Code
-	 * @brief Which kind of error
-	 */
-	enum Code {
-		Timeout,		///!< The action did timeout
-		System,			///!< There is a system error
-		Other			///!< Other custom error
-	};
-
-private:
-	Code m_code;
-	std::string m_function;
-	std::string m_error;
-
-public:
-	/**
-	 * Constructor that use the last system error.
-	 *
-	 * @param code which kind of error
-	 * @param function the function name
-	 */
-	Error(Code code, std::string function);
-
-	/**
-	 * Constructor that use the system error set by the user.
-	 *
-	 * @param code which kind of error
-	 * @param function the function name
-	 * @param error the error
-	 */
-	Error(Code code, std::string function, int error);
-
-	/**
-	 * Constructor that set the error specified by the user.
-	 *
-	 * @param code which kind of error
-	 * @param function the function name
-	 * @param error the error
-	 */
-	Error(Code code, std::string function, std::string error);
-
-	/**
-	 * Get which function has triggered the error.
-	 *
-	 * @return the function name (e.g connect)
-	 */
-	inline const std::string &function() const noexcept
-	{
-		return m_function;
-	}
-
-	/**
-	 * The error code.
-	 *
-	 * @return the code
-	 */
-	inline Code code() const noexcept
-	{
-		return m_code;
-	}
-
-	/**
-	 * Get the error (only the error content).
-	 *
-	 * @return the error
-	 */
-	const char *what() const noexcept
-	{
-		return m_error.c_str();
-	}
-};
-
-/* }}} */
-
-/*
- * State class
- * ------------------------------------------------------------------
- *
- * To facilitate higher-level stuff, the socket has a state.
- */
-
-/* {{{ State */
-
-/**
- * @enum State
- * @brief Current socket state.
- */
-enum class State {
-	Open,			//!< Socket is open
-	Bound,			//!< Socket is bound to an address
-	Connecting,		//!< The connection is in progress
-	Connected,		//!< Connection is complete
-	Accepted,		//!< Socket has been accepted (client)
-	Accepting,		//!< The client acceptation is in progress
-	Closed,			//!< The socket has been closed
-	Disconnected,		//!< The connection was lost
-};
-
-/* }}} */
-
-/*
- * Action enum
- * ------------------------------------------------------------------
- *
- * Defines the pending operation.
- */
-
-/* {{{ Action */
-
-/**
- * @enum Action
- * @brief Define the current operation that must complete.
- *
- * Some operations like accept, connect, recv or send must sometimes do several round-trips to complete and the socket
- * action is set with that enumeration. The user is responsible of calling accept, connect send or recv until the
- * operation is complete.
- *
- * Note: the user must wait for the appropriate condition in Socket::condition to check if the required condition is
- * met.
- *
- * It is important to complete the operation in the correct order because protocols like Tls may require to continue
- * re-negociating when calling Socket::send or Socket::Recv.
- */
-enum class Action {
-	None,		//!< No action is required, socket is ready
-	Accept,		//!< The socket is not yet accepted, caller must call accept() again
-	Connect,	//!< The socket is not yet connected, caller must call connect() again
-	Receive,	//!< The received operation has not succeeded yet, caller must call recv() or recvfrom() again
-	Send		//!< The send operation has not succeded yet, caller must call send() or sendto() again
-};
-
-/* }}} */
-
-/*
- * Condition enum
- * ------------------------------------------------------------------
- *
- * Defines if we must wait for reading or writing.
- */
-
-/* {{{ Condition */
-
-/**
- * @enum Condition
- * @brief Define the required condition for the socket.
- *
- * As explained in Action enumeration, some operations required to be called several times, before calling these
- * operations, the user must wait the socket to be readable or writable. This can be checked with Socket::condition.
- */
-enum class Condition {
-	None,			//!< No condition is required
-	Readable = (1 << 0),	//!< The socket must be readable
-	Writable = (1 << 1)	//!< The socket must be writable
-};
-
-/**
- * Apply bitwise XOR.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-constexpr Condition operator^(Condition v1, Condition v2) noexcept
-{
-	return static_cast<Condition>(static_cast<int>(v1) ^ static_cast<int>(v2));
-}
-
-/**
- * Apply bitwise AND.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-constexpr Condition operator&(Condition v1, Condition v2) noexcept
-{
-	return static_cast<Condition>(static_cast<int>(v1) & static_cast<int>(v2));
-}
-
-/**
- * Apply bitwise OR.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-constexpr Condition operator|(Condition v1, Condition v2) noexcept
-{
-	return static_cast<Condition>(static_cast<int>(v1) | static_cast<int>(v2));
-}
-
-/**
- * Apply bitwise NOT.
- *
- * @param v the value
- * @return the complement
- */
-constexpr Condition operator~(Condition v) noexcept
-{
-	return static_cast<Condition>(~static_cast<int>(v));
-}
-
-/**
- * Assign bitwise OR.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-inline Condition &operator|=(Condition &v1, Condition v2) noexcept
-{
-	v1 = static_cast<Condition>(static_cast<int>(v1) | static_cast<int>(v2));
-
-	return v1;
-}
-
-/**
- * Assign bitwise AND.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-inline Condition &operator&=(Condition &v1, Condition v2) noexcept
-{
-	v1 = static_cast<Condition>(static_cast<int>(v1) & static_cast<int>(v2));
-
-	return v1;
-}
-
-/**
- * Assign bitwise XOR.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-inline Condition &operator^=(Condition &v1, Condition v2) noexcept
-{
-	v1 = static_cast<Condition>(static_cast<int>(v1) ^ static_cast<int>(v2));
-
-	return v1;
-}
-
-/* }}} */
-
-/*
- * Base Socket class
- * ------------------------------------------------------------------
- *
- * This base class has operations that are common to all types of sockets but you usually instanciate
- * a SocketTcp or SocketUdp
- */
-
-/* {{{ Socket */
-
-/**
- * @class Socket
- * @brief Base socket class for socket operations.
- *
- * **Important:** When using non-blocking sockets, some considerations must be taken. See the implementation of the
- * underlying protocol for more details.
- *
- * @see protocol::Tls
- * @see protocol::Tcp
- * @see protocol::Udp
- */
-template <typename Address, typename Protocol>
-class Socket {
-private:
-	Protocol m_proto;
-	State m_state{State::Closed};
-	Action m_action{Action::None};
-	Condition m_condition{Condition::None};
-
-protected:
-	/**
-	 * The native handle.
-	 */
-	Handle m_handle{Invalid};
-
-public:
-	/**
-	 * Create a socket handle.
-	 *
-	 * This is the primary function and the only one that creates the socket handle, all other constructors
-	 * are just overloaded functions.
-	 *
-	 * @param domain the domain AF_*
-	 * @param type the type SOCK_*
-	 * @param protocol the protocol
-	 * @param iface the implementation
-	 * @throw net::Error on errors
-	 * @post state is set to Open
-	 * @post handle is not set to Invalid
-	 */
-	Socket(int domain, int type, int protocol, Protocol iface = {})
-		: m_proto(std::move(iface))
-	{
-#if !defined(SOCKET_NO_AUTO_INIT)
-		init();
-#endif
-		m_handle = ::socket(domain, type, protocol);
-
-		if (m_handle == Invalid) {
-			throw Error{Error::System, "socket"};
-		}
-
-		m_proto.create(*this);
-		m_state = State::Open;
-
-		assert(m_handle != Invalid);
-	}
-
-	/**
-	 * This tries to create a socket.
-	 *
-	 * Domain and type are determined by the Address and Protocol object.
-	 *
-	 * @param protocol the protocol
-	 * @param address which type of address
-	 * @throw net::Error on errors
-	 */
-	explicit inline Socket(Protocol protocol = {}, const Address &address = {})
-		: Socket{address.domain(), protocol.type(), 0, std::move(protocol)}
-	{
-	}
-
-	/**
-	 * Construct a socket with an already created descriptor.
-	 *
-	 * @param handle the native descriptor
-	 * @param state specify the socket state
-	 * @param protocol the type of socket implementation
-	 * @post action is set to None
-	 * @post condition is set to None
-	 */
-	explicit inline Socket(Handle handle, State state = State::Closed, Protocol protocol = {}) noexcept
-		: m_proto(std::move(protocol))
-		, m_state{state}
-		, m_handle{handle}
-	{
-		assert(m_action == Action::None);
-		assert(m_condition == Condition::None);
-	}
-
-	/**
-	 * Create an invalid socket. Can be used when you cannot instanciate the socket immediately.
-	 */
-	explicit inline Socket(std::nullptr_t) noexcept
-		: m_handle{Invalid}
-	{
-	}
-
-	/**
-	 * Copy constructor deleted.
-	 */
-	Socket(const Socket &) = delete;
-
-	/**
-	 * Transfer ownership from other to this.
-	 *
-	 * @param other the other socket
-	 */
-	inline Socket(Socket &&other) noexcept
-		: m_proto(std::move(other.m_proto))
-		, m_state{other.m_state}
-		, m_action{other.m_action}
-		, m_condition{other.m_condition}
-		, m_handle{other.m_handle}
-	{
-		/* Invalidate other */
-		other.m_handle = Invalid;
-		other.m_state = State::Closed;
-		other.m_action = Action::None;
-		other.m_condition = Condition::None;
-	}
-
-	/**
-	 * Default destructor.
-	 */
-	virtual ~Socket()
-	{
-		close();
-	}
-
-	/**
-	 * Access the implementation.
-	 *
-	 * @return the implementation
-	 * @warning use this function with care
-	 */
-	inline const Protocol &protocol() const noexcept
-	{
-		return m_proto;
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the implementation
-	 */
-	inline Protocol &protocol() noexcept
-	{
-		return m_proto;
-	}
-
-	/**
-	 * Get the current socket state.
-	 *
-	 * @return the state
-	 */
-	inline State state() const noexcept
-	{
-		return m_state;
-	}
-
-	/**
-	 * Change the current socket state.
-	 *
-	 * @param state the new state
-	 * @warning only implementations should call this function
-	 */
-	inline void setState(State state) noexcept
-	{
-		m_state = state;
-	}
-
-	/**
-	 * Get the pending operation.
-	 *
-	 * @return the action to complete before continuing
-	 * @note usually only needed in non-blocking sockets
-	 */
-	inline Action action() const noexcept
-	{
-		return m_action;
-	}
-
-	/**
-	 * Change the pending operation.
-	 *
-	 * @param action the action
-	 * @warning you should not call this function yourself
-	 */
-	inline void setAction(Action action) noexcept
-	{
-		m_action = action;
-	}
-
-	/**
-	 * Get the condition to wait for.
-	 *
-	 * @return the condition
-	 */
-	inline Condition condition() const noexcept
-	{
-		return m_condition;
-	}
-
-	/**
-	 * Change the condition required.
-	 *
-	 * @param condition the condition
-	 * @warning you should not call this function yourself
-	 */
-	inline void setCondition(Condition condition) noexcept
-	{
-		m_condition = condition;
-	}
-
-	/**
-	 * Set an option for the socket. Wrapper of setsockopt(2).
-	 *
-	 * @param level the setting level
-	 * @param name the name
-	 * @param arg the value
-	 * @throw net::Error on errors
-	 */
-	template <typename Argument>
-	void set(int level, int name, const Argument &arg)
-	{
-		if (setsockopt(m_handle, level, name, (ConstArg)&arg, sizeof (arg)) == Failure) {
-			throw Error{Error::System, "set"};
-		}
-	}
-
-	/**
-	 * Object-oriented option setter.
-	 *
-	 * The object must have `set(Socket<Address, Protocol> &) const`.
-	 *
-	 * @param option the option
-	 * @throw net::Error on errors
-	 */
-	template <typename Option>
-	inline void set(const Option &option)
-	{
-		option.set(*this);
-	}
-
-	/**
-	 * Get an option for the socket. Wrapper of getsockopt(2).
-	 *
-	 * @param level the setting level
-	 * @param name the name
-	 * @throw net::Error on errors
-	 */
-	template <typename Argument>
-	Argument get(int level, int name)
-	{
-		Argument desired, result{};
-		socklen_t size = sizeof (result);
-
-		if (getsockopt(m_handle, level, name, (Arg)&desired, &size) == Failure) {
-			throw Error{Error::System, "get"};
-		}
-
-		std::memcpy(&result, &desired, size);
-
-		return result;
-	}
-
-	/**
-	 * Object-oriented option getter.
-	 *
-	 * The object must have `T get(Socket<Address, Protocol> &) const`, T can be any type and it is the value
-	 * returned from this function.
-	 *
-	 * @return the same value as get() in the option
-	 * @throw net::Error on errors
-	 */
-	template <typename Option>
-	inline auto get() -> decltype(std::declval<Option>().get(*this))
-	{
-		return Option{}.get(*this);
-	}
-
-	/**
-	 * Get the native handle.
-	 *
-	 * @return the handle
-	 * @warning Not portable
-	 */
-	inline Handle handle() const noexcept
-	{
-		return m_handle;
-	}
-
-	/**
-	 * Bind using a native address.
-	 *
-	 * @param address the address
-	 * @param length the size
-	 * @pre state must not be Bound
-	 * @throw net::Error on errors
-	 */
-	void bind(const sockaddr *address, socklen_t length)
-	{
-		assert(m_state != State::Bound);
-
-		if (::bind(m_handle, address, length) == Failure) {
-			throw Error{Error::System, "bind"};
-		}
-
-		m_state = State::Bound;
-	}
-
-	/**
-	 * Overload that takes an address.
-	 *
-	 * @param address the address
-	 * @throw net::Error on errors
-	 */
-	inline void bind(const Address &address)
-	{
-		bind(address.address(), address.length());
-	}
-
-	/**
-	 * Listen for pending connection.
-	 *
-	 * @param max the maximum number
-	 * @pre state must be Bound
-	 * @throw net::Error on errors
-	 */
-	inline void listen(int max = 128)
-	{
-		assert(m_state == State::Bound);
-
-		if (::listen(this->m_handle, max) == Failure) {
-			throw Error{Error::System, "listen"};
-		}
-	}
-
-	/**
-	 * Connect to the address.
-	 *
-	 * If connection cannot be established immediately, connect with no argument must be called again. See
-	 * the underlying protocol for more information.
-	 *
-	 * @pre state must be State::Open
-	 * @param address the address
-	 * @param length the the address length
-	 * @throw net::Error on errors
-	 * @post state is set to State::Connecting or State::Connected
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	void connect(const sockaddr *address, socklen_t length)
-	{
-		assert(m_state == State::Open);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		m_proto.connect(*this, address, length);
-
-		assert((m_state == State::Connected  && m_action == Action::None    && m_condition == Condition::None) ||
-		       (m_state == State::Connecting && m_action == Action::Connect && m_condition != Condition::None));
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * Effectively call connect(address.address(), address.length());
-	 *
-	 * @param address the address
-	 */
-	inline void connect(const Address &address)
-	{
-		connect(address.address(), address.length());
-	}
-
-	/**
-	 * Continue the connection, only required with non-blocking sockets.
-	 *
-	 * @pre state must be State::Connecting
-	 * @throw net::Error on errors
-	 */
-	void connect()
-	{
-		assert(m_state == State::Connecting);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		m_proto.connect(*this);
-
-		assert((m_state == State::Connected  && m_action == Action::None    && m_condition == Condition::None) ||
-		       (m_state == State::Connecting && m_action == Action::Connect && m_condition != Condition::None));
-	}
-
-	/**
-	 * Accept a new client. If there are no pending connection, throws an error.
-	 *
-	 * If the client cannot be accepted immediately, the client is returned and accept with no arguments
-	 * must be called on it. See the underlying protocol for more information.
-	 *
-	 * @pre state must be State::Bound
-	 * @param info the address where to store client's information (optional)
-	 * @return the new socket
-	 * @throw Error on errors
-	 * @post returned client's state is set to State::Accepting or State::Accepted
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	Socket<Address, Protocol> accept(Address *info)
-	{
-		assert(m_state == State::Bound);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		sockaddr_storage storage;
-		socklen_t length = sizeof (storage);
-
-		Socket<Address, Protocol> sc = m_proto.accept(*this, reinterpret_cast<sockaddr *>(&storage), &length);
-
-		if (info) {
-			*info = Address{&storage, length};
-		}
-
-		/* Master do not change */
-		assert(m_state == State::Bound);
-		assert(m_action == Action::None);
-		assert(m_condition == Condition::None);
-
-		/* Client */
-		assert(
-			(sc.state() == State::Accepting && sc.action() == Action::Accept && sc.condition() != Condition::None) ||
-			(sc.state() == State::Accepted  && sc.action() == Action::None   && sc.condition() == Condition::None)
-		);
-
-		return sc;
-	}
-
-	/**
-	 * Continue the accept process on this client. This function must be called only when the socket is
-	 * ready to be readable or writable! (see condition).
-	 *
-	 * @pre state must be State::Accepting
-	 * @throw Error on errors
-	 * @post if connection is complete, state is changed to State::Accepted, action and condition are unset
-	 * @post if connection is still in progress, condition is set
-	 */
-	void accept()
-	{
-		assert(m_state == State::Accepting);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		m_proto.accept(*this);
-
-		assert(
-			(m_state == State::Accepting && m_action == Action::Accept && m_condition != Condition::None) ||
-			(m_state == State::Accepted  && m_action == Action::None   && m_condition == Condition::None)
-		);
-	}
-
-	/**
-	 * Get the local name. This is a wrapper of getsockname().
-	 *
-	 * @return the address
-	 * @throw Error on failures
-	 * @pre state() must not be State::Closed
-	 */
-	Address address() const
-	{
-		assert(m_state != State::Closed);
-
-		sockaddr_storage ss;
-		socklen_t length = sizeof (sockaddr_storage);
-
-		if (::getsockname(m_handle, (sockaddr *)&ss, &length) == Failure) {
-			throw Error{Error::System, "getsockname"};
-		}
-
-		return Address(&ss, length);
-	}
-
-	/**
-	 * Receive some data.
-	 *
-	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
-	 * again when ready. See the underlying protocol for more information.
-	 *
-	 * If action is set to Action::None and result is set to 0, disconnection occured.
-	 *
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @pre action must not be Action::Send
-	 * @return the number of bytes received or 0
-	 * @throw Error on error
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	unsigned recv(void *data, unsigned length)
-	{
-		assert(m_action != Action::Send);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		return m_proto.recv(*this, data, length);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param count the number of bytes to receive
-	 * @return the string
-	 * @throw Error on error
-	 */
-	inline std::string recv(unsigned count)
-	{
-		std::string result;
-
-		result.resize(count);
-		auto n = recv(const_cast<char *>(result.data()), count);
-		result.resize(n);
-
-		return result;
-	}
-
-	/**
-	 * Send some data.
-	 *
-	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
-	 * again when ready. See the underlying protocol for more information.
-	 *
-	 * @param data the data buffer
-	 * @param length the buffer length
-	 * @return the number of bytes sent or 0
-	 * @pre action() must not be Flag::Receive
-	 * @throw Error on error
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	unsigned send(const void *data, unsigned length)
-	{
-		assert(m_action != Action::Receive);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		return m_proto.send(*this, data, length);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the string to send
-	 * @return the number of bytes sent
-	 * @throw Error on error
-	 */
-	inline unsigned send(const std::string &data)
-	{
-		return send(data.c_str(), data.size());
-	}
-
-	/**
-	 * Send data to an end point.
-	 *
-	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
-	 * again when ready. See the underlying protocol for more information.
-	 *
-	 * @param data the buffer
-	 * @param length the buffer length
-	 * @param address the client address
-	 * @param addrlen the address length
-	 * @return the number of bytes sent
-	 * @throw net::Error on errors
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	inline unsigned sendto(const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
-	{
-		return m_proto.sendto(*this, data, length, address, addrlen);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the buffer
-	 * @param length the buffer length
-	 * @param address the destination
-	 * @return the number of bytes sent
-	 * @throw net::Error on errors
-	 */
-	inline unsigned sendto(const void *data, unsigned length, const Address &address)
-	{
-		return sendto(data, length, address.address(), address.length());
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the data
-	 * @param address the address
-	 * @return the number of bytes sent
-	 * @throw net:;Error on errors
-	 */
-	inline unsigned sendto(const std::string &data, const Address &address)
-	{
-		return sendto(data.c_str(), data.length(), address);
-	}
-
-	/**
-	 * Receive data from an end point.
-	 *
-	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
-	 * again when ready. See the underlying protocol for more information.
-	 *
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @param address the address destination
-	 * @param addrlen the address length (in/out)
-	 * @return the number of bytes received
-	 * @throw net::Error on errors
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	inline unsigned recvfrom(void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
-	{
-		return m_proto.recvfrom(*this, data, length, address, addrlen);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @param info the address destination
-	 * @return the number of bytes received
-	 * @throw net::Error on errors
-	 */
-	inline unsigned recvfrom(void *data, unsigned length, Address *info = nullptr)
-	{
-		sockaddr_storage storage;
-		socklen_t addrlen = sizeof (sockaddr_storage);
-
-		auto n = recvfrom(data, length, reinterpret_cast<sockaddr *>(&storage), &addrlen);
-
-		if (info && n != 0) {
-			*info = Address{&storage, addrlen};
-		}
-
-		return n;
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param count the maximum number of bytes to receive
-	 * @param info the client information
-	 * @return the string
-	 * @throw net::Error on errors
-	 */
-	std::string recvfrom(unsigned count, Address *info = nullptr)
-	{
-		std::string result;
-
-		result.resize(count);
-		auto n = recvfrom(const_cast<char *>(result.data()), count, info);
-		result.resize(n);
-
-		return result;
-	}
-
-	/**
-	 * Close the socket.
-	 *
-	 * Automatically called from the destructor.
-	 */
-	void close()
-	{
-		if (m_handle != Invalid) {
-#if defined(_WIN32)
-			::closesocket(m_handle);
-#else
-			::close(m_handle);
-#endif
-			m_handle = Invalid;
-		}
-
-		m_state = State::Closed;
-		m_action = Action::None;
-		m_condition = Condition::None;
-	}
-
-	/**
-	 * Assignment operator forbidden.
-	 *
-	 * @return *this
-	 */
-	Socket &operator=(const Socket &) = delete;
-
-	/**
-	 * Transfer ownership from other to this. The other socket is left
-	 * invalid and will not be closed.
-	 *
-	 * @param other the other socket
-	 * @return this
-	 */
-	Socket &operator=(Socket &&other) noexcept
-	{
-		m_handle = other.m_handle;
-		m_proto = std::move(other.m_proto);
-		m_state = other.m_state;
-		m_action = other.m_action;
-		m_condition = other.m_condition;
-
-		/* Invalidate other */
-		other.m_handle = Invalid;
-		other.m_state = State::Closed;
-		other.m_action = Action::None;
-		other.m_condition = Condition::None;
-
-		return *this;
-	}
-};
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if they equals
- */
-template <typename Address, typename Protocol>
-bool operator==(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() == s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if they are different
- */
-template <typename Address, typename Protocol>
-bool operator!=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() != s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if s1 < s2
- */
-template <typename Address, typename Protocol>
-bool operator<(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() < s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if s1 > s2
- */
-template <typename Address, typename Protocol>
-bool operator>(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() > s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if s1 <= s2
- */
-template <typename Address, typename Protocol>
-bool operator<=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() <= s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if s1 >= s2
- */
-template <typename Address, typename Protocol>
-bool operator>=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() >= s2.handle();
-}
-
-/* }}} */
-
-/*
- * Predefined options
- * ------------------------------------------------------------------
- */
-
-/* {{{ Options */
-
-/**
- * Namespace of predefined options.
- */
-namespace option {
-
-/*
- * Options for socket
- * ------------------------------------------------------------------
- */
-
-/* {{{ Options for socket */
-
-/**
- * @class SockBlockMode
- * @brief Set or get the blocking-mode for a socket.
- * @warning On Windows, it's not possible to check if the socket is blocking or not.
- */
-class SockBlockMode {
-public:
-	/**
-	 * Set to false if you want non-blocking socket.
-	 */
-	bool value{false};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	void set(Socket<Address, Protocol> &sc) const
-	{
-#if defined(O_NONBLOCK) && !defined(_WIN32)
-		int flags;
-
-		if ((flags = fcntl(sc.handle(), F_GETFL, 0)) < 0) {
-			flags = 0;
-		}
-
-		if (value) {
-			flags &= ~(O_NONBLOCK);
-		} else {
-			flags |= O_NONBLOCK;
-		}
-
-		if (fcntl(sc.handle(), F_SETFL, flags) < 0) {
-			throw Error{Error::System, "fcntl"};
-		}
-#else
-		unsigned long flags = (value) ? 0 : 1;
-
-		if (ioctlsocket(sc.handle(), FIONBIO, &flags) == Failure) {
-			throw Error{Error::System, "fcntl"};
-		}
-#endif
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	bool get(Socket<Address, Protocol> &sc) const
-	{
-#if defined(O_NONBLOCK) && !defined(_WIN32)
-		int flags = fcntl(sc.handle(), F_GETFL, 0);
-
-		if (flags < 0) {
-			throw Error{Error::System, "fcntl"};
-		}
-
-		return !(flags & O_NONBLOCK);
-#else
-		throw Error{Error::Other, "get", "Windows API cannot let you get the blocking status of a socket"};
-#endif
-	}
-};
-
-/**
- * @class SockReuseAddress
- * @brief Reuse address, must be used before calling Socket::bind
- */
-class SockReuseAddress {
-public:
-	/**
-	 * Set to true if you want to set the SOL_SOCKET/SO_REUSEADDR option.
-	 */
-	bool value{true};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(SOL_SOCKET, SO_REUSEADDR, value ? 1 : 0);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline bool get(Socket<Address, Protocol> &sc) const
-	{
-		return static_cast<bool>(sc.template get<int>(SOL_SOCKET, SO_REUSEADDR));
-	}
-};
-
-/**
- * @class SockSendBuffer
- * @brief Set or get the output buffer.
- */
-class SockSendBuffer {
-public:
-	/**
-	 * Set to the buffer size.
-	 */
-	int value{2048};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(SOL_SOCKET, SO_SNDBUF, value);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline int get(Socket<Address, Protocol> &sc) const
-	{
-		return sc.template get<int>(SOL_SOCKET, SO_SNDBUF);
-	}
-};
-
-/**
- * @class SockReceiveBuffer
- * @brief Set or get the input buffer.
- */
-class SockReceiveBuffer {
-public:
-	/**
-	 * Set to the buffer size.
-	 */
-	int value{2048};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(SOL_SOCKET, SO_RCVBUF, value);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline int get(Socket<Address, Protocol> &sc) const
-	{
-		return sc.template get<int>(SOL_SOCKET, SO_RCVBUF);
-	}
-};
-
-/* }}} */
-
-/**
- * @class TcpNoDelay
- * @brief Set this option if you want to disable nagle's algorithm.
- */
-class TcpNoDelay {
-public:
-	/**
-	 * Set to true to set TCP_NODELAY option.
-	 */
-	bool value{true};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(IPPROTO_TCP, TCP_NODELAY, value ? 1 : 0);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline bool get(Socket<Address, Protocol> &sc) const
-	{
-		return static_cast<bool>(sc.template get<int>(IPPROTO_TCP, TCP_NODELAY));
-	}
-};
-
-/**
- * @class Ipv6Only
- * @brief Control IPPROTO_IPV6/IPV6_V6ONLY
- *
- * Note: some systems may or not set this option by default so it's a good idea to set it in any case to either
- * false or true if portability is a concern.
- */
-class Ipv6Only {
-public:
-	/**
-	 * Set this to use only IPv6.
-	 */
-	bool value{true};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(IPPROTO_IPV6, IPV6_V6ONLY, value ? 1 : 0);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline bool get(Socket<Address, Protocol> &sc) const
-	{
-		return static_cast<bool>(sc.template get<int>(IPPROTO_IPV6, IPV6_V6ONLY));
-	}
-};
-
-} // !option
-
-/* }}} */
-
-/*
- * Predefined addressed to be used
- * ------------------------------------------------------------------
- *
- * - Ip,
- * - Local.
- */
-
-/* {{{ Addresses */
-
-/**
- * Set of predefined addresses.
- */
-namespace address {
-
-/**
- * @class Ip
- * @brief Base class for IPv6 and IPv4, you can use it if you don't know in advance if you'll use IPv6 or IPv4.
- */
-class Ip {
-public:
-	/**
-	 * @enum Type
-	 * @brief Type of ip address.
-	 */
-	enum Type {
-		v4 = AF_INET,		//!< AF_INET
-		v6 = AF_INET6		//!< AF_INET6
-	};
-
-private:
-	/*
-	 * Default domain when using default constructors.
-	 *
-	 * Note: AF_INET or AF_INET6, not
-	 */
-	static int m_default;
-
-	union {
-		sockaddr_in m_sin;
-		sockaddr_in6 m_sin6;
-	};
-
-	socklen_t m_length{0};
-	int m_domain{AF_INET};
-
-public:
-	/**
-	 * Set the default domain to use when using default Ip constructor. By default, AF_INET is used.
-	 *
-	 * @pre domain must be Type::v4 or Type::v6
-	 */
-	static inline void setDefault(Type domain) noexcept
-	{
-		assert(domain == Type::v4 || domain == Type::v6);
-
-		m_default = static_cast<int>(domain);
-	}
-
-	/**
-	 * Construct using the default domain.
-	 */
-	inline Ip() noexcept
-		: Ip(static_cast<Type>(m_default))
-	{
-	}
-
-	/**
-	 * Default initialize the Ip domain.
-	 *
-	 * @pre domain must be AF_INET or AF_INET6 only
-	 * @param domain the domain (AF_INET or AF_INET6)
-	 */
-	Ip(Type domain) noexcept;
-
-	/**
-	 * Construct an address suitable for bind() or connect().
-	 *
-	 * @pre domain must be Type::v4 or Type::v6
-	 * @param domain the domain (AF_INET or AF_INET6)
-	 * @param host the host (* for any)
-	 * @param port the port number
-	 * @throw Error on errors
-	 */
-	Ip(const std::string &host, int port, Type domain = v4);
-
-	/**
-	 * Construct an address from a storage.
-	 *
-	 * @pre storage's domain must be AF_INET or AF_INET6 only
-	 * @param ss the storage
-	 * @param length the length
-	 */
-	Ip(const sockaddr_storage *ss, socklen_t length) noexcept;
-
-	/**
-	 * Get the domain (AF_INET or AF_INET6).
-	 *
-	 * @return the domain
-	 */
-	inline int domain() const noexcept
-	{
-		return m_domain;
-	}
-
-	/**
-	 * Return the underlying address, either sockaddr_in6 or sockaddr_in.
-	 *
-	 * @return the address
-	 */
-	inline const sockaddr *address() const noexcept
-	{
-		if (m_domain == AF_INET6) {
-			return reinterpret_cast<const sockaddr *>(&m_sin6);
-		}
-
-		return reinterpret_cast<const sockaddr *>(&m_sin);
-	}
-
-	/**
-	 * Return the underlying address length.
-	 *
-	 * @return the length
-	 */
-	inline socklen_t length() const noexcept
-	{
-		return m_length;
-	}
-
-	/**
-	 * Get the port.
-	 *
-	 * @return the port
-	 */
-	inline int port() const noexcept
-	{
-		if (m_domain == AF_INET6) {
-			return ntohs(m_sin6.sin6_port);
-		}
-
-		return ntohs(m_sin.sin_port);
-	}
-};
-
-#if !defined(_WIN32)
-
-/**
- * @class Local
- * @brief unix family sockets
- *
- * Create an address to a specific path. Only available on Unix.
- */
-class Local {
-private:
-	sockaddr_un m_sun;
-	std::string m_path;
-
-public:
-	/**
-	 * Get the domain AF_LOCAL.
-	 *
-	 * @return AF_LOCAL
-	 */
-	inline int domain() const noexcept
-	{
-		return AF_LOCAL;
-	}
-
-	/**
-	 * Default constructor.
-	 */
-	Local() noexcept;
-
-	/**
-	 * Construct an address to a path.
-	 *
-	 * @param path the path
-	 * @param rm remove the file before (default: false)
-	 */
-	Local(std::string path, bool rm = false) noexcept;
-
-	/**
-	 * Construct an unix address from a storage address.
-	 *
-	 * @pre storage's domain must be AF_LOCAL
-	 * @param ss the storage
-	 * @param length the length
-	 */
-	Local(const sockaddr_storage *ss, socklen_t length) noexcept;
-
-	/**
-	 * Get the sockaddr_un.
-	 *
-	 * @return the address
-	 */
-	inline const sockaddr *address() const noexcept
-	{
-		return reinterpret_cast<const sockaddr *>(&m_sun);
-	}
-
-	/**
-	 * Get the address length.
-	 *
-	 * @return the length
-	 */
-	inline socklen_t length() const noexcept
-	{
-#if defined(SOCKET_HAVE_SUN_LEN)
-		return SUN_LEN(&m_sun);
-#else
-		return sizeof (m_sun);
-#endif
-	}
-};
-
-#endif // !_WIN32
-
-} // !address
-
-/* }}} */
-
-/*
- * Predefined protocols
- * ------------------------------------------------------------------
- *
- * - Tcp, for standard stream connections,
- * - Udp, for standard datagram connections,
- * - Tls, for secure stream connections.
- */
-
-/* {{{ Protocols */
-
-/**
- * Set of predefined protocols.
- */
-namespace protocol {
-
-/* {{{ Tcp */
-
-/**
- * @class Tcp
- * @brief Clear TCP implementation.
- *
- * This is the basic TCP protocol that implements recv, send, connect and accept as wrappers of the usual
- * C functions.
- */
-class Tcp {
-public:
-	/**
-	 * Socket type.
-	 *
-	 * @return SOCK_STREAM
-	 */
-	inline int type() const noexcept
-	{
-		return SOCK_STREAM;
-	}
-
-	/**
-	 * Do nothing.
-	 *
-	 * This function is just present for compatibility, it should never be called.
-	 */
-	template <typename Address>
-	inline void create(Socket<Address, Tcp> &) const noexcept
-	{
-		/* No-op */
-	}
-
-	/**
-	 * Standard connect.
-	 *
-	 * If the socket is marked non-blocking and the connection cannot be established immediately, then the
-	 * following is true:
-	 *
-	 * - state is set to State::Connecting,
-	 * - action is set to Action::Connect,
-	 * - condition is set to Condition::Writable.
-	 *
-	 * Then the user must wait until the socket is writable and call connect() with 0 arguments.
-	 *
-	 * If the socket is blocking, this function blocks until the connection is complete or an error occurs, in
-	 * that case state is either set to State::Connected or State::Disconnected but action and condition are
-	 * not set.
-	 *
-	 * @param sc the socket
-	 * @param address the address
-	 * @param length the length
-	 * @throw net::Error on errors
-	 * @note Wrapper of connect(2)
-	 */
-	template <typename Address, typename Protocol>
-	void connect(Socket<Address, Protocol> &sc, const sockaddr *address, socklen_t length)
-	{
-		if (::connect(sc.handle(), address, length) == Failure) {
-			/*
-			 * Determine if the error comes from a non-blocking connect that cannot be
-			 * accomplished yet.
-			 */
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				sc.setState(State::Connecting);
-				sc.setAction(Action::Connect);
-				sc.setCondition(Condition::Writable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "connect", error};
-			}
-#else
-			if (errno == EINPROGRESS) {
-				sc.setState(State::Connecting);
-				sc.setAction(Action::Connect);
-				sc.setCondition(Condition::Writable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "connect"};
-			}
-#endif
-		} else {
-			sc.setState(State::Connected);
-		}
-	}
-
-	/**
-	 * Continue the connection. This function must only be called when the socket is ready for writing,
-	 * the user is responsible of waiting for that condition.
-	 *
-	 * This function check for SOL_SOCKET/SO_ERROR status.
-	 *
-	 * If the connection is complete, status is set to State::Connected, otherwise it is set to
-	 * State::Disconnected. In both cases, action and condition are not set.
-	 *
-	 * @param sc the socket
-	 * @throw net::Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	void connect(Socket<Address, Protocol> &sc)
-	{
-		int error = sc.template get<int>(SOL_SOCKET, SO_ERROR);
-
-		if (error == Failure) {
-			sc.setState(State::Disconnected);
-			throw Error{Error::System, "connect", error};
-		}
-
-		sc.setState(State::Connected);
-	}
-
-	/**
-	 * Accept a clear client.
-	 *
-	 * If the socket is marked non-blocking and there are no pending connection, this function throws an
-	 * error. The user must wait that the socket is readable before calling this function.
-	 *
-	 * If the socket is blocking, this function blocks until a new client is connected or throws an error on
-	 * errors.
-	 *
-	 * If the socket is correctly returned, its state is set to State::Accepted and its action and condition
-	 * are not set.
-	 *
-	 * In any case, action and condition of this socket are not set.
-	 *
-	 * @param sc the socket
-	 * @param address the address destination
-	 * @param length the address length
-	 * @return the socket
-	 * @throw net::Error on errors
-	 * @note Wrapper of accept(2)
-	 */
-	template <typename Address, typename Protocol>
-	Socket<Address, Protocol> accept(Socket<Address, Protocol> &sc, sockaddr *address, socklen_t *length)
-	{
-		Handle handle = ::accept(sc.handle(), address, length);
-
-		if (handle == Invalid) {
-			throw Error{Error::System, "accept"};
-		}
-
-		return Socket<Address, Protocol>{handle, State::Accepted};
-	}
-
-	/**
-	 * Continue accept.
-	 *
-	 * This function is just present for compatibility, it should never be called.
-	 */
-	template <typename Address, typename Protocol>
-	inline void accept(Socket<Address, Protocol> &) const noexcept
-	{
-		/* no-op */
-	}
-
-	/**
-	 * Receive data.
-	 *
-	 * If the socket is marked non-blocking and no data is available, 0 is returned and condition is set to
-	 * Condition::Readable. If 0 is returned and condition is not set, then the state is set to
-	 * State::Disconnected.
-	 *
-	 * If the socket is blocking, this function blocks until some data is available or if an error occurs.
-	 *
-	 * In any case, action is never set.
-	 *
-	 * @param sc the socket
-	 * @param data the destination
-	 * @param length the destination length
-	 * @return the number of bytes read
-	 * @throw Error on errors
-	 * @note Wrapper of recv(2)
-	 */
-	template <typename Address>
-	unsigned recv(Socket<Address, Tcp> &sc, void *data, unsigned length)
-	{
-		int nbread = ::recv(sc.handle(), (Arg)data, length, 0);
-
-		if (nbread == Failure) {
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				nbread = 0;
-				sc.setCondition(Condition::Readable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "recv", error};
-			}
-#else
-			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				sc.setCondition(Condition::Readable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "recv"};
-			}
-#endif
-		} else if (nbread == 0) {
-			sc.setState(State::Disconnected);
-		}
-
-		return static_cast<unsigned>(nbread);
-	}
-
-	/**
-	 * Send some data.
-	 *
-	 * If the socket is marked non-blocking and the operation would block, then 0 is returned and condition is set to
-	 * Condition::Writable.
-	 *
-	 * If the socket is blocking, this function blocks until the data has been sent.
-	 *
-	 * On any other errors, this function throw net::Error.
-	 *
-	 * @param sc the socket
-	 * @param data the buffer to send
-	 * @param length the buffer length
-	 * @return the number of bytes sent
-	 * @throw net::Error on errors
-	 * @note Wrapper of send(2)
-	 */
-	template <typename Address>
-	unsigned send(Socket<Address, Tcp> &sc, const void *data, unsigned length)
-	{
-		int nbsent = ::send(sc.handle(), (ConstArg)data, length, 0);
-
-		if (nbsent == Failure) {
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				nbsent = 0;
-				sc.setCondition(Condition::Writable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "send", error};
-			}
-#else
-			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				nbsent = 0;
-				sc.setCondition(Condition::Writable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "send"};
-			}
-#endif
-		}
-
-		return static_cast<unsigned>(nbsent);
-	}
-};
-
-/* }}} */
-
-/* {{{ Udp */
-
-/**
- * @class Udp
- * @brief Clear UDP type.
- *
- * This class is the basic implementation of UDP sockets.
- */
-class Udp {
-public:
-	/**
-	 * Socket type.
-	 *
-	 * @return SOCK_DGRAM
-	 */
-	inline int type() const noexcept
-	{
-		return SOCK_DGRAM;
-	}
-
-	/**
-	 * Do nothing.
-	 */
-	template <typename Address>
-	inline void create(Socket<Address, Udp> &) noexcept
-	{
-		/* No-op */
-	}
-
-	/**
-	 * Receive data from an end point.
-	 *
-	 * If the socket is marked non-blocking and no data is available, 0 is returned and condition is set to
-	 * Condition::Readable.
-	 *
-	 * If the socket is blocking, this functions blocks until some data is available or if an error occurs.
-	 *
-	 * @param sc the socket
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @param address the address
-	 * @param addrlen the initial address length
-	 * @return the number of bytes received
-	 * @throw Error on error
-	 */
-	template <typename Address>
-	unsigned recvfrom(Socket<Address, Udp> &sc, void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
-	{
-		int nbread;
-
-		nbread = ::recvfrom(sc.handle(), (Arg)data, length, 0, address, addrlen);
-
-		if (nbread == Failure) {
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				nbread = 0;
-				sc.setCondition(Condition::Readable);
-			} else {
-				throw Error{Error::System, "recvfrom"};
-			}
-#else
-			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				nbread = 0;
-				sc.setCondition(Condition::Readable);
-			} else {
-				throw Error{Error::System, "recvfrom"};
-			}
-#endif
-		}
-
-		return static_cast<unsigned>(nbread);
-	}
-
-	/**
-	 * Send data to an end point.
-	 *
-	 * If the socket is marked non-blocking and the operation would block, then 0 is returned and condition is set to
-	 * Condition::Writable.
-	 *
-	 * If the socket is blocking, this functions blocks until the data has been sent.
-	 *
-	 * @param sc the socket
-	 * @param data the buffer
-	 * @param length the buffer length
-	 * @param address the client address
-	 * @param addrlen the adderss length
-	 * @return the number of bytes sent
-	 * @throw Error on error
-	 */
-	template <typename Address>
-	unsigned sendto(Socket<Address, Udp> &sc, const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
-	{
-		int nbsent;
-
-		nbsent = ::sendto(sc.handle(), (ConstArg)data, length, 0, address, addrlen);
-		if (nbsent == Failure) {
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				nbsent = 0;
-				sc.setCondition(Condition::Writable);
-			} else {
-				throw Error{Error::System, "sendto", error};
-			}
-#else
-			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				nbsent = 0;
-				sc.setCondition(Condition::Writable);
-			} else {
-				throw Error{Error::System, "sendto"};
-			}
-#endif
-		}
-
-		return static_cast<unsigned>(nbsent);
-	}
-};
-
-/* }}} */
-
-/* {{{ Tls */
-
-#if !defined(SOCKET_NO_SSL)
-
-/**
- * @class Tls
- * @brief OpenSSL secure layer for TCP.
- *
- * **Note:** This protocol is much more difficult to use with non-blocking sockets, if some operations would block, the
- * user is responsible of calling the function again by waiting for the appropriate condition. See the functions for
- * more details.
- *
- * @see Tls::accept
- * @see Tls::connect
- * @see Tls::recv
- * @see Tls::send
- */
-class Tls : private Tcp {
-private:
-	using Context = std::shared_ptr<SSL_CTX>;
-	using Ssl = std::unique_ptr<SSL, void (*)(SSL *)>;
-
-	/* OpenSSL objects */
-	Context m_context;
-	Ssl m_ssl{nullptr, nullptr};
-
-	/* Status */
-	bool m_tcpconnected{false};
-
-	/*
-	 * User definable parameters
-	 */
-	ssl::Method m_method{ssl::Tlsv1};
-	std::string m_key;
-	std::string m_certificate;
-	bool m_verify{false};
-
-	/*
-	 * Construct with a context and ssl, for Tls::accept.
-	 */
-	Tls(Context context, Ssl ssl)
-		: m_context{std::move(context)}
-		, m_ssl{std::move(ssl)}
-	{
-	}
-
-	/*
-	 * Get the OpenSSL error message.
-	 */
-	inline std::string error(int error)
-	{
-		auto msg = ERR_reason_error_string(error);
-
-		return msg == nullptr ? "" : msg;
-	}
-
-	/*
-	 * Update the states after an uncompleted operation.
-	 */
-	template <typename Address, typename Protocol>
-	inline void updateStates(Socket<Address, Protocol> &sc, State state, Action action, int code)
-	{
-		assert(code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE);
-
-		sc.setState(state);
-		sc.setAction(action);
-
-		if (code == SSL_ERROR_WANT_READ) {
-			sc.setCondition(Condition::Readable);
-		} else {
-			sc.setCondition(Condition::Writable);
-		}
-	}
-
-	/*
-	 * Continue the connect operation.
-	 */
-	template <typename Address, typename Protocol>
-	void processConnect(Socket<Address, Protocol> &sc)
-	{
-		int ret = SSL_connect(m_ssl.get());
-
-		if (ret <= 0) {
-			int no = SSL_get_error(m_ssl.get(), ret);
-
-			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
-				updateStates(sc, State::Connecting, Action::Connect, no);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "connect", error(no)};
-			}
-		} else {
-			sc.setState(State::Connected);
-		}
-	}
-
-	/*
-	 * Continue accept.
-	 */
-	template <typename Address, typename Protocol>
-	void processAccept(Socket<Address, Protocol> &sc)
-	{
-		int ret = SSL_accept(m_ssl.get());
-
-		if (ret <= 0) {
-			int no = SSL_get_error(m_ssl.get(), ret);
-
-			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
-				updateStates(sc, State::Accepting, Action::Accept, no);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error(Error::System, "accept", error(no));
-			}
-		} else {
-			sc.setState(State::Accepted);
-		}
-	}
-
-public:
-	/**
-	 * @copydoc Tcp::type
-	 */
-	inline int type() const noexcept
-	{
-		return SOCK_STREAM;
-	}
-
-	/**
-	 * Empty TLS constructor.
-	 */
-	Tls()
-	{
-#if !defined(SOCKET_NO_SSL_AUTO_INIT)
-		::net::ssl::init();
-#endif
-	}
-
-	/**
-	 * Set the method.
-	 *
-	 * @param method the method
-	 * @pre the socket must not be already created
-	 */
-	inline void setMethod(ssl::Method method) noexcept
-	{
-		assert(!m_context);
-		assert(!m_ssl);
-
-		m_method = method;
-	}
-
-	/**
-	 * Use the specified private key file.
-	 *
-	 * @param file the path to the private key
-	 */
-	inline void setPrivateKey(std::string file) noexcept
-	{
-		m_key = std::move(file);
-	}
-
-	/**
-	 * Use the specified certificate file.
-	 *
-	 * @param file the path to the file
-	 */
-	inline void setCertificate(std::string file) noexcept
-	{
-		m_certificate = std::move(file);
-	}
-
-	/**
-	 * Set to true if we must verify the certificate and private key.
-	 *
-	 * @param verify the mode
-	 */
-	inline void setVerify(bool verify = true) noexcept
-	{
-		m_verify = verify;
-	}
-
-	/**
-	 * Initialize the SSL objects after have created.
-	 *
-	 * @param sc the socket
-	 * @throw net::Error on errors
-	 */
-	template <typename Address>
-	inline void create(Socket<Address, Tls> &sc)
-	{
-		auto method = (m_method == ssl::Tlsv1) ? TLSv1_method() : SSLv3_method();
-
-		m_context = {SSL_CTX_new(method), SSL_CTX_free};
-		m_ssl = {SSL_new(m_context.get()), SSL_free};
-
-		SSL_set_fd(m_ssl.get(), sc.handle());
-
-		/* Load certificates */
-		if (m_certificate.size() > 0) {
-			SSL_CTX_use_certificate_file(m_context.get(), m_certificate.c_str(), SSL_FILETYPE_PEM);
-		}
-		if (m_key.size() > 0) {
-			SSL_CTX_use_PrivateKey_file(m_context.get(), m_key.c_str(), SSL_FILETYPE_PEM);
-		}
-		if (m_verify && !SSL_CTX_check_private_key(m_context.get())) {
-			throw Error{Error::System, "(openssl)", "unable to verify key"};
-		}
-	}
-
-	/**
-	 * Connect to a secure host.
-	 *
-	 * If the socket is marked non-blocking and the connection cannot be established yet, then the state is set
-	 * to State::Connecting, the condition is set to Condition::Readable or Condition::Writable, the user must
-	 * wait for the appropriate condition before calling the overload connect which takes 0 argument.
-	 *
-	 * If the socket is blocking, this functions blocks until the connection is complete.
-	 *
-	 * If the connection was completed correctly the state is set to State::Connected.
-	 *
-	 * @param sc the socket
-	 * @param address the address
-	 * @param length the address length
-	 * @throw net::Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	void connect(Socket<Address, Protocol> &sc, const sockaddr *address, socklen_t length)
-	{
-		/* 1. Connect using raw TCP */
-		Tcp::connect(sc, address, length);
-
-		/* 2. If the connection is complete (e.g. non-blocking), try handshake */
-		if (sc.state() == State::Connected) {
-			m_tcpconnected = true;
-			processConnect(sc);
-		}
-	}
-
-	/**
-	 * Continue the connection.
-	 *
-	 * This function must be called when the socket is ready for reading or writing (check with Socket::condition),
-	 * the state may change exactly like the initial connect call.
-	 *
-	 * @param sc the socket
-	 * @throw net::Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	void connect(Socket<Address, Protocol> &sc)
-	{
-		/* 1. Be sure to complete standard connect before */
-		if (!m_tcpconnected) {
-			Tcp::connect(sc);
-			m_tcpconnected = sc.state() == State::Connected;
-		}
-
-		if (m_tcpconnected) {
-			processConnect(sc);
-		}
-	}
-
-	/**
-	 * Accept a secure client.
-	 *
-	 * Because SSL needs several round-trips, if the socket is marked non-blocking and the connection is not
-	 * completed yet, a new socket is returned but with the State::Accepting state. Its condition is set to
-	 * Condition::Readable or Condition::Writable, the user is responsible of calling accept overload which takes
-	 * 0 arguments on the returned socket when the condition is met.
-	 *
-	 * If the socket is blocking, this function blocks until the client is accepted and returned.
-	 *
-	 * If the client is accepted correctly, its state is set to State::Accepted. This instance does not change.
-	 *
-	 * @param sc the socket
-	 * @param address the address destination
-	 * @param length the address length
-	 * @return the client
-	 * @throw net::Error on errors
-	 */
-	template <typename Address>
-	Socket<Address, Tls> accept(Socket<Address, Tls> &sc, sockaddr *address, socklen_t *length)
-	{
-		Socket<Address, Tls> client = Tcp::accept(sc, address, length);
-		Tls &proto = client.protocol();
-
-		/* 1. Share the context */
-		proto.m_context = m_context;
-
-		/* 2. Create new SSL instance */
-		proto.m_ssl = Ssl{SSL_new(m_context.get()), SSL_free};
-		SSL_set_fd(proto.m_ssl.get(), client.handle());
-
-		/* 3. Try accept process on the **new** client */
-		proto.processAccept(client);
-
-		return client;
-	}
-
-	/**
-	 * Continue accept.
-	 *
-	 * This function must be called on the client that is being accepted.
-	 *
-	 * Like accept or connect, user is responsible of calling this function until the connection is complete.
-	 *
-	 * @param sc the socket
-	 * @throw net::Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void accept(Socket<Address, Protocol> &sc)
-	{
-		processAccept(sc);
-	}
-
-	/**
-	 * Receive some secure data.
-	 *
-	 * If the socket is marked non-blocking, 0 is returned if no data is available yet or if the connection
-	 * needs renegociation. If renegociation is required case, the action is set to Action::Receive and condition
-	 * is set to Condition::Readable or Condition::Writable. The user must wait that the condition is met and
-	 * call this function again.
-	 *
-	 * @param sc the socket
-	 * @param data the destination
-	 * @param len the buffer length
-	 * @return the number of bytes read
-	 * @throw net::Error on errors
-	 */
-	template <typename Address>
-	unsigned recv(Socket<Address, Tls> &sc, void *data, unsigned len)
-	{
-		auto nbread = SSL_read(m_ssl.get(), data, len);
-
-		if (nbread <= 0) {
-			auto no = SSL_get_error(m_ssl.get(), nbread);
-
-			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
-				nbread = 0;
-				updateStates(sc, sc.state(), Action::Receive, no);
-			} else {
-				throw Error{Error::System, "recv", error(no)};
-			}
-		}
-
-		return nbread;
-	}
-
-	/**
-	 * Send some data.
-	 *
-	 * Like recv, if the socket is marked non-blocking and no data can be sent or a negociation is required,
-	 * condition and action are set. See receive for more details
-	 *
-	 * @param sc the socket
-	 * @param data the data to send
-	 * @param len the buffer length
-	 * @return the number of bytes sent
-	 * @throw net::Error on errors
-	 */
-	template <typename Address>
-	unsigned send(Socket<Address, Tls> &sc, const void *data, unsigned len)
-	{
-		auto nbsent = SSL_write(m_ssl.get(), data, len);
-
-		if (nbsent <= 0) {
-			auto no = SSL_get_error(m_ssl.get(), nbsent);
-
-			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
-				nbsent = 0;
-				updateStates(sc, sc.state(), Action::Send, no);
-			} else {
-				throw Error{Error::System, "send", error(no)};
-			}
-		}
-
-		return nbsent;
-	}
-};
-
-#endif // !SOCKET_NO_SSL
-
-/* }}} */
-
-} // !protocol
-
-/* }}} */
-
-/*
- * Convenient helpers
- * ------------------------------------------------------------------
- *
- * - SocketTcp<Address>, for TCP sockets,
- * - SocketUdp<Address>, for UDP sockets,
- * - SocketTls<Address>, for secure TCP sockets.
- */
-
-/* {{{ Helpers */
-
-/**
- * Helper to create TCP sockets.
- */
-template <typename Address>
-using SocketTcp = Socket<Address, protocol::Tcp>;
-
-/**
- * Helper to create TCP/IP sockets.
- */
-using SocketTcpIp = Socket<address::Ip, protocol::Tcp>;
-
-#if !defined(_WIN32)
-
-/**
- * Helper to create TCP/Local sockets.
- */
-using SocketTcpLocal = Socket<address::Local, protocol::Tcp>;
-
-#endif
-
-/**
- * Helper to create UDP sockets.
- */
-template <typename Address>
-using SocketUdp = Socket<Address, protocol::Udp>;
-
-/**
- * Helper to create UDP/IP sockets.
- */
-using SocketUdpIp = Socket<address::Ip, protocol::Udp>;
-
-#if !defined(SOCKET_NO_SSL)
-
-/**
- * Helper to create OpenSSL TCP sockets.
- */
-template <typename Address>
-using SocketTls = Socket<Address, protocol::Tls>;
-
-/**
- * Helper to create OpenSSL TCP/Ip sockets.
- */
-using SocketTlsIp = Socket<address::Ip, protocol::Tls>;
-
-#endif // !SOCKET_NO_SSL
-
-/* }}} */
-
-/*
- * Select wrapper
- * ------------------------------------------------------------------
- *
- * Wrapper for select(2) and other various implementations.
- */
-
-/* {{{ Listener */
-
-/**
- * @class ListenerStatus
- * @brief Result of polling
- *
- * Result of a select call, returns the first ready socket found with its
- * flags.
- */
-class ListenerStatus {
-public:
-	Handle socket;		//!< which socket is ready
-	Condition flags;	//!< the flags
-};
-
-/**
- * Table used in the socket listener to store which sockets have been
- * set in which directions.
- */
-using ListenerTable = std::map<Handle, Condition>;
-
-/**
- * @class Select
- * @brief Implements select(2)
- *
- * This class is the fallback of any other method, it is not preferred at all for many reasons.
- */
-class Select {
-public:
-	/**
-	 * No-op, uses the ListenerTable directly.
-	 */
-	inline void set(const ListenerTable &, Handle, Condition, bool) noexcept {}
-
-	/**
-	 * No-op, uses the ListenerTable directly.
-	 */
-	inline void unset(const ListenerTable &, Handle, Condition, bool) noexcept {}
-
-	/**
-	 * Return the sockets
-	 */
-	std::vector<ListenerStatus> wait(const ListenerTable &table, int ms);
-
-	/**
-	 * Backend identifier
-	 */
-	inline const char *name() const noexcept
-	{
-		return "select";
-	}
-};
-
-#if defined(SOCKET_HAVE_POLL)
-
-/**
- * @class Poll
- * @brief Implements poll(2).
- *
- * Poll is widely supported and is better than select(2). It is still not the
- * best option as selecting the sockets is O(n).
- */
-class Poll {
-private:
-	std::vector<pollfd> m_fds;
-
-	short toPoll(Condition flags) const noexcept;
-	Condition toCondition(short &event) const noexcept;
-
-public:
-	/**
-	 * Set the handle.
-	 */
-	void set(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Unset the handle.
-	 */
-	void unset(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Wait for events.
-	 */
-	std::vector<ListenerStatus> wait(const ListenerTable &, int ms);
-
-	/**
-	 * Backend identifier
-	 */
-	inline const char *name() const noexcept
-	{
-		return "poll";
-	}
-};
-
-#endif
-
-#if defined(SOCKET_HAVE_EPOLL)
-
-/**
- * @class Epoll
- * @brief Linux's epoll.
- */
-class Epoll {
-private:
-	int m_handle;
-	std::vector<epoll_event> m_events;
-
-	Epoll(const Epoll &) = delete;
-	Epoll &operator=(const Epoll &) = delete;
-	Epoll(const Epoll &&) = delete;
-	Epoll &operator=(const Epoll &&) = delete;
-
-	uint32_t toEpoll(Condition flags) const noexcept;
-	Condition toCondition(uint32_t events) const noexcept;
-	void update(Handle sc, int op, int eflags);
-
-public:
-	/**
-	 * Construct the epoll instance.
-	 */
-	Epoll();
-
-	/**
-	 * Close the epoll instance.
-	 */
-	~Epoll();
-
-	/**
-	 * Set the handle.
-	 */
-	void set(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Unset the handle.
-	 */
-	void unset(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Wait for events.
-	 */
-	std::vector<ListenerStatus> wait(const ListenerTable &, int);
-
-	/**
-	 * Backend identifier
-	 */
-	inline const char *name() const noexcept
-	{
-		return "epoll";
-	}
-};
-
-#endif
-
-#if defined(SOCKET_HAVE_KQUEUE)
-
-/**
- * @class Kqueue
- * @brief Implements kqueue(2).
- *
- * This implementation is available on all BSD and Mac OS X. It is better than
- * poll(2) because it's O(1), however it's a bit more memory consuming.
- */
-class Kqueue {
-private:
-	std::vector<struct kevent> m_result;
-	int m_handle;
-
-	Kqueue(const Kqueue &) = delete;
-	Kqueue &operator=(const Kqueue &) = delete;
-	Kqueue(Kqueue &&) = delete;
-	Kqueue &operator=(Kqueue &&) = delete;
-
-	void update(Handle sc, int filter, int kflags);
-
-public:
-	/**
-	 * Construct the kqueue instance.
-	 */
-	Kqueue();
-
-	/**
-	 * Destroy the kqueue instance.
-	 */
-	~Kqueue();
-
-	/**
-	 * Set the handle.
-	 */
-	void set(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Unset the handle.
-	 */
-	void unset(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Wait for events.
-	 */
-	std::vector<ListenerStatus> wait(const ListenerTable &, int);
-
-	/**
-	 * Backend identifier
-	 */
-	inline const char *name() const noexcept
-	{
-		return "kqueue";
-	}
-};
-
-#endif
-
-/**
- * @class Listener
- * @brief Synchronous multiplexing
- *
- * Convenient wrapper around the select() system call.
- *
- * This class is implemented using a bridge pattern to allow different uses
- * of listener implementation.
- *
- * You should not reinstanciate a new Listener at each iteartion of your
- * main loop as it can be extremely costly. Instead use the same listener that
- * you can safely modify on the fly.
- *
- * Currently, poll, epoll, select and kqueue are available.
- *
- * To implement the backend, the following functions must be available:
- *
- * ### Set
- *
- * @code
- * void set(const ListenerTable &, Handle sc, Condition condition, bool add);
- * @endcode
- *
- * This function, takes the socket to be added and the flags. The condition is
- * always guaranteed to be correct and the function will never be called twice
- * even if the user tries to set the same flag again.
- *
- * An optional add argument is added for backends which needs to do different
- * operation depending if the socket was already set before or if it is the
- * first time (e.g EPOLL_CTL_ADD vs EPOLL_CTL_MOD for epoll(7).
- *
- * ### Unset
- *
- * @code
- * void unset(const ListenerTable &, Handle sc, Condition condition, bool remove);
- * @endcode
- *
- * Like set, this function is only called if the condition is actually set and will
- * not be called multiple times.
- *
- * Also like set, an optional remove argument is set if the socket is being
- * completely removed (e.g no more flags are set for this socket).
- *
- * ### Wait
- *
- * @code
- * std::vector<ListenerStatus> wait(const ListenerTable &, int ms);
- * @endcode
- *
- * Wait for the sockets to be ready with the specified milliseconds. Must return a list of ListenerStatus,
- * may throw any exceptions.
- *
- * ### Name
- *
- * @code
- * inline const char *name() const noexcept
- * @endcode
- *
- * Returns the backend name. Usually the class in lower case.
- */
-template <typename Backend = SOCKET_DEFAULT_BACKEND>
-class Listener {
-private:
-	Backend m_backend;
-	ListenerTable m_table;
-
-public:
-	/**
-	 * Construct an empty listener.
-	 */
-	Listener() = default;
-
-	/**
-	 * Get the backend.
-	 *
-	 * @return the backend
-	 */
-	inline const Backend &backend() const noexcept
-	{
-		return m_backend;
-	}
-
-	/**
-	 * Get the non-modifiable table.
-	 *
-	 * @return the table
-	 */
-	inline const ListenerTable &table() const noexcept
-	{
-		return m_table;
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the iterator
-	 */
-	inline ListenerTable::const_iterator begin() const noexcept
-	{
-		return m_table.begin();
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the iterator
-	 */
-	inline ListenerTable::const_iterator cbegin() const noexcept
-	{
-		return m_table.cbegin();
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the iterator
-	 */
-	inline ListenerTable::const_iterator end() const noexcept
-	{
-		return m_table.end();
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the iterator
-	 */
-	inline ListenerTable::const_iterator cend() const noexcept
-	{
-		return m_table.cend();
-	}
-
-	/**
-	 * Add or update a socket to the listener.
-	 *
-	 * If the socket is already placed with the appropriate flags, the
-	 * function is a no-op.
-	 *
-	 * If incorrect flags are passed, the function does nothing.
-	 *
-	 * @param sc the socket
-	 * @param condition the condition (may be OR'ed)
-	 * @throw Error if the backend failed to set
-	 */
-	void set(Handle sc, Condition condition)
-	{
-		/* Invalid or useless flags */
-		if (condition == Condition::None || static_cast<int>(condition) > 0x3)
-			return;
-
-		auto it = m_table.find(sc);
-
-		/*
-		 * Do not update the table if the backend failed to add
-		 * or update.
-		 */
-		if (it == m_table.end()) {
-			m_backend.set(m_table, sc, condition, true);
-			m_table.emplace(sc, condition);
-		} else {
-			/* Remove flag if already present */
-			if ((condition & Condition::Readable) == Condition::Readable &&
-			    (it->second & Condition::Readable) == Condition::Readable) {
-				condition &= ~(Condition::Readable);
-			}
-			if ((condition & Condition::Writable) == Condition::Writable &&
-			    (it->second & Condition::Writable) == Condition::Writable) {
-				condition &= ~(Condition::Writable);
-			}
-
-			/* Still need a call? */
-			if (condition != Condition::None) {
-				m_backend.set(m_table, sc, condition, false);
-				it->second |= condition;
-			}
-		}
-	}
-
-	/**
-	 * Unset a socket from the listener, only the flags is removed
-	 * unless the two flagss are requested.
-	 *
-	 * For example, if you added a socket for both reading and writing,
-	 * unsetting the write flags will keep the socket for reading.
-	 *
-	 * @param sc the socket
-	 * @param condition the condition (may be OR'ed)
-	 * @see remove
-	 */
-	void unset(Handle sc, Condition condition)
-	{
-		auto it = m_table.find(sc);
-
-		/* Invalid or useless flags */
-		if (condition == Condition::None || static_cast<int>(condition) > 0x3 || it == m_table.end())
-			return;
-
-		/*
-		 * Like set, do not update if the socket is already at the appropriate
-		 * state.
-		 */
-		if ((condition & Condition::Readable) == Condition::Readable &&
-		    (it->second & Condition::Readable) != Condition::Readable) {
-			condition &= ~(Condition::Readable);
-		}
-		if ((condition & Condition::Writable) == Condition::Writable &&
-		    (it->second & Condition::Writable) != Condition::Writable) {
-			condition &= ~(Condition::Writable);
-		}
-
-		if (condition != Condition::None) {
-			/* Determine if it's a complete removal */
-			bool removal = ((it->second) & ~(condition)) == Condition::None;
-
-			m_backend.unset(m_table, sc, condition, removal);
-
-			if (removal) {
-				m_table.erase(it);
-			} else {
-				it->second &= ~(condition);
-			}
-		}
-	}
-
-	/**
-	 * Remove completely the socket from the listener.
-	 *
-	 * It is a shorthand for unset(sc, Condition::Readable | Condition::Writable);
-	 *
-	 * @param sc the socket
-	 */
-	inline void remove(Handle sc)
-	{
-		unset(sc, Condition::Readable | Condition::Writable);
-	}
-
-	/**
-	 * Remove all sockets.
-	 */
-	inline void clear()
-	{
-		while (!m_table.empty()) {
-			remove(m_table.begin()->first);
-		}
-	}
-
-	/**
-	 * Get the number of sockets in the listener.
-	 */
-	inline ListenerTable::size_type size() const noexcept
-	{
-		return m_table.size();
-	}
-
-	/**
-	 * Select a socket. Waits for a specific amount of time specified as the duration.
-	 *
-	 * @param duration the duration
-	 * @return the socket ready
-	 */
-	template <typename Rep, typename Ratio>
-	inline ListenerStatus wait(const std::chrono::duration<Rep, Ratio> &duration)
-	{
-		auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
-
-		return m_backend.wait(m_table, cvt.count())[0];
-	}
-
-	/**
-	 * Overload with milliseconds.
-	 *
-	 * @param timeout the optional timeout in milliseconds
-	 * @return the socket ready
-	 */
-	inline ListenerStatus wait(int timeout = -1)
-	{
-		return wait(std::chrono::milliseconds(timeout));
-	}
-
-	/**
-	 * Select multiple sockets.
-	 *
-	 * @param duration the duration
-	 * @return the socket ready
-	 */
-	template <typename Rep, typename Ratio>
-	inline std::vector<ListenerStatus> waitMultiple(const std::chrono::duration<Rep, Ratio> &duration)
-	{
-		auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
-
-		return m_backend.wait(m_table, cvt.count());
-	}
-
-	/**
-	 * Overload with milliseconds.
-	 *
-	 * @return the socket ready
-	 */
-	inline std::vector<ListenerStatus> waitMultiple(int timeout = -1)
-	{
-		return waitMultiple(std::chrono::milliseconds(timeout));
-	}
-};
-
-/* }}} */
-
-/*
- * Callback
- * ------------------------------------------------------------------
- *
- * Function owner with tests.
- */
-
-/* {{{ Callback */
-
-/**
- * @class Callback
- * @brief Convenient signal owner that checks if the target is valid.
- *
- * This class also catch all errors thrown from signals to avoid interfering with our process.
- */
-template <typename... Args>
-class Callback : public std::function<void (Args...)> {
-public:
-	/**
-	 * Inherited constructors.
-	 */
-	using std::function<void (Args...)>::function;
-
-	/**
-	 * Execute the callback only if a target is set.
-	 */
-	void operator()(Args... args) const
-	{
-		if (*this) {
-			try {
-				std::function<void (Args...)>::operator()(args...);
-			} catch (...) {
-			}
-		}
-	}
-};
-
-/* }}} */
-
-/*
- * StreamConnection
- * ------------------------------------------------------------------
- *
- * Client connected on the server side.
- */
-
-/* {{{ StreamConnection */
-
-/**
- * @class StreamConnection
- * @brief Connected client on the server side.
- *
- * This object is created from StreamServer when a new client is connected, it is the higher
- * level object of sockets and completely asynchronous.
- */
-template <typename Address, typename Protocol>
-class StreamConnection {
-public:
-	/**
-	 * Called when the output has changed.
-	 */
-	using WriteHandler = Callback<>;
-
-private:
-	/* Signals */
-	WriteHandler m_onWrite;
-
-	/* Sockets and output buffer */
-	Socket<Address, Protocol> m_socket;
-	std::string m_output;
-
-public:
-	/**
-	 * Create the connection.
-	 *
-	 * @param s the socket
-	 */
-	StreamConnection(Socket<Address, Protocol> s)
-		: m_socket{std::move(s)}
-	{
-		m_socket.set(net::option::SockBlockMode{false});
-	}
-
-	/**
-	 * Access the underlying socket.
-	 *
-	 * @return the socket
-	 * @warning use with care
-	 */
-	inline Socket<Address, Protocol> &socket() noexcept
-	{
-		return m_socket;
-	}
-
-	/**
-	 * Access the current output.
-	 *
-	 * @return the output
-	 */
-	inline const std::string &output() const noexcept
-	{
-		return m_output;
-	}
-
-	/**
-	 * Overloaded function
-	 *
-	 * @return the output
-	 * @warning use with care, avoid modifying the output if you don't know what you're doing
-	 */
-	inline std::string &output() noexcept
-	{
-		return m_output;
-	}
-
-	/**
-	 * Post some data to be sent asynchronously.
-	 *
-	 * @param str the data to append
-	 */
-	inline void send(std::string str)
-	{
-		m_output += str;
-		m_onWrite();
-	}
-
-	/**
-	 * Kill the client.
-	 */
-	inline void close()
-	{
-		m_socket.close();
-	}
-
-	/**
-	 * Set the write handler, the signal is emitted when the output has changed so that the StreamServer owner
-	 * knows that there are some data to send.
-	 *
-	 * @param handler the handler
-	 * @warning you usually never need to set this yourself
-	 */
-	inline void setWriteHandler(WriteHandler handler)
-	{
-		m_onWrite = std::move(handler);
-	}
-};
-
-/* }}} */
-
-/*
- * StreamServer
- * ------------------------------------------------------------------
- *
- * Convenient stream oriented server.
- */
-
-/* {{{ StreamServer */
-
-/**
- * @class StreamServer
- * @brief Convenient stream server for TCP and TLS.
- *
- * This class does all the things for you as accepting new clients, listening for it and sending data. It works
- * asynchronously without blocking to let you control your process workflow.
- *
- * This class is not thread safe and you must not call any of the functions from different threads.
- */
-template <typename Address, typename Protocol>
-class StreamServer {
-public:
-	/**
-	 * Handler when a new client is connected.
-	 */
-	using ConnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
-
-	/**
-	 * Handler when a client is disconnected.
-	 */
-	using DisconnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
-
-	/**
-	 * Handler when data has been received from a client.
-	 */
-	using ReadHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
-
-	/**
-	 * Handler when data has been correctly sent to a client.
-	 */
-	using WriteHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
-
-	/**
-	 * Handler when an error occured.
-	 */
-	using ErrorHandler = Callback<const Error &>;
-
-	/**
-	 * Handler when there was a timeout.
-	 */
-	using TimeoutHandler = Callback<>;
-
-private:
-	using ClientMap = std::map<Handle, std::shared_ptr<StreamConnection<Address, Protocol>>>;
-
-	/* Signals */
-	ConnectionHandler m_onConnection;
-	DisconnectionHandler m_onDisconnection;
-	ReadHandler m_onRead;
-	WriteHandler m_onWrite;
-	ErrorHandler m_onError;
-	TimeoutHandler m_onTimeout;
-
-	/* Sockets */
-	Socket<Address, Protocol> m_master;
-	Listener<> m_listener;
-	ClientMap m_clients;
-
-	/*
-	 * Update flags depending on the required condition.
-	 */
-	void updateFlags(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
-	{
-		assert(client->socket().action() != Action::None);
-
-		m_listener.remove(client->socket().handle());
-		m_listener.set(client->socket().handle(), client->socket().condition());
-	}
-
-	/*
-	 * Continue accept process.
-	 */
-	template <typename AcceptCall>
-	void processAccept(std::shared_ptr<StreamConnection<Address, Protocol>> &client, const AcceptCall &acceptFunc)
-	{
-		try {
-			/* Do the accept */
-			acceptFunc();
-
-			/* 1. First remove completely the client */
-			m_listener.remove(client->socket().handle());
-
-			/* 2. If accept is not finished, wait for the appropriate condition */
-			if (client->socket().state() == State::Accepted) {
-				/* 3. Client is accepted, notify the user */
-				m_listener.set(client->socket().handle(), Condition::Readable);
-				m_onConnection(client);
-			} else {
-				/* Operation still in progress */
-				updateFlags(client);
-			}
-		} catch (const Error &error) {
-			m_clients.erase(client->socket().handle());
-			m_listener.remove(client->socket().handle());
-			m_onError(error);
-		}
-	}
-
-	/*
-	 * Process initial accept of master socket, this is the initial accepting process. Except on errors, the
-	 * socket is stored but the user will be notified only once the socket is completely accepted.
-	 */
-	void processInitialAccept()
-	{
-		// TODO: store address too.
-		std::shared_ptr<StreamConnection<Address, Protocol>> client = std::make_shared<StreamConnection<Address, Protocol>>(m_master.accept(nullptr));
-		std::weak_ptr<StreamConnection<Address, Protocol>> ptr{client};
-
-		/* 1. Register output changed to update listener */
-		client->setWriteHandler([this, ptr] () {
-			auto client = ptr.lock();
-
-			/* Do not update the listener immediately if an action is pending */
-			if (client && client->socket().action() == Action::None && !client->output().empty()) {
-				m_listener.set(client->socket().handle(), Condition::Writable);
-			}
-		});
-
-		/* 2. Add the client */
-		m_clients.insert(std::make_pair(client->socket().handle(), client));
-
-		/*
-		 * 2. Do an initial check to set the listener flags, at this moment the socket may or not be
-		 *    completely accepted.
-		 */
-		processAccept(client, [&] () {});
-	}
-
-	/*
-	 * Read or complete the read operation.
-	 */
-	void processRead(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
-	{
-		/*
-		 * Read because there is something to read or because the pending operation is
-		 * read and must complete.
-		 */
-		auto buffer = client->socket().recv(512);
-
-		/*
-		 * Now the receive operation may be completed, in that case, two possibilities:
-		 *
-		 * 1. The action is set to None (completed)
-		 * 2. The action is still not complete, update the flags
-		 */
-		if (client->socket().action() == Action::None) {
-			/* Empty mean normal disconnection */
-			if (buffer.empty()) {
-				m_listener.remove(client->socket().handle());
-				m_clients.erase(client->socket().handle());
-				m_onDisconnection(client);
-			} else {
-				/*
-				 * At this step, it is possible that we were completing a receive operation, in this
-				 * case the write flag may be removed, add it if required.
-				 */
-				if (!client->output().empty()) {
-					m_listener.set(client->socket().handle(), Condition::Writable);
-				}
-
-				m_onRead(client, buffer);
-			}
-		} else {
-			/* Operation in progress */
-			updateFlags(client);
-		}
-	}
-
-	/*
-	 * Flush the output buffer.
-	 */
-	void processWrite(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
-	{
-		auto &output = client->output();
-		auto nsent = client->socket().send(output);
-
-		if (client->socket().action() == Action::None) {
-			/* 1. Create a copy of content that has been sent */
-			auto sent = output.substr(0, nsent);
-
-			/* 2. Erase the content sent */
-			output.erase(0, nsent);
-
-			/* 3. Update listener */
-			if (output.empty()) {
-				m_listener.unset(client->socket().handle(), Condition::Writable);
-			}
-
-			/* 4. Notify user */
-			m_onWrite(client, sent);
-		} else {
-			updateFlags(client);
-		}
-	}
-
-	void processSync(std::shared_ptr<StreamConnection<Address, Protocol>> &client, Condition flags)
-	{
-		try {
-			auto action = client->socket().action();
-
-			if (action == Action::Receive ||
-			    (action == Action::None && (flags & Condition::Readable) == Condition::Readable)) {
-				processRead(client);
-			} else if ((flags & Condition::Writable) == Condition::Writable) {
-				processWrite(client);
-			}
-		} catch (const Error &error) {
-			m_onDisconnection(client);
-			m_listener.remove(client->socket().handle());
-			m_clients.erase(client->socket().handle());
-		}
-	}
-
-public:
-	/**
-	 * Create a stream server with the specified address to bind.
-	 *
-	 * @param protocol the protocol (Tcp or Tls)
-	 * @param address the address to bind
-	 * @param max the max number to listen
-	 * @throw Error on errors
-	 */
-	StreamServer(Protocol protocol, const Address &address, int max = 128)
-		: m_master{std::move(protocol), address}
-	{
-		// TODO: m_onError
-		m_master.set(SOL_SOCKET, SO_REUSEADDR, 1);
-		m_master.bind(address);
-		m_master.listen(max);
-		m_listener.set(m_master.handle(), Condition::Readable);
-	}
-
-	/**
-	 * Set the connection handler, called when a new client is connected.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setConnectionHandler(ConnectionHandler handler)
-	{
-		m_onConnection = std::move(handler);
-	}
-
-	/**
-	 * Set the disconnection handler, called when a client died.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setDisconnectionHandler(DisconnectionHandler handler)
-	{
-		m_onDisconnection = std::move(handler);
-	}
-
-	/**
-	 * Set the receive handler, called when a client has sent something.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setReadHandler(ReadHandler handler)
-	{
-		m_onRead = std::move(handler);
-	}
-
-	/**
-	 * Set the writing handler, called when some data has been sent to a client.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setWriteHandler(WriteHandler handler)
-	{
-		m_onWrite = std::move(handler);
-	}
-
-	/**
-	 * Set the error handler, called when unrecoverable error has occured.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setErrorHandler(ErrorHandler handler)
-	{
-		m_onError = std::move(handler);
-	}
-
-	/**
-	 * Set the timeout handler, called when the selection has timeout.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setTimeoutHandler(TimeoutHandler handler)
-	{
-		m_onTimeout = std::move(handler);
-	}
-
-	/**
-	 * Poll for the next event.
-	 *
-	 * @param timeout the timeout (-1 for indefinitely)
-	 * @throw Error on errors
-	 */
-	void poll(int timeout = -1)
-	{
-		try {
-			auto st = m_listener.wait(timeout);
-
-			if (st.socket == m_master.handle()) {
-				/* New client */
-				processInitialAccept();
-			} else {
-				/* Recv / Send / Accept on a client */
-				auto client = m_clients[st.socket];
-
-				if (client->socket().state() == State::Accepted) {
-					processSync(client, st.flags);
-				} else {
-					processAccept(client, [&] () { client->socket().accept(); });
-				}
-			}
-		} catch (const Error &error) {
-			if (error.code() == Error::Timeout) {
-				m_onTimeout();
-			} else {
-				m_onError(error);
-			}
-		}
-	}
-};
-
-/* }}} */
-
-/*
- * StreamClient
- * ------------------------------------------------------------------
- */
-
-/* {{{ StreamClient */
-
-/**
- * @class StreamClient
- * @brief Client side connection to a server.
- *
- * This class is not thread safe and you must not call any of the functions from different threads.
- */
-template <typename Address, typename Protocol>
-class StreamClient {
-public:
-	/**
-	 * Handler when connection is complete.
-	 */
-	using ConnectionHandler = Callback<>;
-
-	/**
-	 * Handler when data has been received.
-	 */
-	using ReadHandler = Callback<const std::string &>;
-
-	/**
-	 * Handler when data has been sent correctly.
-	 */
-	using WriteHandler = Callback<const std::string &>;
-
-	/**
-	 * Handler when disconnected.
-	 */
-	using DisconnectionHandler = Callback<>;
-
-	/**
-	 * Handler on unrecoverable error.
-	 */
-	using ErrorHandler = Callback<const Error &>;
-
-	/**
-	 * Handler when timeout occured.
-	 */
-	using TimeoutHandler = Callback<>;
-
-private:
-	/* Signals */
-	ConnectionHandler m_onConnection;
-	ReadHandler m_onRead;
-	WriteHandler m_onWrite;
-	DisconnectionHandler m_onDisconnection;
-	ErrorHandler m_onError;
-	TimeoutHandler m_onTimeout;
-
-	/* Socket */
-	Socket<Address, Protocol> m_socket;
-	Listener<> m_listener;
-
-	/* Output buffer */
-	std::string m_output;
-
-	/*
-	 * Update the flags after an uncompleted operation. This function must only be called when the operation
-	 * has not complete (e.g. connect, recv, send).
-	 */
-	void updateFlags()
-	{
-		assert(m_socket.action() != Action::None);
-
-		m_listener.remove(m_socket.handle());
-		m_listener.set(m_socket.handle(), m_socket.condition());
-	}
-
-	/*
-	 * This is the generic connect helper, it will be used to both initiate the connection or to continue the
-	 * connection process if needed.
-	 *
-	 * Thus the template parameter is the appropriate function to call either, m_socket.connect(address) or
-	 * m_socket.connect().
-	 *
-	 * See poll() and connect() to understand.
-	 */
-	template <typename ConnectCall>
-	void processConnect(const ConnectCall &connectFunc)
-	{
-		/* Call m_socket.connect() or m_socket.connect(address) */
-		connectFunc();
-
-		/* Remove entirely */
-		m_listener.remove(m_socket.handle());
-
-		if (m_socket.state() == State::Connected) {
-			m_onConnection();
-			m_listener.set(m_socket.handle(), Condition::Readable);
-		} else {
-			/* Connection still in progress */
-			updateFlags();
-		}
-	}
-
-	/*
-	 * Receive or complete the receive command, if the command is not complete, the listener is updated
-	 * accordingly.
-	 */
-	void processRead()
-	{
-		auto received = m_socket.recv(512);
-
-		if (m_socket.action() == Action::None) {
-			/* 0 means disconnection */
-			if (received.empty()) {
-				m_onDisconnection();
-			} else {
-				/*
-				 * At this step, it is possible that we were completing a receive operation, in this
-				 * case the write flag may be removed, add it if required.
-				 */
-				if (m_output.empty()) {
-					m_listener.unset(m_socket.handle(), Condition::Writable);
-				}
-
-				m_onRead(received);
-			}
-		} else {
-			/* Receive operation in progress */
-			updateFlags();
-		}
-	}
-
-	/*
-	 * Send or complete the send command, if the command is not complete, the listener is updated
-	 * accordingly.
-	 */
-	void processWrite()
-	{
-		auto nsent = m_socket.send(m_output);
-
-		if (m_socket.action() == Action::None) {
-			/* 1. Make a copy of what has been sent */
-			auto sent = m_output.substr(0, nsent);
-
-			/* 2. Erase sent content */
-			m_output.erase(0, nsent);
-
-			/* 3. Update flags if needed */
-			if (m_output.empty()) {
-				m_listener.unset(m_socket.handle(), Condition::Writable);
-			}
-
-			/* 4. Notify user */
-			m_onWrite(sent);
-		} else {
-			/* Send operation in progress */
-			updateFlags();
-		}
-	}
-
-	/*
-	 * Receive or send.
-	 */
-	void processSync(Condition condition)
-	{
-		if ((m_socket.action() == Action::Receive) ||
-		    (m_socket.action() == Action::None && (condition & Condition::Readable) == Condition::Readable)) {
-			processRead();
-		} else {
-			processWrite();
-		}
-	}
-
-public:
-	/**
-	 * Create a client. The client is automatically marked as non-blocking.
-	 *
-	 * @param protocol the protocol (Tcp or Tls)
-	 * @param address the optional address
-	 * @throw net::Error on failures
-	 */
-	StreamClient(Protocol protocol = {}, const Address &address = {})
-		: m_socket{std::move(protocol), address}
-	{
-		m_socket.set(net::option::SockBlockMode{false});
-		m_listener.set(m_socket.handle(), Condition::Readable);
-	}
-
-	/**
-	 * Set the connection handler, called when the connection succeed.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setConnectionHandler(ConnectionHandler handler)
-	{
-		m_onConnection = std::move(handler);
-	}
-
-	/**
-	 * Set the disconnection handler, called when the server closed the connection.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setDisconnectionHandler(DisconnectionHandler handler)
-	{
-		m_onDisconnection = std::move(handler);
-	}
-
-	/**
-	 * Set the read handler, called when we received something.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setReadHandler(ReadHandler handler)
-	{
-		m_onRead = std::move(handler);
-	}
-
-	/**
-	 * Set the write handler, called when we successfully sent data.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setWriteHandler(WriteHandler handler)
-	{
-		m_onWrite = std::move(handler);
-	}
-
-	/**
-	 * Set the error handler, called when unexpected error occurs.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setErrorHandler(ErrorHandler handler)
-	{
-		m_onError = std::move(handler);
-	}
-
-	/**
-	 * Connect to a server, this function may connect immediately or not in any case the connection handler
-	 * will be called when the connection completed.
-	 *
-	 * @param address the address to connect to
-	 */
-	void connect(const Address &address) noexcept
-	{
-		assert(m_socket.state() == State::Open);
-
-		processConnect([&] () { m_socket.connect(address); });
-	}
-
-	/**
-	 * Asynchronously send data to the server.
-	 *
-	 * @param str the data to append
-	 */
-	void send(std::string str)
-	{
-		m_output += str;
-
-		/* Don't update the listener if there is a pending operation */
-		if (m_socket.state() == State::Connected && m_socket.action() == Action::None && !m_output.empty()) {
-			m_listener.set(m_socket.handle(), Condition::Writable);
-		}
-	}
-
-	/**
-	 * Wait for the next event.
-	 *
-	 * @param timeout the time to wait in milliseconds
-	 * @throw Error on errors
-	 */
-	void poll(int timeout = -1) noexcept
-	{
-		try {
-			auto st = m_listener.wait(timeout);
-
-			if (m_socket.state() != State::Connected) {
-				/* Continue the connection */
-				processConnect([&] () { m_socket.connect(); });
-			} else {
-				/* Read / Write */
-				processSync(st.flags);
-			}
-		} catch (const Error &error) {
-			if (error.code() == Error::Timeout) {
-				m_onTimeout();
-			} else {
-				m_listener.remove(m_socket.handle());
-				m_onError(error);
-			}
-		}
-	}
-};
-
-/* }}} */
-
-} // !net
-
-#endif // !_SOCKETS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Socket/sockets.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,709 @@
+/*
+ * sockets.cpp -- portable C++ socket wrappers
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define TIMEOUT_MSG "operation timeout"
+
+#include <algorithm>
+#include <atomic>
+#include <cstring>
+#include <mutex>
+
+#include "sockets.h"
+
+namespace net {
+
+/*
+ * Portable constants
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Constants */
+
+#if defined(_WIN32)
+
+const Handle Invalid{INVALID_SOCKET};
+const int Failure{SOCKET_ERROR};
+
+#else
+
+const Handle Invalid{-1};
+const int Failure{-1};
+
+#endif
+
+/* }}} */
+
+/*
+ * Portable functions
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Functions */
+
+#if defined(_WIN32)
+
+namespace {
+
+static std::mutex s_mutex;
+static std::atomic<bool> s_initialized{false};
+
+} // !namespace
+
+#endif // !_WIN32
+
+void init() noexcept
+{
+#if defined(_WIN32)
+	std::lock_guard<std::mutex> lock(s_mutex);
+
+	if (!s_initialized) {
+		s_initialized = true;
+
+		WSADATA wsa;
+		WSAStartup(MAKEWORD(2, 2), &wsa);
+
+		/*
+		 * If SOCKET_WSA_NO_INIT is not set then the user
+		 * must also call finish himself.
+		 */
+#if !defined(SOCKET_NO_AUTO_INIT)
+		atexit(finish);
+#endif
+	}
+#endif
+}
+
+void finish() noexcept
+{
+#if defined(_WIN32)
+	WSACleanup();
+#endif
+}
+
+std::string error(int errn)
+{
+#if defined(_WIN32)
+	LPSTR str = nullptr;
+	std::string errmsg = "Unknown error";
+
+	FormatMessageA(
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,
+		errn,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPSTR)&str, 0, NULL);
+
+
+	if (str) {
+		errmsg = std::string(str);
+		LocalFree(str);
+	}
+
+	return errmsg;
+#else
+	return strerror(errn);
+#endif
+}
+
+std::string error()
+{
+#if defined(_WIN32)
+	return error(WSAGetLastError());
+#else
+	return error(errno);
+#endif
+}
+
+/* }}} */
+
+/*
+ * SSL stuff
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ SSL initialization */
+
+#if !defined(SOCKET_NO_SSL)
+
+namespace ssl {
+
+namespace {
+
+std::mutex mutex;
+std::atomic<bool> initialized{false};
+
+} // !namespace
+
+void finish() noexcept
+{
+	ERR_free_strings();
+}
+
+void init() noexcept
+{
+	std::lock_guard<std::mutex> lock{mutex};
+
+	if (!initialized) {
+		initialized = true;
+
+		SSL_library_init();
+		SSL_load_error_strings();
+		OpenSSL_add_all_algorithms();
+
+#if !defined(SOCKET_NO_AUTO_SSL_INIT)
+		atexit(finish);
+#endif // SOCKET_NO_AUTO_SSL_INIT
+	}
+}
+
+} // !ssl
+
+#endif // SOCKET_NO_SSL
+
+/* }}} */
+
+/*
+ * Error class
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Error */
+
+Error::Error(Code code, std::string function)
+	: m_code{code}
+	, m_function{std::move(function)}
+	, m_error{error()}
+{
+}
+
+Error::Error(Code code, std::string function, int n)
+	: m_code{code}
+	, m_function{std::move(function)}
+	, m_error{error(n)}
+{
+}
+
+Error::Error(Code code, std::string function, std::string error)
+	: m_code{code}
+	, m_function{std::move(function)}
+	, m_error{std::move(error)}
+{
+}
+
+/* }}} */
+
+/*
+ * Predefine addressed to be used
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Addresses */
+
+namespace address {
+
+/* Default domain */
+int Ip::m_default{AF_INET};
+
+Ip::Ip(Type domain) noexcept
+	: m_domain(static_cast<int>(domain))
+{
+	assert(m_domain == AF_INET6 || m_domain == AF_INET);
+
+	if (m_domain == AF_INET6) {
+		std::memset(&m_sin6, 0, sizeof (sockaddr_in6));
+	} else {
+		std::memset(&m_sin, 0, sizeof (sockaddr_in));
+	}
+}
+
+Ip::Ip(const std::string &host, int port, Type domain)
+	: m_domain(static_cast<int>(domain))
+{
+	assert(m_domain == AF_INET6 || m_domain == AF_INET);
+
+	if (host == "*") {
+		if (m_domain == AF_INET6) {
+			std::memset(&m_sin6, 0, sizeof (sockaddr_in6));
+
+			m_length = sizeof (sockaddr_in6);
+			m_sin6.sin6_addr = in6addr_any;
+			m_sin6.sin6_family = AF_INET6;
+			m_sin6.sin6_port = htons(port);
+		} else {
+			std::memset(&m_sin, 0, sizeof (sockaddr_in));
+
+			m_length = sizeof (sockaddr_in);
+			m_sin.sin_addr.s_addr = INADDR_ANY;
+			m_sin.sin_family = AF_INET;
+			m_sin.sin_port = htons(port);
+		}
+	} else {
+		addrinfo hints, *res;
+
+		std::memset(&hints, 0, sizeof (addrinfo));
+		hints.ai_family = domain;
+
+		auto error = getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res);
+		if (error != 0) {
+			throw Error{Error::System, "getaddrinfo", gai_strerror(error)};
+		}
+
+		if (m_domain == AF_INET6) {
+			std::memcpy(&m_sin6, res->ai_addr, res->ai_addrlen);
+		} else {
+			std::memcpy(&m_sin, res->ai_addr, res->ai_addrlen);
+		}
+
+		m_length = res->ai_addrlen;
+		freeaddrinfo(res);
+	}
+}
+
+Ip::Ip(const sockaddr_storage *ss, socklen_t length) noexcept
+	: m_length{length}
+	, m_domain{ss->ss_family}
+{
+	assert(ss->ss_family == AF_INET6 || ss->ss_family == AF_INET);
+
+	if (ss->ss_family == AF_INET6) {
+		std::memcpy(&m_sin6, ss, length);
+	} else if (ss->ss_family == AF_INET) {
+		std::memcpy(&m_sin, ss, length);
+	}
+}
+
+#if !defined(_WIN32)
+
+Local::Local() noexcept
+{
+	std::memset(&m_sun, 0, sizeof (sockaddr_un));
+}
+
+Local::Local(std::string path, bool rm) noexcept
+	: m_path{std::move(path)}
+{
+	/* Silently remove the file even if it fails */
+	if (rm) {
+		::remove(m_path.c_str());
+	}
+
+	/* Copy the path */
+	std::memset(m_sun.sun_path, 0, sizeof (m_sun.sun_path));
+	std::strncpy(m_sun.sun_path, m_path.c_str(), sizeof (m_sun.sun_path) - 1);
+
+	/* Set the parameters */
+	m_sun.sun_family = AF_LOCAL;
+}
+
+Local::Local(const sockaddr_storage *ss, socklen_t length) noexcept
+{
+	assert(ss->ss_family == AF_LOCAL);
+
+	if (ss->ss_family == AF_LOCAL) {
+		std::memcpy(&m_sun, ss, length);
+		m_path = reinterpret_cast<const sockaddr_un &>(m_sun).sun_path;
+	}
+}
+
+#endif // !_WIN32
+
+} // !address
+
+/* }}} */
+
+/*
+ * Select
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Select */
+
+std::vector<ListenerStatus> Select::wait(const ListenerTable &table, int ms)
+{
+	timeval maxwait, *towait;
+	fd_set readset;
+	fd_set writeset;
+
+	FD_ZERO(&readset);
+	FD_ZERO(&writeset);
+
+	Handle max = 0;
+
+	for (const auto &pair : table) {
+		if ((pair.second & Condition::Readable) == Condition::Readable) {
+			FD_SET(pair.first, &readset);
+		}
+		if ((pair.second & Condition::Writable) == Condition::Writable) {
+			FD_SET(pair.first, &writeset);
+		}
+
+		if (pair.first > max) {
+			max = pair.first;
+		}
+	}
+
+	maxwait.tv_sec = 0;
+	maxwait.tv_usec = ms * 1000;
+
+	// Set to nullptr for infinite timeout.
+	towait = (ms < 0) ? nullptr : &maxwait;
+
+	auto error = ::select(max + 1, &readset, &writeset, nullptr, towait);
+	if (error == Failure) {
+		throw Error{Error::System, "select"};
+	}
+	if (error == 0) {
+		throw Error{Error::Timeout, "select", TIMEOUT_MSG};
+	}
+
+	std::vector<ListenerStatus> sockets;
+
+	for (const auto &pair : table) {
+		if (FD_ISSET(pair.first, &readset)) {
+			sockets.push_back(ListenerStatus{pair.first, Condition::Readable});
+		}
+		if (FD_ISSET(pair.first, &writeset)) {
+			sockets.push_back(ListenerStatus{pair.first, Condition::Writable});
+		}
+	}
+
+	return sockets;
+}
+
+/* }}} */
+
+/*
+ * Poll
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Poll */
+
+/*
+ * Poll implementation
+ * ------------------------------------------------------------------
+ */
+
+#if defined(SOCKET_HAVE_POLL)
+
+#if defined(_WIN32)
+#  define poll WSAPoll
+#endif
+
+short Poll::toPoll(Condition condition) const noexcept
+{
+	short result(0);
+
+	if ((condition & Condition::Readable) == Condition::Readable) {
+		result |= POLLIN;
+	}
+	if ((condition & Condition::Writable) == Condition::Writable) {
+		result |= POLLOUT;
+	}
+
+	return result;
+}
+
+Condition Poll::toCondition(short &event) const noexcept
+{
+	Condition condition{Condition::None};
+
+	/*
+	 * Poll implementations mark the socket differently regarding
+	 * the disconnection of a socket.
+	 *
+	 * At least, even if POLLHUP or POLLIN is set, recv() always
+	 * return 0 so we mark the socket as readable.
+	 */
+	if ((event & POLLIN) || (event & POLLHUP)) {
+		condition |= Condition::Readable;
+	}
+	if (event & POLLOUT) {
+		condition |= Condition::Writable;
+	}
+
+	/* Reset event for safety */
+	event = 0;
+
+	return condition;
+}
+
+void Poll::set(const ListenerTable &, Handle h, Condition condition, bool add)
+{
+	if (add) {
+		m_fds.push_back(pollfd{h, toPoll(condition), 0});
+	} else {
+		auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const pollfd &pfd) {
+			return pfd.fd == h;
+		});
+
+		it->events |= toPoll(condition);
+	}
+}
+
+void Poll::unset(const ListenerTable &, Handle h, Condition condition, bool remove)
+{
+	auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const pollfd &pfd) {
+		return pfd.fd == h;
+	});
+
+	if (remove) {
+		m_fds.erase(it);
+	} else {
+		it->events &= ~(toPoll(condition));
+	}
+}
+
+std::vector<ListenerStatus> Poll::wait(const ListenerTable &, int ms)
+{
+	auto result = poll(m_fds.data(), m_fds.size(), ms);
+	if (result == 0) {
+		throw Error{Error::Timeout, "select", TIMEOUT_MSG};
+	}
+	if (result < 0) {
+		throw Error{Error::System, "poll"};
+	}
+
+	std::vector<ListenerStatus> sockets;
+	for (auto &fd : m_fds) {
+		if (fd.revents != 0) {
+			sockets.push_back(ListenerStatus{fd.fd, toCondition(fd.revents)});
+		}
+	}
+
+	return sockets;
+}
+
+#endif // !SOCKET_HAVE_POLL
+
+/* }}} */
+
+/*
+ * Epoll implementation
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Epoll */
+
+#if defined(SOCKET_HAVE_EPOLL)
+
+uint32_t Epoll::toEpoll(Condition condition) const noexcept
+{
+	uint32_t events = 0;
+
+	if ((condition & Condition::Readable) == Condition::Readable) {
+		events |= EPOLLIN;
+	}
+	if ((condition & Condition::Writable) == Condition::Writable) {
+		events |= EPOLLOUT;
+	}
+
+	return events;
+}
+
+Condition Epoll::toCondition(uint32_t events) const noexcept
+{
+	Condition condition{Condition::None};
+
+	if ((events & EPOLLIN) || (events & EPOLLHUP)) {
+		condition |= Condition::Readable;
+	}
+	if (events & EPOLLOUT) {
+		condition |= Condition::Writable;
+	}
+
+	return condition;
+}
+
+void Epoll::update(Handle h, int op, int eflags)
+{
+	epoll_event ev;
+
+	std::memset(&ev, 0, sizeof (epoll_event));
+
+	ev.events = eflags;
+	ev.data.fd = h;
+
+	if (epoll_ctl(m_handle, op, h, &ev) < 0) {
+		throw Error{Error::System, "epoll_ctl"};
+	}
+}
+
+Epoll::Epoll()
+	: m_handle{epoll_create1(0)}
+{
+	if (m_handle < 0) {
+		throw Error{Error::System, "epoll_create"};
+	}
+}
+
+Epoll::~Epoll()
+{
+	close(m_handle);
+}
+
+/*
+ * For set and unset, we need to apply the whole flags required, so if the socket
+ * was set to Connection::Readable and user add Connection::Writable, we must
+ * place both.
+ */
+void Epoll::set(const ListenerTable &table, Handle sc, Condition condition, bool add)
+{
+	if (add) {
+		update(sc, EPOLL_CTL_ADD, toEpoll(condition));
+		m_events.resize(m_events.size() + 1);
+	} else {
+		update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) | condition));
+	}
+}
+
+/*
+ * Unset is a bit complicated case because Listener tells us which
+ * flag to remove but to update epoll descriptor we need to pass
+ * the effective flags that we want to be applied.
+ *
+ * So we put the same flags that are currently effective and remove the
+ * requested one.
+ */
+void Epoll::unset(const ListenerTable &table, Handle sc, Condition condition, bool remove)
+{
+	if (remove) {
+		update(sc, EPOLL_CTL_DEL, 0);
+		m_events.resize(m_events.size() - 1);
+	} else {
+		update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) & ~(condition)));
+	}
+}
+
+std::vector<ListenerStatus> Epoll::wait(const ListenerTable &, int ms)
+{
+	int ret = epoll_wait(m_handle, m_events.data(), m_events.size(), ms);
+	std::vector<ListenerStatus> result;
+
+	if (ret == 0) {
+		throw Error{Error::Timeout, "epoll_wait", TIMEOUT_MSG};
+	}
+	if (ret < 0) {
+		throw Error{Error::System, "epoll_wait"};
+	}
+
+	for (int i = 0; i < ret; ++i) {
+		result.push_back(ListenerStatus{m_events[i].data.fd, toCondition(m_events[i].events)});
+	}
+
+	return result;
+}
+
+#endif // !SOCKET_HAVE_EPOLL
+
+/* }}} */
+
+/*
+ * Kqueue implementation
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Kqueue */
+
+#if defined(SOCKET_HAVE_KQUEUE)
+
+Kqueue::Kqueue()
+	: m_handle(kqueue())
+{
+	if (m_handle < 0) {
+		throw Error{Error::System, "kqueue"};
+	}
+}
+
+Kqueue::~Kqueue()
+{
+	close(m_handle);
+}
+
+void Kqueue::update(Handle h, int filter, int kflags)
+{
+	struct kevent ev;
+
+	EV_SET(&ev, h, filter, kflags, 0, 0, nullptr);
+
+	if (kevent(m_handle, &ev, 1, nullptr, 0, nullptr) < 0) {
+		throw Error{Error::System, "kevent"};
+	}
+}
+
+void Kqueue::set(const ListenerTable &, Handle h, Condition condition, bool add)
+{
+	if ((condition & Condition::Readable) == Condition::Readable) {
+		update(h, EVFILT_READ, EV_ADD | EV_ENABLE);
+	}
+	if ((condition & Condition::Writable) == Condition::Writable) {
+		update(h, EVFILT_WRITE, EV_ADD | EV_ENABLE);
+	}
+
+	if (add) {
+		m_result.resize(m_result.size() + 1);
+	}
+}
+
+void Kqueue::unset(const ListenerTable &, Handle h, Condition condition, bool remove)
+{
+	if ((condition & Condition::Readable) == Condition::Readable) {
+		update(h, EVFILT_READ, EV_DELETE);
+	}
+	if ((condition & Condition::Writable) == Condition::Writable) {
+		update(h, EVFILT_WRITE, EV_DELETE);
+	}
+
+	if (remove) {
+		m_result.resize(m_result.size() - 1);
+	}
+}
+
+std::vector<ListenerStatus> Kqueue::wait(const ListenerTable &, int ms)
+{
+	std::vector<ListenerStatus> sockets;
+	timespec ts = { 0, 0 };
+	timespec *pts = (ms <= 0) ? nullptr : &ts;
+
+	ts.tv_sec = ms / 1000;
+	ts.tv_nsec = (ms % 1000) * 1000000;
+
+	int nevents = kevent(m_handle, nullptr, 0, &m_result[0], m_result.capacity(), pts);
+
+	if (nevents == 0) {
+		throw Error{Error::Timeout, "kevent", TIMEOUT_MSG};
+	}
+	if (nevents < 0) {
+		throw Error{Error::System, "kevent"};
+	}
+
+	for (int i = 0; i < nevents; ++i) {
+		sockets.push_back(ListenerStatus{
+			static_cast<Handle>(m_result[i].ident),
+			m_result[i].filter == EVFILT_READ ? Condition::Readable : Condition::Writable
+		});
+	}
+
+	return sockets;
+}
+
+#endif // !SOCKET_HAVE_KQUEUE
+
+/* }}} */
+
+} // !net
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Socket/sockets.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,4063 @@
+/*
+ * sockets.h -- portable C++ socket wrappers
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SOCKETS_H_
+#define _SOCKETS_H_
+
+/**
+ * @file sockets.h
+ * @brief Portable socket abstraction
+ *
+ * # Introduction
+ *
+ * This file is a portable networking library.
+ *
+ * ## Options
+ *
+ * The user may set the following variables before compiling these files:
+ *
+ * ### General options
+ *
+ * - **SOCKET_NO_AUTO_INIT**: (bool) Set to 0 if you don't want Socket class to
+ * automatically calls net::init function and net::finish functions.
+ * - **SOCKET_NO_SSL**: (bool) Set to 0 if you don't have access to OpenSSL library.
+ * - **SOCKET_NO_AUTO_SSL_INIT**: (bool) Set to 0 if you don't want Socket class with Tls to automatically init
+ * the OpenSSL library. You will need to call net::ssl::init and net::ssl::finish.
+ *
+ * ### Options for Listener class
+ *
+ * Feature detection, multiple implementations may be avaible, for example, Linux has poll, select and epoll.
+ *
+ * We assume that `select(2)` is always available.
+ *
+ * Of course, you can set the variables yourself if you test it with your build system.
+ *
+ * - **SOCKET_HAVE_POLL**: Defined on all BSD, Linux. Also defined on Windows
+ *   if _WIN32_WINNT is set to 0x0600 or greater.
+ * - **SOCKET_HAVE_KQUEUE**: Defined on all BSD and Apple.
+ * - **SOCKET_HAVE_EPOLL**: Defined on Linux only.
+ * - **SOCKET_DEFAULT_BACKEND**: Which backend to use (e.g. `Select`).
+ *
+ * The preference priority is ordered from left to right.
+ *
+ * | System        | Backend                 | Class name   |
+ * |---------------|-------------------------|--------------|
+ * | Linux         | epoll(7)                | Epoll        |
+ * | *BSD          | kqueue(2)               | Kqueue       |
+ * | Windows       | poll(2), select(2)      | Poll, Select |
+ * | Mac OS X      | kqueue(2)               | Kqueue       |
+ */
+
+#if defined(_WIN32)
+#  if _WIN32_WINNT >= 0x0600 && !defined(SOCKET_HAVE_POLL)
+#    define SOCKET_HAVE_POLL
+#  endif
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+#  if !defined(SOCKET_HAVE_KQUEUE)
+#    define SOCKET_HAVE_KQUEUE
+#  endif
+#  if !defined(SOCKET_HAVE_POLL)
+#    define SOCKET_HAVE_POLL
+#  endif
+#elif defined(__linux__)
+#  if !defined(SOCKET_HAVE_EPOLL)
+#    define SOCKET_HAVE_EPOLL
+#  endif
+#  if !defined(SOCKET_HAVE_POLL)
+#    define SOCKET_HAVE_POLL
+#  endif
+#endif
+
+/*
+ * Define SOCKET_DEFAULT_BACKEND
+ * ------------------------------------------------------------------
+ */
+
+/**
+ * Defines the default Listener backend to use.
+ *
+ * @note Do not rely on the value shown in doxygen.
+ */
+#if defined(_WIN32)
+#  if !defined(SOCKET_DEFAULT_BACKEND)
+#    if defined(SOCKET_HAVE_POLL)
+#      define SOCKET_DEFAULT_BACKEND Poll
+#    else
+#      define SOCKET_DEFAULT_BACKEND Select
+#    endif
+#  endif
+#elif defined(__linux__)
+#  include <sys/epoll.h>
+
+#  if !defined(SOCKET_DEFAULT_BACKEND)
+#    define SOCKET_DEFAULT_BACKEND Epoll
+#  endif
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#  include <sys/types.h>
+#  include <sys/event.h>
+#  include <sys/time.h>
+
+#  if !defined(SOCKET_DEFAULT_BACKEND)
+#    define SOCKET_DEFAULT_BACKEND Kqueue
+#  endif
+#else
+#  if !defined(SOCKET_DEFAULT_BACKEND)
+#    define SOCKET_DEFAULT_BACKEND Select
+#  endif
+#endif
+
+#if defined(SOCKET_HAVE_POLL) && !defined(_WIN32)
+#  include <poll.h>
+#endif
+
+/*
+ * Headers to include
+ * ------------------------------------------------------------------
+ */
+
+#if defined(_WIN32)
+#  include <cstdlib>
+
+#  include <WinSock2.h>
+#  include <WS2tcpip.h>
+#else
+#  include <cerrno>
+
+#  include <sys/ioctl.h>
+#  include <sys/types.h>
+#  include <sys/socket.h>
+#  include <sys/un.h>
+
+#  include <arpa/inet.h>
+
+#  include <netinet/in.h>
+#  include <netinet/tcp.h>
+
+#  include <fcntl.h>
+#  include <netdb.h>
+#  include <unistd.h>
+#endif
+
+#if !defined(SOCKET_NO_SSL)
+#  include <openssl/err.h>
+#  include <openssl/evp.h>
+#  include <openssl/ssl.h>
+#endif
+
+#include <cassert>
+#include <chrono>
+#include <cstdlib>
+#include <cstring>
+#include <exception>
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+/**
+ * General network namespace.
+ */
+namespace net {
+
+/*
+ * Portables types
+ * ------------------------------------------------------------------
+ *
+ * The following types are defined differently between Unix and Windows.
+ */
+
+/* {{{ Protocols */
+
+#if defined(_WIN32)
+
+/**
+ * Socket type, SOCKET.
+ */
+using Handle	= SOCKET;
+
+/**
+ * Argument to pass to set.
+ */
+using ConstArg	= const char *;
+
+/**
+ * Argument to pass to get.
+ */
+using Arg	= char *;
+
+#else
+
+/**
+ * Socket type, int.
+ */
+using Handle	= int;
+
+/**
+ * Argument to pass to set.
+ */
+using ConstArg	= const void *;
+
+/**
+ * Argument to pass to get.
+ */
+using Arg	= void *;
+
+#endif
+
+/* }}} */
+
+/*
+ * Portable constants
+ * ------------------------------------------------------------------
+ *
+ * These constants are needed to check functions return codes, they are rarely needed in end user code.
+ */
+
+/* {{{ Constants */
+
+/*
+ * The following constants are defined differently from Unix
+ * to Windows.
+ */
+#if defined(_WIN32)
+
+/**
+ * Socket creation failure or invalidation.
+ */
+extern const Handle Invalid;
+
+/**
+ * Socket operation failure.
+ */
+extern const int Failure;
+
+#else
+
+/**
+ * Socket creation failure or invalidation.
+ */
+extern const int Invalid;
+
+/**
+ * Socket operation failure.
+ */
+extern const int Failure;
+
+#endif
+
+#if !defined(SOCKET_NO_SSL)
+
+namespace ssl {
+
+/**
+ * @enum Method
+ * @brief Which OpenSSL method to use.
+ */
+enum Method {
+	Tlsv1,		//!< TLS v1.2 (recommended)
+	Sslv3		//!< SSLv3
+};
+
+} // !ssl
+
+#endif
+
+/* }}} */
+
+/*
+ * Portable functions
+ * ------------------------------------------------------------------
+ *
+ * The following free functions can be used to initialize the library or to get the last system error.
+ */
+
+/* {{{ Functions */
+
+/**
+ * Initialize the socket library. Except if you defined SOCKET_NO_AUTO_INIT, you don't need to call this
+ * function manually.
+ */
+void init() noexcept;
+
+/**
+ * Close the socket library.
+ */
+void finish() noexcept;
+
+#if !defined(SOCKET_NO_SSL)
+
+/**
+ * OpenSSL namespace.
+ */
+namespace ssl {
+
+/**
+ * Initialize the OpenSSL library. Except if you defined SOCKET_NO_AUTO_SSL_INIT, you don't need to call this function
+ * manually.
+ */
+void init() noexcept;
+
+/**
+ * Close the OpenSSL library.
+ */
+void finish() noexcept;
+
+} // !ssl
+
+#endif // SOCKET_NO_SSL
+
+/**
+ * Get the last socket system error. The error is set from errno or from
+ * WSAGetLastError on Windows.
+ *
+ * @return a string message
+ */
+std::string error();
+
+/**
+ * Get the last system error.
+ *
+ * @param errn the error number (errno or WSAGetLastError)
+ * @return the error
+ */
+std::string error(int errn);
+
+/* }}} */
+
+/*
+ * Error class
+ * ------------------------------------------------------------------
+ *
+ * This is the main exception thrown on socket operations.
+ */
+
+/* {{{ Error */
+
+/**
+ * @class Error
+ * @brief Base class for sockets error
+ */
+class Error : public std::exception {
+public:
+	/**
+	 * @enum Code
+	 * @brief Which kind of error
+	 */
+	enum Code {
+		Timeout,		///!< The action did timeout
+		System,			///!< There is a system error
+		Other			///!< Other custom error
+	};
+
+private:
+	Code m_code;
+	std::string m_function;
+	std::string m_error;
+
+public:
+	/**
+	 * Constructor that use the last system error.
+	 *
+	 * @param code which kind of error
+	 * @param function the function name
+	 */
+	Error(Code code, std::string function);
+
+	/**
+	 * Constructor that use the system error set by the user.
+	 *
+	 * @param code which kind of error
+	 * @param function the function name
+	 * @param error the error
+	 */
+	Error(Code code, std::string function, int error);
+
+	/**
+	 * Constructor that set the error specified by the user.
+	 *
+	 * @param code which kind of error
+	 * @param function the function name
+	 * @param error the error
+	 */
+	Error(Code code, std::string function, std::string error);
+
+	/**
+	 * Get which function has triggered the error.
+	 *
+	 * @return the function name (e.g connect)
+	 */
+	inline const std::string &function() const noexcept
+	{
+		return m_function;
+	}
+
+	/**
+	 * The error code.
+	 *
+	 * @return the code
+	 */
+	inline Code code() const noexcept
+	{
+		return m_code;
+	}
+
+	/**
+	 * Get the error (only the error content).
+	 *
+	 * @return the error
+	 */
+	const char *what() const noexcept
+	{
+		return m_error.c_str();
+	}
+};
+
+/* }}} */
+
+/*
+ * State class
+ * ------------------------------------------------------------------
+ *
+ * To facilitate higher-level stuff, the socket has a state.
+ */
+
+/* {{{ State */
+
+/**
+ * @enum State
+ * @brief Current socket state.
+ */
+enum class State {
+	Open,			//!< Socket is open
+	Bound,			//!< Socket is bound to an address
+	Connecting,		//!< The connection is in progress
+	Connected,		//!< Connection is complete
+	Accepted,		//!< Socket has been accepted (client)
+	Accepting,		//!< The client acceptation is in progress
+	Closed,			//!< The socket has been closed
+	Disconnected,		//!< The connection was lost
+};
+
+/* }}} */
+
+/*
+ * Action enum
+ * ------------------------------------------------------------------
+ *
+ * Defines the pending operation.
+ */
+
+/* {{{ Action */
+
+/**
+ * @enum Action
+ * @brief Define the current operation that must complete.
+ *
+ * Some operations like accept, connect, recv or send must sometimes do several round-trips to complete and the socket
+ * action is set with that enumeration. The user is responsible of calling accept, connect send or recv until the
+ * operation is complete.
+ *
+ * Note: the user must wait for the appropriate condition in Socket::condition to check if the required condition is
+ * met.
+ *
+ * It is important to complete the operation in the correct order because protocols like Tls may require to continue
+ * re-negociating when calling Socket::send or Socket::Recv.
+ */
+enum class Action {
+	None,		//!< No action is required, socket is ready
+	Accept,		//!< The socket is not yet accepted, caller must call accept() again
+	Connect,	//!< The socket is not yet connected, caller must call connect() again
+	Receive,	//!< The received operation has not succeeded yet, caller must call recv() or recvfrom() again
+	Send		//!< The send operation has not succeded yet, caller must call send() or sendto() again
+};
+
+/* }}} */
+
+/*
+ * Condition enum
+ * ------------------------------------------------------------------
+ *
+ * Defines if we must wait for reading or writing.
+ */
+
+/* {{{ Condition */
+
+/**
+ * @enum Condition
+ * @brief Define the required condition for the socket.
+ *
+ * As explained in Action enumeration, some operations required to be called several times, before calling these
+ * operations, the user must wait the socket to be readable or writable. This can be checked with Socket::condition.
+ */
+enum class Condition {
+	None,			//!< No condition is required
+	Readable = (1 << 0),	//!< The socket must be readable
+	Writable = (1 << 1)	//!< The socket must be writable
+};
+
+/**
+ * Apply bitwise XOR.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+constexpr Condition operator^(Condition v1, Condition v2) noexcept
+{
+	return static_cast<Condition>(static_cast<int>(v1) ^ static_cast<int>(v2));
+}
+
+/**
+ * Apply bitwise AND.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+constexpr Condition operator&(Condition v1, Condition v2) noexcept
+{
+	return static_cast<Condition>(static_cast<int>(v1) & static_cast<int>(v2));
+}
+
+/**
+ * Apply bitwise OR.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+constexpr Condition operator|(Condition v1, Condition v2) noexcept
+{
+	return static_cast<Condition>(static_cast<int>(v1) | static_cast<int>(v2));
+}
+
+/**
+ * Apply bitwise NOT.
+ *
+ * @param v the value
+ * @return the complement
+ */
+constexpr Condition operator~(Condition v) noexcept
+{
+	return static_cast<Condition>(~static_cast<int>(v));
+}
+
+/**
+ * Assign bitwise OR.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+inline Condition &operator|=(Condition &v1, Condition v2) noexcept
+{
+	v1 = static_cast<Condition>(static_cast<int>(v1) | static_cast<int>(v2));
+
+	return v1;
+}
+
+/**
+ * Assign bitwise AND.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+inline Condition &operator&=(Condition &v1, Condition v2) noexcept
+{
+	v1 = static_cast<Condition>(static_cast<int>(v1) & static_cast<int>(v2));
+
+	return v1;
+}
+
+/**
+ * Assign bitwise XOR.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+inline Condition &operator^=(Condition &v1, Condition v2) noexcept
+{
+	v1 = static_cast<Condition>(static_cast<int>(v1) ^ static_cast<int>(v2));
+
+	return v1;
+}
+
+/* }}} */
+
+/*
+ * Base Socket class
+ * ------------------------------------------------------------------
+ *
+ * This base class has operations that are common to all types of sockets but you usually instanciate
+ * a SocketTcp or SocketUdp
+ */
+
+/* {{{ Socket */
+
+/**
+ * @class Socket
+ * @brief Base socket class for socket operations.
+ *
+ * **Important:** When using non-blocking sockets, some considerations must be taken. See the implementation of the
+ * underlying protocol for more details.
+ *
+ * @see protocol::Tls
+ * @see protocol::Tcp
+ * @see protocol::Udp
+ */
+template <typename Address, typename Protocol>
+class Socket {
+private:
+	Protocol m_proto;
+	State m_state{State::Closed};
+	Action m_action{Action::None};
+	Condition m_condition{Condition::None};
+
+protected:
+	/**
+	 * The native handle.
+	 */
+	Handle m_handle{Invalid};
+
+public:
+	/**
+	 * Create a socket handle.
+	 *
+	 * This is the primary function and the only one that creates the socket handle, all other constructors
+	 * are just overloaded functions.
+	 *
+	 * @param domain the domain AF_*
+	 * @param type the type SOCK_*
+	 * @param protocol the protocol
+	 * @param iface the implementation
+	 * @throw net::Error on errors
+	 * @post state is set to Open
+	 * @post handle is not set to Invalid
+	 */
+	Socket(int domain, int type, int protocol, Protocol iface = {})
+		: m_proto(std::move(iface))
+	{
+#if !defined(SOCKET_NO_AUTO_INIT)
+		init();
+#endif
+		m_handle = ::socket(domain, type, protocol);
+
+		if (m_handle == Invalid) {
+			throw Error{Error::System, "socket"};
+		}
+
+		m_proto.create(*this);
+		m_state = State::Open;
+
+		assert(m_handle != Invalid);
+	}
+
+	/**
+	 * This tries to create a socket.
+	 *
+	 * Domain and type are determined by the Address and Protocol object.
+	 *
+	 * @param protocol the protocol
+	 * @param address which type of address
+	 * @throw net::Error on errors
+	 */
+	explicit inline Socket(Protocol protocol = {}, const Address &address = {})
+		: Socket{address.domain(), protocol.type(), 0, std::move(protocol)}
+	{
+	}
+
+	/**
+	 * Construct a socket with an already created descriptor.
+	 *
+	 * @param handle the native descriptor
+	 * @param state specify the socket state
+	 * @param protocol the type of socket implementation
+	 * @post action is set to None
+	 * @post condition is set to None
+	 */
+	explicit inline Socket(Handle handle, State state = State::Closed, Protocol protocol = {}) noexcept
+		: m_proto(std::move(protocol))
+		, m_state{state}
+		, m_handle{handle}
+	{
+		assert(m_action == Action::None);
+		assert(m_condition == Condition::None);
+	}
+
+	/**
+	 * Create an invalid socket. Can be used when you cannot instanciate the socket immediately.
+	 */
+	explicit inline Socket(std::nullptr_t) noexcept
+		: m_handle{Invalid}
+	{
+	}
+
+	/**
+	 * Copy constructor deleted.
+	 */
+	Socket(const Socket &) = delete;
+
+	/**
+	 * Transfer ownership from other to this.
+	 *
+	 * @param other the other socket
+	 */
+	inline Socket(Socket &&other) noexcept
+		: m_proto(std::move(other.m_proto))
+		, m_state{other.m_state}
+		, m_action{other.m_action}
+		, m_condition{other.m_condition}
+		, m_handle{other.m_handle}
+	{
+		/* Invalidate other */
+		other.m_handle = Invalid;
+		other.m_state = State::Closed;
+		other.m_action = Action::None;
+		other.m_condition = Condition::None;
+	}
+
+	/**
+	 * Default destructor.
+	 */
+	virtual ~Socket()
+	{
+		close();
+	}
+
+	/**
+	 * Access the implementation.
+	 *
+	 * @return the implementation
+	 * @warning use this function with care
+	 */
+	inline const Protocol &protocol() const noexcept
+	{
+		return m_proto;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the implementation
+	 */
+	inline Protocol &protocol() noexcept
+	{
+		return m_proto;
+	}
+
+	/**
+	 * Get the current socket state.
+	 *
+	 * @return the state
+	 */
+	inline State state() const noexcept
+	{
+		return m_state;
+	}
+
+	/**
+	 * Change the current socket state.
+	 *
+	 * @param state the new state
+	 * @warning only implementations should call this function
+	 */
+	inline void setState(State state) noexcept
+	{
+		m_state = state;
+	}
+
+	/**
+	 * Get the pending operation.
+	 *
+	 * @return the action to complete before continuing
+	 * @note usually only needed in non-blocking sockets
+	 */
+	inline Action action() const noexcept
+	{
+		return m_action;
+	}
+
+	/**
+	 * Change the pending operation.
+	 *
+	 * @param action the action
+	 * @warning you should not call this function yourself
+	 */
+	inline void setAction(Action action) noexcept
+	{
+		m_action = action;
+	}
+
+	/**
+	 * Get the condition to wait for.
+	 *
+	 * @return the condition
+	 */
+	inline Condition condition() const noexcept
+	{
+		return m_condition;
+	}
+
+	/**
+	 * Change the condition required.
+	 *
+	 * @param condition the condition
+	 * @warning you should not call this function yourself
+	 */
+	inline void setCondition(Condition condition) noexcept
+	{
+		m_condition = condition;
+	}
+
+	/**
+	 * Set an option for the socket. Wrapper of setsockopt(2).
+	 *
+	 * @param level the setting level
+	 * @param name the name
+	 * @param arg the value
+	 * @throw net::Error on errors
+	 */
+	template <typename Argument>
+	void set(int level, int name, const Argument &arg)
+	{
+		if (setsockopt(m_handle, level, name, (ConstArg)&arg, sizeof (arg)) == Failure) {
+			throw Error{Error::System, "set"};
+		}
+	}
+
+	/**
+	 * Object-oriented option setter.
+	 *
+	 * The object must have `set(Socket<Address, Protocol> &) const`.
+	 *
+	 * @param option the option
+	 * @throw net::Error on errors
+	 */
+	template <typename Option>
+	inline void set(const Option &option)
+	{
+		option.set(*this);
+	}
+
+	/**
+	 * Get an option for the socket. Wrapper of getsockopt(2).
+	 *
+	 * @param level the setting level
+	 * @param name the name
+	 * @throw net::Error on errors
+	 */
+	template <typename Argument>
+	Argument get(int level, int name)
+	{
+		Argument desired, result{};
+		socklen_t size = sizeof (result);
+
+		if (getsockopt(m_handle, level, name, (Arg)&desired, &size) == Failure) {
+			throw Error{Error::System, "get"};
+		}
+
+		std::memcpy(&result, &desired, size);
+
+		return result;
+	}
+
+	/**
+	 * Object-oriented option getter.
+	 *
+	 * The object must have `T get(Socket<Address, Protocol> &) const`, T can be any type and it is the value
+	 * returned from this function.
+	 *
+	 * @return the same value as get() in the option
+	 * @throw net::Error on errors
+	 */
+	template <typename Option>
+	inline auto get() -> decltype(std::declval<Option>().get(*this))
+	{
+		return Option{}.get(*this);
+	}
+
+	/**
+	 * Get the native handle.
+	 *
+	 * @return the handle
+	 * @warning Not portable
+	 */
+	inline Handle handle() const noexcept
+	{
+		return m_handle;
+	}
+
+	/**
+	 * Bind using a native address.
+	 *
+	 * @param address the address
+	 * @param length the size
+	 * @pre state must not be Bound
+	 * @throw net::Error on errors
+	 */
+	void bind(const sockaddr *address, socklen_t length)
+	{
+		assert(m_state != State::Bound);
+
+		if (::bind(m_handle, address, length) == Failure) {
+			throw Error{Error::System, "bind"};
+		}
+
+		m_state = State::Bound;
+	}
+
+	/**
+	 * Overload that takes an address.
+	 *
+	 * @param address the address
+	 * @throw net::Error on errors
+	 */
+	inline void bind(const Address &address)
+	{
+		bind(address.address(), address.length());
+	}
+
+	/**
+	 * Listen for pending connection.
+	 *
+	 * @param max the maximum number
+	 * @pre state must be Bound
+	 * @throw net::Error on errors
+	 */
+	inline void listen(int max = 128)
+	{
+		assert(m_state == State::Bound);
+
+		if (::listen(this->m_handle, max) == Failure) {
+			throw Error{Error::System, "listen"};
+		}
+	}
+
+	/**
+	 * Connect to the address.
+	 *
+	 * If connection cannot be established immediately, connect with no argument must be called again. See
+	 * the underlying protocol for more information.
+	 *
+	 * @pre state must be State::Open
+	 * @param address the address
+	 * @param length the the address length
+	 * @throw net::Error on errors
+	 * @post state is set to State::Connecting or State::Connected
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	void connect(const sockaddr *address, socklen_t length)
+	{
+		assert(m_state == State::Open);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		m_proto.connect(*this, address, length);
+
+		assert((m_state == State::Connected  && m_action == Action::None    && m_condition == Condition::None) ||
+		       (m_state == State::Connecting && m_action == Action::Connect && m_condition != Condition::None));
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * Effectively call connect(address.address(), address.length());
+	 *
+	 * @param address the address
+	 */
+	inline void connect(const Address &address)
+	{
+		connect(address.address(), address.length());
+	}
+
+	/**
+	 * Continue the connection, only required with non-blocking sockets.
+	 *
+	 * @pre state must be State::Connecting
+	 * @throw net::Error on errors
+	 */
+	void connect()
+	{
+		assert(m_state == State::Connecting);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		m_proto.connect(*this);
+
+		assert((m_state == State::Connected  && m_action == Action::None    && m_condition == Condition::None) ||
+		       (m_state == State::Connecting && m_action == Action::Connect && m_condition != Condition::None));
+	}
+
+	/**
+	 * Accept a new client. If there are no pending connection, throws an error.
+	 *
+	 * If the client cannot be accepted immediately, the client is returned and accept with no arguments
+	 * must be called on it. See the underlying protocol for more information.
+	 *
+	 * @pre state must be State::Bound
+	 * @param info the address where to store client's information (optional)
+	 * @return the new socket
+	 * @throw Error on errors
+	 * @post returned client's state is set to State::Accepting or State::Accepted
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	Socket<Address, Protocol> accept(Address *info)
+	{
+		assert(m_state == State::Bound);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		sockaddr_storage storage;
+		socklen_t length = sizeof (storage);
+
+		Socket<Address, Protocol> sc = m_proto.accept(*this, reinterpret_cast<sockaddr *>(&storage), &length);
+
+		if (info) {
+			*info = Address{&storage, length};
+		}
+
+		/* Master do not change */
+		assert(m_state == State::Bound);
+		assert(m_action == Action::None);
+		assert(m_condition == Condition::None);
+
+		/* Client */
+		assert(
+			(sc.state() == State::Accepting && sc.action() == Action::Accept && sc.condition() != Condition::None) ||
+			(sc.state() == State::Accepted  && sc.action() == Action::None   && sc.condition() == Condition::None)
+		);
+
+		return sc;
+	}
+
+	/**
+	 * Continue the accept process on this client. This function must be called only when the socket is
+	 * ready to be readable or writable! (see condition).
+	 *
+	 * @pre state must be State::Accepting
+	 * @throw Error on errors
+	 * @post if connection is complete, state is changed to State::Accepted, action and condition are unset
+	 * @post if connection is still in progress, condition is set
+	 */
+	void accept()
+	{
+		assert(m_state == State::Accepting);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		m_proto.accept(*this);
+
+		assert(
+			(m_state == State::Accepting && m_action == Action::Accept && m_condition != Condition::None) ||
+			(m_state == State::Accepted  && m_action == Action::None   && m_condition == Condition::None)
+		);
+	}
+
+	/**
+	 * Get the local name. This is a wrapper of getsockname().
+	 *
+	 * @return the address
+	 * @throw Error on failures
+	 * @pre state() must not be State::Closed
+	 */
+	Address address() const
+	{
+		assert(m_state != State::Closed);
+
+		sockaddr_storage ss;
+		socklen_t length = sizeof (sockaddr_storage);
+
+		if (::getsockname(m_handle, (sockaddr *)&ss, &length) == Failure) {
+			throw Error{Error::System, "getsockname"};
+		}
+
+		return Address(&ss, length);
+	}
+
+	/**
+	 * Receive some data.
+	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
+	 * If action is set to Action::None and result is set to 0, disconnection occured.
+	 *
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @pre action must not be Action::Send
+	 * @return the number of bytes received or 0
+	 * @throw Error on error
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	unsigned recv(void *data, unsigned length)
+	{
+		assert(m_action != Action::Send);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		return m_proto.recv(*this, data, length);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param count the number of bytes to receive
+	 * @return the string
+	 * @throw Error on error
+	 */
+	inline std::string recv(unsigned count)
+	{
+		std::string result;
+
+		result.resize(count);
+		auto n = recv(const_cast<char *>(result.data()), count);
+		result.resize(n);
+
+		return result;
+	}
+
+	/**
+	 * Send some data.
+	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
+	 * @param data the data buffer
+	 * @param length the buffer length
+	 * @return the number of bytes sent or 0
+	 * @pre action() must not be Flag::Receive
+	 * @throw Error on error
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	unsigned send(const void *data, unsigned length)
+	{
+		assert(m_action != Action::Receive);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		return m_proto.send(*this, data, length);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the string to send
+	 * @return the number of bytes sent
+	 * @throw Error on error
+	 */
+	inline unsigned send(const std::string &data)
+	{
+		return send(data.c_str(), data.size());
+	}
+
+	/**
+	 * Send data to an end point.
+	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
+	 * @param data the buffer
+	 * @param length the buffer length
+	 * @param address the client address
+	 * @param addrlen the address length
+	 * @return the number of bytes sent
+	 * @throw net::Error on errors
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	inline unsigned sendto(const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
+	{
+		return m_proto.sendto(*this, data, length, address, addrlen);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the buffer
+	 * @param length the buffer length
+	 * @param address the destination
+	 * @return the number of bytes sent
+	 * @throw net::Error on errors
+	 */
+	inline unsigned sendto(const void *data, unsigned length, const Address &address)
+	{
+		return sendto(data, length, address.address(), address.length());
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the data
+	 * @param address the address
+	 * @return the number of bytes sent
+	 * @throw net:;Error on errors
+	 */
+	inline unsigned sendto(const std::string &data, const Address &address)
+	{
+		return sendto(data.c_str(), data.length(), address);
+	}
+
+	/**
+	 * Receive data from an end point.
+	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @param address the address destination
+	 * @param addrlen the address length (in/out)
+	 * @return the number of bytes received
+	 * @throw net::Error on errors
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	inline unsigned recvfrom(void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
+	{
+		return m_proto.recvfrom(*this, data, length, address, addrlen);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @param info the address destination
+	 * @return the number of bytes received
+	 * @throw net::Error on errors
+	 */
+	inline unsigned recvfrom(void *data, unsigned length, Address *info = nullptr)
+	{
+		sockaddr_storage storage;
+		socklen_t addrlen = sizeof (sockaddr_storage);
+
+		auto n = recvfrom(data, length, reinterpret_cast<sockaddr *>(&storage), &addrlen);
+
+		if (info && n != 0) {
+			*info = Address{&storage, addrlen};
+		}
+
+		return n;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param count the maximum number of bytes to receive
+	 * @param info the client information
+	 * @return the string
+	 * @throw net::Error on errors
+	 */
+	std::string recvfrom(unsigned count, Address *info = nullptr)
+	{
+		std::string result;
+
+		result.resize(count);
+		auto n = recvfrom(const_cast<char *>(result.data()), count, info);
+		result.resize(n);
+
+		return result;
+	}
+
+	/**
+	 * Close the socket.
+	 *
+	 * Automatically called from the destructor.
+	 */
+	void close()
+	{
+		if (m_handle != Invalid) {
+#if defined(_WIN32)
+			::closesocket(m_handle);
+#else
+			::close(m_handle);
+#endif
+			m_handle = Invalid;
+		}
+
+		m_state = State::Closed;
+		m_action = Action::None;
+		m_condition = Condition::None;
+	}
+
+	/**
+	 * Assignment operator forbidden.
+	 *
+	 * @return *this
+	 */
+	Socket &operator=(const Socket &) = delete;
+
+	/**
+	 * Transfer ownership from other to this. The other socket is left
+	 * invalid and will not be closed.
+	 *
+	 * @param other the other socket
+	 * @return this
+	 */
+	Socket &operator=(Socket &&other) noexcept
+	{
+		m_handle = other.m_handle;
+		m_proto = std::move(other.m_proto);
+		m_state = other.m_state;
+		m_action = other.m_action;
+		m_condition = other.m_condition;
+
+		/* Invalidate other */
+		other.m_handle = Invalid;
+		other.m_state = State::Closed;
+		other.m_action = Action::None;
+		other.m_condition = Condition::None;
+
+		return *this;
+	}
+};
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if they equals
+ */
+template <typename Address, typename Protocol>
+bool operator==(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() == s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if they are different
+ */
+template <typename Address, typename Protocol>
+bool operator!=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() != s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 < s2
+ */
+template <typename Address, typename Protocol>
+bool operator<(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() < s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 > s2
+ */
+template <typename Address, typename Protocol>
+bool operator>(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() > s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 <= s2
+ */
+template <typename Address, typename Protocol>
+bool operator<=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() <= s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 >= s2
+ */
+template <typename Address, typename Protocol>
+bool operator>=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() >= s2.handle();
+}
+
+/* }}} */
+
+/*
+ * Predefined options
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Options */
+
+/**
+ * Namespace of predefined options.
+ */
+namespace option {
+
+/*
+ * Options for socket
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Options for socket */
+
+/**
+ * @class SockBlockMode
+ * @brief Set or get the blocking-mode for a socket.
+ * @warning On Windows, it's not possible to check if the socket is blocking or not.
+ */
+class SockBlockMode {
+public:
+	/**
+	 * Set to false if you want non-blocking socket.
+	 */
+	bool value{false};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	void set(Socket<Address, Protocol> &sc) const
+	{
+#if defined(O_NONBLOCK) && !defined(_WIN32)
+		int flags;
+
+		if ((flags = fcntl(sc.handle(), F_GETFL, 0)) < 0) {
+			flags = 0;
+		}
+
+		if (value) {
+			flags &= ~(O_NONBLOCK);
+		} else {
+			flags |= O_NONBLOCK;
+		}
+
+		if (fcntl(sc.handle(), F_SETFL, flags) < 0) {
+			throw Error{Error::System, "fcntl"};
+		}
+#else
+		unsigned long flags = (value) ? 0 : 1;
+
+		if (ioctlsocket(sc.handle(), FIONBIO, &flags) == Failure) {
+			throw Error{Error::System, "fcntl"};
+		}
+#endif
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	bool get(Socket<Address, Protocol> &sc) const
+	{
+#if defined(O_NONBLOCK) && !defined(_WIN32)
+		int flags = fcntl(sc.handle(), F_GETFL, 0);
+
+		if (flags < 0) {
+			throw Error{Error::System, "fcntl"};
+		}
+
+		return !(flags & O_NONBLOCK);
+#else
+		throw Error{Error::Other, "get", "Windows API cannot let you get the blocking status of a socket"};
+#endif
+	}
+};
+
+/**
+ * @class SockReuseAddress
+ * @brief Reuse address, must be used before calling Socket::bind
+ */
+class SockReuseAddress {
+public:
+	/**
+	 * Set to true if you want to set the SOL_SOCKET/SO_REUSEADDR option.
+	 */
+	bool value{true};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(SOL_SOCKET, SO_REUSEADDR, value ? 1 : 0);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline bool get(Socket<Address, Protocol> &sc) const
+	{
+		return static_cast<bool>(sc.template get<int>(SOL_SOCKET, SO_REUSEADDR));
+	}
+};
+
+/**
+ * @class SockSendBuffer
+ * @brief Set or get the output buffer.
+ */
+class SockSendBuffer {
+public:
+	/**
+	 * Set to the buffer size.
+	 */
+	int value{2048};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(SOL_SOCKET, SO_SNDBUF, value);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline int get(Socket<Address, Protocol> &sc) const
+	{
+		return sc.template get<int>(SOL_SOCKET, SO_SNDBUF);
+	}
+};
+
+/**
+ * @class SockReceiveBuffer
+ * @brief Set or get the input buffer.
+ */
+class SockReceiveBuffer {
+public:
+	/**
+	 * Set to the buffer size.
+	 */
+	int value{2048};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(SOL_SOCKET, SO_RCVBUF, value);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline int get(Socket<Address, Protocol> &sc) const
+	{
+		return sc.template get<int>(SOL_SOCKET, SO_RCVBUF);
+	}
+};
+
+/* }}} */
+
+/**
+ * @class TcpNoDelay
+ * @brief Set this option if you want to disable nagle's algorithm.
+ */
+class TcpNoDelay {
+public:
+	/**
+	 * Set to true to set TCP_NODELAY option.
+	 */
+	bool value{true};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(IPPROTO_TCP, TCP_NODELAY, value ? 1 : 0);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline bool get(Socket<Address, Protocol> &sc) const
+	{
+		return static_cast<bool>(sc.template get<int>(IPPROTO_TCP, TCP_NODELAY));
+	}
+};
+
+/**
+ * @class Ipv6Only
+ * @brief Control IPPROTO_IPV6/IPV6_V6ONLY
+ *
+ * Note: some systems may or not set this option by default so it's a good idea to set it in any case to either
+ * false or true if portability is a concern.
+ */
+class Ipv6Only {
+public:
+	/**
+	 * Set this to use only IPv6.
+	 */
+	bool value{true};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(IPPROTO_IPV6, IPV6_V6ONLY, value ? 1 : 0);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline bool get(Socket<Address, Protocol> &sc) const
+	{
+		return static_cast<bool>(sc.template get<int>(IPPROTO_IPV6, IPV6_V6ONLY));
+	}
+};
+
+} // !option
+
+/* }}} */
+
+/*
+ * Predefined addressed to be used
+ * ------------------------------------------------------------------
+ *
+ * - Ip,
+ * - Local.
+ */
+
+/* {{{ Addresses */
+
+/**
+ * Set of predefined addresses.
+ */
+namespace address {
+
+/**
+ * @class Ip
+ * @brief Base class for IPv6 and IPv4, you can use it if you don't know in advance if you'll use IPv6 or IPv4.
+ */
+class Ip {
+public:
+	/**
+	 * @enum Type
+	 * @brief Type of ip address.
+	 */
+	enum Type {
+		v4 = AF_INET,		//!< AF_INET
+		v6 = AF_INET6		//!< AF_INET6
+	};
+
+private:
+	/*
+	 * Default domain when using default constructors.
+	 *
+	 * Note: AF_INET or AF_INET6, not
+	 */
+	static int m_default;
+
+	union {
+		sockaddr_in m_sin;
+		sockaddr_in6 m_sin6;
+	};
+
+	socklen_t m_length{0};
+	int m_domain{AF_INET};
+
+public:
+	/**
+	 * Set the default domain to use when using default Ip constructor. By default, AF_INET is used.
+	 *
+	 * @pre domain must be Type::v4 or Type::v6
+	 */
+	static inline void setDefault(Type domain) noexcept
+	{
+		assert(domain == Type::v4 || domain == Type::v6);
+
+		m_default = static_cast<int>(domain);
+	}
+
+	/**
+	 * Construct using the default domain.
+	 */
+	inline Ip() noexcept
+		: Ip(static_cast<Type>(m_default))
+	{
+	}
+
+	/**
+	 * Default initialize the Ip domain.
+	 *
+	 * @pre domain must be AF_INET or AF_INET6 only
+	 * @param domain the domain (AF_INET or AF_INET6)
+	 */
+	Ip(Type domain) noexcept;
+
+	/**
+	 * Construct an address suitable for bind() or connect().
+	 *
+	 * @pre domain must be Type::v4 or Type::v6
+	 * @param domain the domain (AF_INET or AF_INET6)
+	 * @param host the host (* for any)
+	 * @param port the port number
+	 * @throw Error on errors
+	 */
+	Ip(const std::string &host, int port, Type domain = v4);
+
+	/**
+	 * Construct an address from a storage.
+	 *
+	 * @pre storage's domain must be AF_INET or AF_INET6 only
+	 * @param ss the storage
+	 * @param length the length
+	 */
+	Ip(const sockaddr_storage *ss, socklen_t length) noexcept;
+
+	/**
+	 * Get the domain (AF_INET or AF_INET6).
+	 *
+	 * @return the domain
+	 */
+	inline int domain() const noexcept
+	{
+		return m_domain;
+	}
+
+	/**
+	 * Return the underlying address, either sockaddr_in6 or sockaddr_in.
+	 *
+	 * @return the address
+	 */
+	inline const sockaddr *address() const noexcept
+	{
+		if (m_domain == AF_INET6) {
+			return reinterpret_cast<const sockaddr *>(&m_sin6);
+		}
+
+		return reinterpret_cast<const sockaddr *>(&m_sin);
+	}
+
+	/**
+	 * Return the underlying address length.
+	 *
+	 * @return the length
+	 */
+	inline socklen_t length() const noexcept
+	{
+		return m_length;
+	}
+
+	/**
+	 * Get the port.
+	 *
+	 * @return the port
+	 */
+	inline int port() const noexcept
+	{
+		if (m_domain == AF_INET6) {
+			return ntohs(m_sin6.sin6_port);
+		}
+
+		return ntohs(m_sin.sin_port);
+	}
+};
+
+#if !defined(_WIN32)
+
+/**
+ * @class Local
+ * @brief unix family sockets
+ *
+ * Create an address to a specific path. Only available on Unix.
+ */
+class Local {
+private:
+	sockaddr_un m_sun;
+	std::string m_path;
+
+public:
+	/**
+	 * Get the domain AF_LOCAL.
+	 *
+	 * @return AF_LOCAL
+	 */
+	inline int domain() const noexcept
+	{
+		return AF_LOCAL;
+	}
+
+	/**
+	 * Default constructor.
+	 */
+	Local() noexcept;
+
+	/**
+	 * Construct an address to a path.
+	 *
+	 * @param path the path
+	 * @param rm remove the file before (default: false)
+	 */
+	Local(std::string path, bool rm = false) noexcept;
+
+	/**
+	 * Construct an unix address from a storage address.
+	 *
+	 * @pre storage's domain must be AF_LOCAL
+	 * @param ss the storage
+	 * @param length the length
+	 */
+	Local(const sockaddr_storage *ss, socklen_t length) noexcept;
+
+	/**
+	 * Get the sockaddr_un.
+	 *
+	 * @return the address
+	 */
+	inline const sockaddr *address() const noexcept
+	{
+		return reinterpret_cast<const sockaddr *>(&m_sun);
+	}
+
+	/**
+	 * Get the address length.
+	 *
+	 * @return the length
+	 */
+	inline socklen_t length() const noexcept
+	{
+#if defined(SOCKET_HAVE_SUN_LEN)
+		return SUN_LEN(&m_sun);
+#else
+		return sizeof (m_sun);
+#endif
+	}
+};
+
+#endif // !_WIN32
+
+} // !address
+
+/* }}} */
+
+/*
+ * Predefined protocols
+ * ------------------------------------------------------------------
+ *
+ * - Tcp, for standard stream connections,
+ * - Udp, for standard datagram connections,
+ * - Tls, for secure stream connections.
+ */
+
+/* {{{ Protocols */
+
+/**
+ * Set of predefined protocols.
+ */
+namespace protocol {
+
+/* {{{ Tcp */
+
+/**
+ * @class Tcp
+ * @brief Clear TCP implementation.
+ *
+ * This is the basic TCP protocol that implements recv, send, connect and accept as wrappers of the usual
+ * C functions.
+ */
+class Tcp {
+public:
+	/**
+	 * Socket type.
+	 *
+	 * @return SOCK_STREAM
+	 */
+	inline int type() const noexcept
+	{
+		return SOCK_STREAM;
+	}
+
+	/**
+	 * Do nothing.
+	 *
+	 * This function is just present for compatibility, it should never be called.
+	 */
+	template <typename Address>
+	inline void create(Socket<Address, Tcp> &) const noexcept
+	{
+		/* No-op */
+	}
+
+	/**
+	 * Standard connect.
+	 *
+	 * If the socket is marked non-blocking and the connection cannot be established immediately, then the
+	 * following is true:
+	 *
+	 * - state is set to State::Connecting,
+	 * - action is set to Action::Connect,
+	 * - condition is set to Condition::Writable.
+	 *
+	 * Then the user must wait until the socket is writable and call connect() with 0 arguments.
+	 *
+	 * If the socket is blocking, this function blocks until the connection is complete or an error occurs, in
+	 * that case state is either set to State::Connected or State::Disconnected but action and condition are
+	 * not set.
+	 *
+	 * @param sc the socket
+	 * @param address the address
+	 * @param length the length
+	 * @throw net::Error on errors
+	 * @note Wrapper of connect(2)
+	 */
+	template <typename Address, typename Protocol>
+	void connect(Socket<Address, Protocol> &sc, const sockaddr *address, socklen_t length)
+	{
+		if (::connect(sc.handle(), address, length) == Failure) {
+			/*
+			 * Determine if the error comes from a non-blocking connect that cannot be
+			 * accomplished yet.
+			 */
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				sc.setState(State::Connecting);
+				sc.setAction(Action::Connect);
+				sc.setCondition(Condition::Writable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "connect", error};
+			}
+#else
+			if (errno == EINPROGRESS) {
+				sc.setState(State::Connecting);
+				sc.setAction(Action::Connect);
+				sc.setCondition(Condition::Writable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "connect"};
+			}
+#endif
+		} else {
+			sc.setState(State::Connected);
+		}
+	}
+
+	/**
+	 * Continue the connection. This function must only be called when the socket is ready for writing,
+	 * the user is responsible of waiting for that condition.
+	 *
+	 * This function check for SOL_SOCKET/SO_ERROR status.
+	 *
+	 * If the connection is complete, status is set to State::Connected, otherwise it is set to
+	 * State::Disconnected. In both cases, action and condition are not set.
+	 *
+	 * @param sc the socket
+	 * @throw net::Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	void connect(Socket<Address, Protocol> &sc)
+	{
+		int error = sc.template get<int>(SOL_SOCKET, SO_ERROR);
+
+		if (error == Failure) {
+			sc.setState(State::Disconnected);
+			throw Error{Error::System, "connect", error};
+		}
+
+		sc.setState(State::Connected);
+	}
+
+	/**
+	 * Accept a clear client.
+	 *
+	 * If the socket is marked non-blocking and there are no pending connection, this function throws an
+	 * error. The user must wait that the socket is readable before calling this function.
+	 *
+	 * If the socket is blocking, this function blocks until a new client is connected or throws an error on
+	 * errors.
+	 *
+	 * If the socket is correctly returned, its state is set to State::Accepted and its action and condition
+	 * are not set.
+	 *
+	 * In any case, action and condition of this socket are not set.
+	 *
+	 * @param sc the socket
+	 * @param address the address destination
+	 * @param length the address length
+	 * @return the socket
+	 * @throw net::Error on errors
+	 * @note Wrapper of accept(2)
+	 */
+	template <typename Address, typename Protocol>
+	Socket<Address, Protocol> accept(Socket<Address, Protocol> &sc, sockaddr *address, socklen_t *length)
+	{
+		Handle handle = ::accept(sc.handle(), address, length);
+
+		if (handle == Invalid) {
+			throw Error{Error::System, "accept"};
+		}
+
+		return Socket<Address, Protocol>{handle, State::Accepted};
+	}
+
+	/**
+	 * Continue accept.
+	 *
+	 * This function is just present for compatibility, it should never be called.
+	 */
+	template <typename Address, typename Protocol>
+	inline void accept(Socket<Address, Protocol> &) const noexcept
+	{
+		/* no-op */
+	}
+
+	/**
+	 * Receive data.
+	 *
+	 * If the socket is marked non-blocking and no data is available, 0 is returned and condition is set to
+	 * Condition::Readable. If 0 is returned and condition is not set, then the state is set to
+	 * State::Disconnected.
+	 *
+	 * If the socket is blocking, this function blocks until some data is available or if an error occurs.
+	 *
+	 * In any case, action is never set.
+	 *
+	 * @param sc the socket
+	 * @param data the destination
+	 * @param length the destination length
+	 * @return the number of bytes read
+	 * @throw Error on errors
+	 * @note Wrapper of recv(2)
+	 */
+	template <typename Address>
+	unsigned recv(Socket<Address, Tcp> &sc, void *data, unsigned length)
+	{
+		int nbread = ::recv(sc.handle(), (Arg)data, length, 0);
+
+		if (nbread == Failure) {
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				nbread = 0;
+				sc.setCondition(Condition::Readable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "recv", error};
+			}
+#else
+			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+				sc.setCondition(Condition::Readable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "recv"};
+			}
+#endif
+		} else if (nbread == 0) {
+			sc.setState(State::Disconnected);
+		}
+
+		return static_cast<unsigned>(nbread);
+	}
+
+	/**
+	 * Send some data.
+	 *
+	 * If the socket is marked non-blocking and the operation would block, then 0 is returned and condition is set to
+	 * Condition::Writable.
+	 *
+	 * If the socket is blocking, this function blocks until the data has been sent.
+	 *
+	 * On any other errors, this function throw net::Error.
+	 *
+	 * @param sc the socket
+	 * @param data the buffer to send
+	 * @param length the buffer length
+	 * @return the number of bytes sent
+	 * @throw net::Error on errors
+	 * @note Wrapper of send(2)
+	 */
+	template <typename Address>
+	unsigned send(Socket<Address, Tcp> &sc, const void *data, unsigned length)
+	{
+		int nbsent = ::send(sc.handle(), (ConstArg)data, length, 0);
+
+		if (nbsent == Failure) {
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "send", error};
+			}
+#else
+			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "send"};
+			}
+#endif
+		}
+
+		return static_cast<unsigned>(nbsent);
+	}
+};
+
+/* }}} */
+
+/* {{{ Udp */
+
+/**
+ * @class Udp
+ * @brief Clear UDP type.
+ *
+ * This class is the basic implementation of UDP sockets.
+ */
+class Udp {
+public:
+	/**
+	 * Socket type.
+	 *
+	 * @return SOCK_DGRAM
+	 */
+	inline int type() const noexcept
+	{
+		return SOCK_DGRAM;
+	}
+
+	/**
+	 * Do nothing.
+	 */
+	template <typename Address>
+	inline void create(Socket<Address, Udp> &) noexcept
+	{
+		/* No-op */
+	}
+
+	/**
+	 * Receive data from an end point.
+	 *
+	 * If the socket is marked non-blocking and no data is available, 0 is returned and condition is set to
+	 * Condition::Readable.
+	 *
+	 * If the socket is blocking, this functions blocks until some data is available or if an error occurs.
+	 *
+	 * @param sc the socket
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @param address the address
+	 * @param addrlen the initial address length
+	 * @return the number of bytes received
+	 * @throw Error on error
+	 */
+	template <typename Address>
+	unsigned recvfrom(Socket<Address, Udp> &sc, void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
+	{
+		int nbread;
+
+		nbread = ::recvfrom(sc.handle(), (Arg)data, length, 0, address, addrlen);
+
+		if (nbread == Failure) {
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				nbread = 0;
+				sc.setCondition(Condition::Readable);
+			} else {
+				throw Error{Error::System, "recvfrom"};
+			}
+#else
+			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+				nbread = 0;
+				sc.setCondition(Condition::Readable);
+			} else {
+				throw Error{Error::System, "recvfrom"};
+			}
+#endif
+		}
+
+		return static_cast<unsigned>(nbread);
+	}
+
+	/**
+	 * Send data to an end point.
+	 *
+	 * If the socket is marked non-blocking and the operation would block, then 0 is returned and condition is set to
+	 * Condition::Writable.
+	 *
+	 * If the socket is blocking, this functions blocks until the data has been sent.
+	 *
+	 * @param sc the socket
+	 * @param data the buffer
+	 * @param length the buffer length
+	 * @param address the client address
+	 * @param addrlen the adderss length
+	 * @return the number of bytes sent
+	 * @throw Error on error
+	 */
+	template <typename Address>
+	unsigned sendto(Socket<Address, Udp> &sc, const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
+	{
+		int nbsent;
+
+		nbsent = ::sendto(sc.handle(), (ConstArg)data, length, 0, address, addrlen);
+		if (nbsent == Failure) {
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				throw Error{Error::System, "sendto", error};
+			}
+#else
+			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				throw Error{Error::System, "sendto"};
+			}
+#endif
+		}
+
+		return static_cast<unsigned>(nbsent);
+	}
+};
+
+/* }}} */
+
+/* {{{ Tls */
+
+#if !defined(SOCKET_NO_SSL)
+
+/**
+ * @class Tls
+ * @brief OpenSSL secure layer for TCP.
+ *
+ * **Note:** This protocol is much more difficult to use with non-blocking sockets, if some operations would block, the
+ * user is responsible of calling the function again by waiting for the appropriate condition. See the functions for
+ * more details.
+ *
+ * @see Tls::accept
+ * @see Tls::connect
+ * @see Tls::recv
+ * @see Tls::send
+ */
+class Tls : private Tcp {
+private:
+	using Context = std::shared_ptr<SSL_CTX>;
+	using Ssl = std::unique_ptr<SSL, void (*)(SSL *)>;
+
+	/* OpenSSL objects */
+	Context m_context;
+	Ssl m_ssl{nullptr, nullptr};
+
+	/* Status */
+	bool m_tcpconnected{false};
+
+	/*
+	 * User definable parameters
+	 */
+	ssl::Method m_method{ssl::Tlsv1};
+	std::string m_key;
+	std::string m_certificate;
+	bool m_verify{false};
+
+	/*
+	 * Construct with a context and ssl, for Tls::accept.
+	 */
+	Tls(Context context, Ssl ssl)
+		: m_context{std::move(context)}
+		, m_ssl{std::move(ssl)}
+	{
+	}
+
+	/*
+	 * Get the OpenSSL error message.
+	 */
+	inline std::string error(int error)
+	{
+		auto msg = ERR_reason_error_string(error);
+
+		return msg == nullptr ? "" : msg;
+	}
+
+	/*
+	 * Update the states after an uncompleted operation.
+	 */
+	template <typename Address, typename Protocol>
+	inline void updateStates(Socket<Address, Protocol> &sc, State state, Action action, int code)
+	{
+		assert(code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE);
+
+		sc.setState(state);
+		sc.setAction(action);
+
+		if (code == SSL_ERROR_WANT_READ) {
+			sc.setCondition(Condition::Readable);
+		} else {
+			sc.setCondition(Condition::Writable);
+		}
+	}
+
+	/*
+	 * Continue the connect operation.
+	 */
+	template <typename Address, typename Protocol>
+	void processConnect(Socket<Address, Protocol> &sc)
+	{
+		int ret = SSL_connect(m_ssl.get());
+
+		if (ret <= 0) {
+			int no = SSL_get_error(m_ssl.get(), ret);
+
+			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
+				updateStates(sc, State::Connecting, Action::Connect, no);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "connect", error(no)};
+			}
+		} else {
+			sc.setState(State::Connected);
+		}
+	}
+
+	/*
+	 * Continue accept.
+	 */
+	template <typename Address, typename Protocol>
+	void processAccept(Socket<Address, Protocol> &sc)
+	{
+		int ret = SSL_accept(m_ssl.get());
+
+		if (ret <= 0) {
+			int no = SSL_get_error(m_ssl.get(), ret);
+
+			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
+				updateStates(sc, State::Accepting, Action::Accept, no);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error(Error::System, "accept", error(no));
+			}
+		} else {
+			sc.setState(State::Accepted);
+		}
+	}
+
+public:
+	/**
+	 * @copydoc Tcp::type
+	 */
+	inline int type() const noexcept
+	{
+		return SOCK_STREAM;
+	}
+
+	/**
+	 * Empty TLS constructor.
+	 */
+	Tls()
+	{
+#if !defined(SOCKET_NO_SSL_AUTO_INIT)
+		::net::ssl::init();
+#endif
+	}
+
+	/**
+	 * Set the method.
+	 *
+	 * @param method the method
+	 * @pre the socket must not be already created
+	 */
+	inline void setMethod(ssl::Method method) noexcept
+	{
+		assert(!m_context);
+		assert(!m_ssl);
+
+		m_method = method;
+	}
+
+	/**
+	 * Use the specified private key file.
+	 *
+	 * @param file the path to the private key
+	 */
+	inline void setPrivateKey(std::string file) noexcept
+	{
+		m_key = std::move(file);
+	}
+
+	/**
+	 * Use the specified certificate file.
+	 *
+	 * @param file the path to the file
+	 */
+	inline void setCertificate(std::string file) noexcept
+	{
+		m_certificate = std::move(file);
+	}
+
+	/**
+	 * Set to true if we must verify the certificate and private key.
+	 *
+	 * @param verify the mode
+	 */
+	inline void setVerify(bool verify = true) noexcept
+	{
+		m_verify = verify;
+	}
+
+	/**
+	 * Initialize the SSL objects after have created.
+	 *
+	 * @param sc the socket
+	 * @throw net::Error on errors
+	 */
+	template <typename Address>
+	inline void create(Socket<Address, Tls> &sc)
+	{
+		auto method = (m_method == ssl::Tlsv1) ? TLSv1_method() : SSLv3_method();
+
+		m_context = {SSL_CTX_new(method), SSL_CTX_free};
+		m_ssl = {SSL_new(m_context.get()), SSL_free};
+
+		SSL_set_fd(m_ssl.get(), sc.handle());
+
+		/* Load certificates */
+		if (m_certificate.size() > 0) {
+			SSL_CTX_use_certificate_file(m_context.get(), m_certificate.c_str(), SSL_FILETYPE_PEM);
+		}
+		if (m_key.size() > 0) {
+			SSL_CTX_use_PrivateKey_file(m_context.get(), m_key.c_str(), SSL_FILETYPE_PEM);
+		}
+		if (m_verify && !SSL_CTX_check_private_key(m_context.get())) {
+			throw Error{Error::System, "(openssl)", "unable to verify key"};
+		}
+	}
+
+	/**
+	 * Connect to a secure host.
+	 *
+	 * If the socket is marked non-blocking and the connection cannot be established yet, then the state is set
+	 * to State::Connecting, the condition is set to Condition::Readable or Condition::Writable, the user must
+	 * wait for the appropriate condition before calling the overload connect which takes 0 argument.
+	 *
+	 * If the socket is blocking, this functions blocks until the connection is complete.
+	 *
+	 * If the connection was completed correctly the state is set to State::Connected.
+	 *
+	 * @param sc the socket
+	 * @param address the address
+	 * @param length the address length
+	 * @throw net::Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	void connect(Socket<Address, Protocol> &sc, const sockaddr *address, socklen_t length)
+	{
+		/* 1. Connect using raw TCP */
+		Tcp::connect(sc, address, length);
+
+		/* 2. If the connection is complete (e.g. non-blocking), try handshake */
+		if (sc.state() == State::Connected) {
+			m_tcpconnected = true;
+			processConnect(sc);
+		}
+	}
+
+	/**
+	 * Continue the connection.
+	 *
+	 * This function must be called when the socket is ready for reading or writing (check with Socket::condition),
+	 * the state may change exactly like the initial connect call.
+	 *
+	 * @param sc the socket
+	 * @throw net::Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	void connect(Socket<Address, Protocol> &sc)
+	{
+		/* 1. Be sure to complete standard connect before */
+		if (!m_tcpconnected) {
+			Tcp::connect(sc);
+			m_tcpconnected = sc.state() == State::Connected;
+		}
+
+		if (m_tcpconnected) {
+			processConnect(sc);
+		}
+	}
+
+	/**
+	 * Accept a secure client.
+	 *
+	 * Because SSL needs several round-trips, if the socket is marked non-blocking and the connection is not
+	 * completed yet, a new socket is returned but with the State::Accepting state. Its condition is set to
+	 * Condition::Readable or Condition::Writable, the user is responsible of calling accept overload which takes
+	 * 0 arguments on the returned socket when the condition is met.
+	 *
+	 * If the socket is blocking, this function blocks until the client is accepted and returned.
+	 *
+	 * If the client is accepted correctly, its state is set to State::Accepted. This instance does not change.
+	 *
+	 * @param sc the socket
+	 * @param address the address destination
+	 * @param length the address length
+	 * @return the client
+	 * @throw net::Error on errors
+	 */
+	template <typename Address>
+	Socket<Address, Tls> accept(Socket<Address, Tls> &sc, sockaddr *address, socklen_t *length)
+	{
+		Socket<Address, Tls> client = Tcp::accept(sc, address, length);
+		Tls &proto = client.protocol();
+
+		/* 1. Share the context */
+		proto.m_context = m_context;
+
+		/* 2. Create new SSL instance */
+		proto.m_ssl = Ssl{SSL_new(m_context.get()), SSL_free};
+		SSL_set_fd(proto.m_ssl.get(), client.handle());
+
+		/* 3. Try accept process on the **new** client */
+		proto.processAccept(client);
+
+		return client;
+	}
+
+	/**
+	 * Continue accept.
+	 *
+	 * This function must be called on the client that is being accepted.
+	 *
+	 * Like accept or connect, user is responsible of calling this function until the connection is complete.
+	 *
+	 * @param sc the socket
+	 * @throw net::Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void accept(Socket<Address, Protocol> &sc)
+	{
+		processAccept(sc);
+	}
+
+	/**
+	 * Receive some secure data.
+	 *
+	 * If the socket is marked non-blocking, 0 is returned if no data is available yet or if the connection
+	 * needs renegociation. If renegociation is required case, the action is set to Action::Receive and condition
+	 * is set to Condition::Readable or Condition::Writable. The user must wait that the condition is met and
+	 * call this function again.
+	 *
+	 * @param sc the socket
+	 * @param data the destination
+	 * @param len the buffer length
+	 * @return the number of bytes read
+	 * @throw net::Error on errors
+	 */
+	template <typename Address>
+	unsigned recv(Socket<Address, Tls> &sc, void *data, unsigned len)
+	{
+		auto nbread = SSL_read(m_ssl.get(), data, len);
+
+		if (nbread <= 0) {
+			auto no = SSL_get_error(m_ssl.get(), nbread);
+
+			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
+				nbread = 0;
+				updateStates(sc, sc.state(), Action::Receive, no);
+			} else {
+				throw Error{Error::System, "recv", error(no)};
+			}
+		}
+
+		return nbread;
+	}
+
+	/**
+	 * Send some data.
+	 *
+	 * Like recv, if the socket is marked non-blocking and no data can be sent or a negociation is required,
+	 * condition and action are set. See receive for more details
+	 *
+	 * @param sc the socket
+	 * @param data the data to send
+	 * @param len the buffer length
+	 * @return the number of bytes sent
+	 * @throw net::Error on errors
+	 */
+	template <typename Address>
+	unsigned send(Socket<Address, Tls> &sc, const void *data, unsigned len)
+	{
+		auto nbsent = SSL_write(m_ssl.get(), data, len);
+
+		if (nbsent <= 0) {
+			auto no = SSL_get_error(m_ssl.get(), nbsent);
+
+			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
+				nbsent = 0;
+				updateStates(sc, sc.state(), Action::Send, no);
+			} else {
+				throw Error{Error::System, "send", error(no)};
+			}
+		}
+
+		return nbsent;
+	}
+};
+
+#endif // !SOCKET_NO_SSL
+
+/* }}} */
+
+} // !protocol
+
+/* }}} */
+
+/*
+ * Convenient helpers
+ * ------------------------------------------------------------------
+ *
+ * - SocketTcp<Address>, for TCP sockets,
+ * - SocketUdp<Address>, for UDP sockets,
+ * - SocketTls<Address>, for secure TCP sockets.
+ */
+
+/* {{{ Helpers */
+
+/**
+ * Helper to create TCP sockets.
+ */
+template <typename Address>
+using SocketTcp = Socket<Address, protocol::Tcp>;
+
+/**
+ * Helper to create TCP/IP sockets.
+ */
+using SocketTcpIp = Socket<address::Ip, protocol::Tcp>;
+
+#if !defined(_WIN32)
+
+/**
+ * Helper to create TCP/Local sockets.
+ */
+using SocketTcpLocal = Socket<address::Local, protocol::Tcp>;
+
+#endif
+
+/**
+ * Helper to create UDP sockets.
+ */
+template <typename Address>
+using SocketUdp = Socket<Address, protocol::Udp>;
+
+/**
+ * Helper to create UDP/IP sockets.
+ */
+using SocketUdpIp = Socket<address::Ip, protocol::Udp>;
+
+#if !defined(SOCKET_NO_SSL)
+
+/**
+ * Helper to create OpenSSL TCP sockets.
+ */
+template <typename Address>
+using SocketTls = Socket<Address, protocol::Tls>;
+
+/**
+ * Helper to create OpenSSL TCP/Ip sockets.
+ */
+using SocketTlsIp = Socket<address::Ip, protocol::Tls>;
+
+#endif // !SOCKET_NO_SSL
+
+/* }}} */
+
+/*
+ * Select wrapper
+ * ------------------------------------------------------------------
+ *
+ * Wrapper for select(2) and other various implementations.
+ */
+
+/* {{{ Listener */
+
+/**
+ * @class ListenerStatus
+ * @brief Result of polling
+ *
+ * Result of a select call, returns the first ready socket found with its
+ * flags.
+ */
+class ListenerStatus {
+public:
+	Handle socket;		//!< which socket is ready
+	Condition flags;	//!< the flags
+};
+
+/**
+ * Table used in the socket listener to store which sockets have been
+ * set in which directions.
+ */
+using ListenerTable = std::map<Handle, Condition>;
+
+/**
+ * @class Select
+ * @brief Implements select(2)
+ *
+ * This class is the fallback of any other method, it is not preferred at all for many reasons.
+ */
+class Select {
+public:
+	/**
+	 * No-op, uses the ListenerTable directly.
+	 */
+	inline void set(const ListenerTable &, Handle, Condition, bool) noexcept {}
+
+	/**
+	 * No-op, uses the ListenerTable directly.
+	 */
+	inline void unset(const ListenerTable &, Handle, Condition, bool) noexcept {}
+
+	/**
+	 * Return the sockets
+	 */
+	std::vector<ListenerStatus> wait(const ListenerTable &table, int ms);
+
+	/**
+	 * Backend identifier
+	 */
+	inline const char *name() const noexcept
+	{
+		return "select";
+	}
+};
+
+#if defined(SOCKET_HAVE_POLL)
+
+/**
+ * @class Poll
+ * @brief Implements poll(2).
+ *
+ * Poll is widely supported and is better than select(2). It is still not the
+ * best option as selecting the sockets is O(n).
+ */
+class Poll {
+private:
+	std::vector<pollfd> m_fds;
+
+	short toPoll(Condition flags) const noexcept;
+	Condition toCondition(short &event) const noexcept;
+
+public:
+	/**
+	 * Set the handle.
+	 */
+	void set(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Unset the handle.
+	 */
+	void unset(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Wait for events.
+	 */
+	std::vector<ListenerStatus> wait(const ListenerTable &, int ms);
+
+	/**
+	 * Backend identifier
+	 */
+	inline const char *name() const noexcept
+	{
+		return "poll";
+	}
+};
+
+#endif
+
+#if defined(SOCKET_HAVE_EPOLL)
+
+/**
+ * @class Epoll
+ * @brief Linux's epoll.
+ */
+class Epoll {
+private:
+	int m_handle;
+	std::vector<epoll_event> m_events;
+
+	Epoll(const Epoll &) = delete;
+	Epoll &operator=(const Epoll &) = delete;
+	Epoll(const Epoll &&) = delete;
+	Epoll &operator=(const Epoll &&) = delete;
+
+	uint32_t toEpoll(Condition flags) const noexcept;
+	Condition toCondition(uint32_t events) const noexcept;
+	void update(Handle sc, int op, int eflags);
+
+public:
+	/**
+	 * Construct the epoll instance.
+	 */
+	Epoll();
+
+	/**
+	 * Close the epoll instance.
+	 */
+	~Epoll();
+
+	/**
+	 * Set the handle.
+	 */
+	void set(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Unset the handle.
+	 */
+	void unset(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Wait for events.
+	 */
+	std::vector<ListenerStatus> wait(const ListenerTable &, int);
+
+	/**
+	 * Backend identifier
+	 */
+	inline const char *name() const noexcept
+	{
+		return "epoll";
+	}
+};
+
+#endif
+
+#if defined(SOCKET_HAVE_KQUEUE)
+
+/**
+ * @class Kqueue
+ * @brief Implements kqueue(2).
+ *
+ * This implementation is available on all BSD and Mac OS X. It is better than
+ * poll(2) because it's O(1), however it's a bit more memory consuming.
+ */
+class Kqueue {
+private:
+	std::vector<struct kevent> m_result;
+	int m_handle;
+
+	Kqueue(const Kqueue &) = delete;
+	Kqueue &operator=(const Kqueue &) = delete;
+	Kqueue(Kqueue &&) = delete;
+	Kqueue &operator=(Kqueue &&) = delete;
+
+	void update(Handle sc, int filter, int kflags);
+
+public:
+	/**
+	 * Construct the kqueue instance.
+	 */
+	Kqueue();
+
+	/**
+	 * Destroy the kqueue instance.
+	 */
+	~Kqueue();
+
+	/**
+	 * Set the handle.
+	 */
+	void set(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Unset the handle.
+	 */
+	void unset(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Wait for events.
+	 */
+	std::vector<ListenerStatus> wait(const ListenerTable &, int);
+
+	/**
+	 * Backend identifier
+	 */
+	inline const char *name() const noexcept
+	{
+		return "kqueue";
+	}
+};
+
+#endif
+
+/**
+ * @class Listener
+ * @brief Synchronous multiplexing
+ *
+ * Convenient wrapper around the select() system call.
+ *
+ * This class is implemented using a bridge pattern to allow different uses
+ * of listener implementation.
+ *
+ * You should not reinstanciate a new Listener at each iteartion of your
+ * main loop as it can be extremely costly. Instead use the same listener that
+ * you can safely modify on the fly.
+ *
+ * Currently, poll, epoll, select and kqueue are available.
+ *
+ * To implement the backend, the following functions must be available:
+ *
+ * ### Set
+ *
+ * @code
+ * void set(const ListenerTable &, Handle sc, Condition condition, bool add);
+ * @endcode
+ *
+ * This function, takes the socket to be added and the flags. The condition is
+ * always guaranteed to be correct and the function will never be called twice
+ * even if the user tries to set the same flag again.
+ *
+ * An optional add argument is added for backends which needs to do different
+ * operation depending if the socket was already set before or if it is the
+ * first time (e.g EPOLL_CTL_ADD vs EPOLL_CTL_MOD for epoll(7).
+ *
+ * ### Unset
+ *
+ * @code
+ * void unset(const ListenerTable &, Handle sc, Condition condition, bool remove);
+ * @endcode
+ *
+ * Like set, this function is only called if the condition is actually set and will
+ * not be called multiple times.
+ *
+ * Also like set, an optional remove argument is set if the socket is being
+ * completely removed (e.g no more flags are set for this socket).
+ *
+ * ### Wait
+ *
+ * @code
+ * std::vector<ListenerStatus> wait(const ListenerTable &, int ms);
+ * @endcode
+ *
+ * Wait for the sockets to be ready with the specified milliseconds. Must return a list of ListenerStatus,
+ * may throw any exceptions.
+ *
+ * ### Name
+ *
+ * @code
+ * inline const char *name() const noexcept
+ * @endcode
+ *
+ * Returns the backend name. Usually the class in lower case.
+ */
+template <typename Backend = SOCKET_DEFAULT_BACKEND>
+class Listener {
+private:
+	Backend m_backend;
+	ListenerTable m_table;
+
+public:
+	/**
+	 * Construct an empty listener.
+	 */
+	Listener() = default;
+
+	/**
+	 * Get the backend.
+	 *
+	 * @return the backend
+	 */
+	inline const Backend &backend() const noexcept
+	{
+		return m_backend;
+	}
+
+	/**
+	 * Get the non-modifiable table.
+	 *
+	 * @return the table
+	 */
+	inline const ListenerTable &table() const noexcept
+	{
+		return m_table;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the iterator
+	 */
+	inline ListenerTable::const_iterator begin() const noexcept
+	{
+		return m_table.begin();
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the iterator
+	 */
+	inline ListenerTable::const_iterator cbegin() const noexcept
+	{
+		return m_table.cbegin();
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the iterator
+	 */
+	inline ListenerTable::const_iterator end() const noexcept
+	{
+		return m_table.end();
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the iterator
+	 */
+	inline ListenerTable::const_iterator cend() const noexcept
+	{
+		return m_table.cend();
+	}
+
+	/**
+	 * Add or update a socket to the listener.
+	 *
+	 * If the socket is already placed with the appropriate flags, the
+	 * function is a no-op.
+	 *
+	 * If incorrect flags are passed, the function does nothing.
+	 *
+	 * @param sc the socket
+	 * @param condition the condition (may be OR'ed)
+	 * @throw Error if the backend failed to set
+	 */
+	void set(Handle sc, Condition condition)
+	{
+		/* Invalid or useless flags */
+		if (condition == Condition::None || static_cast<int>(condition) > 0x3)
+			return;
+
+		auto it = m_table.find(sc);
+
+		/*
+		 * Do not update the table if the backend failed to add
+		 * or update.
+		 */
+		if (it == m_table.end()) {
+			m_backend.set(m_table, sc, condition, true);
+			m_table.emplace(sc, condition);
+		} else {
+			/* Remove flag if already present */
+			if ((condition & Condition::Readable) == Condition::Readable &&
+			    (it->second & Condition::Readable) == Condition::Readable) {
+				condition &= ~(Condition::Readable);
+			}
+			if ((condition & Condition::Writable) == Condition::Writable &&
+			    (it->second & Condition::Writable) == Condition::Writable) {
+				condition &= ~(Condition::Writable);
+			}
+
+			/* Still need a call? */
+			if (condition != Condition::None) {
+				m_backend.set(m_table, sc, condition, false);
+				it->second |= condition;
+			}
+		}
+	}
+
+	/**
+	 * Unset a socket from the listener, only the flags is removed
+	 * unless the two flagss are requested.
+	 *
+	 * For example, if you added a socket for both reading and writing,
+	 * unsetting the write flags will keep the socket for reading.
+	 *
+	 * @param sc the socket
+	 * @param condition the condition (may be OR'ed)
+	 * @see remove
+	 */
+	void unset(Handle sc, Condition condition)
+	{
+		auto it = m_table.find(sc);
+
+		/* Invalid or useless flags */
+		if (condition == Condition::None || static_cast<int>(condition) > 0x3 || it == m_table.end())
+			return;
+
+		/*
+		 * Like set, do not update if the socket is already at the appropriate
+		 * state.
+		 */
+		if ((condition & Condition::Readable) == Condition::Readable &&
+		    (it->second & Condition::Readable) != Condition::Readable) {
+			condition &= ~(Condition::Readable);
+		}
+		if ((condition & Condition::Writable) == Condition::Writable &&
+		    (it->second & Condition::Writable) != Condition::Writable) {
+			condition &= ~(Condition::Writable);
+		}
+
+		if (condition != Condition::None) {
+			/* Determine if it's a complete removal */
+			bool removal = ((it->second) & ~(condition)) == Condition::None;
+
+			m_backend.unset(m_table, sc, condition, removal);
+
+			if (removal) {
+				m_table.erase(it);
+			} else {
+				it->second &= ~(condition);
+			}
+		}
+	}
+
+	/**
+	 * Remove completely the socket from the listener.
+	 *
+	 * It is a shorthand for unset(sc, Condition::Readable | Condition::Writable);
+	 *
+	 * @param sc the socket
+	 */
+	inline void remove(Handle sc)
+	{
+		unset(sc, Condition::Readable | Condition::Writable);
+	}
+
+	/**
+	 * Remove all sockets.
+	 */
+	inline void clear()
+	{
+		while (!m_table.empty()) {
+			remove(m_table.begin()->first);
+		}
+	}
+
+	/**
+	 * Get the number of sockets in the listener.
+	 */
+	inline ListenerTable::size_type size() const noexcept
+	{
+		return m_table.size();
+	}
+
+	/**
+	 * Select a socket. Waits for a specific amount of time specified as the duration.
+	 *
+	 * @param duration the duration
+	 * @return the socket ready
+	 */
+	template <typename Rep, typename Ratio>
+	inline ListenerStatus wait(const std::chrono::duration<Rep, Ratio> &duration)
+	{
+		auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
+
+		return m_backend.wait(m_table, cvt.count())[0];
+	}
+
+	/**
+	 * Overload with milliseconds.
+	 *
+	 * @param timeout the optional timeout in milliseconds
+	 * @return the socket ready
+	 */
+	inline ListenerStatus wait(int timeout = -1)
+	{
+		return wait(std::chrono::milliseconds(timeout));
+	}
+
+	/**
+	 * Select multiple sockets.
+	 *
+	 * @param duration the duration
+	 * @return the socket ready
+	 */
+	template <typename Rep, typename Ratio>
+	inline std::vector<ListenerStatus> waitMultiple(const std::chrono::duration<Rep, Ratio> &duration)
+	{
+		auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
+
+		return m_backend.wait(m_table, cvt.count());
+	}
+
+	/**
+	 * Overload with milliseconds.
+	 *
+	 * @return the socket ready
+	 */
+	inline std::vector<ListenerStatus> waitMultiple(int timeout = -1)
+	{
+		return waitMultiple(std::chrono::milliseconds(timeout));
+	}
+};
+
+/* }}} */
+
+/*
+ * Callback
+ * ------------------------------------------------------------------
+ *
+ * Function owner with tests.
+ */
+
+/* {{{ Callback */
+
+/**
+ * @class Callback
+ * @brief Convenient signal owner that checks if the target is valid.
+ *
+ * This class also catch all errors thrown from signals to avoid interfering with our process.
+ */
+template <typename... Args>
+class Callback : public std::function<void (Args...)> {
+public:
+	/**
+	 * Inherited constructors.
+	 */
+	using std::function<void (Args...)>::function;
+
+	/**
+	 * Execute the callback only if a target is set.
+	 */
+	void operator()(Args... args) const
+	{
+		if (*this) {
+			try {
+				std::function<void (Args...)>::operator()(args...);
+			} catch (...) {
+			}
+		}
+	}
+};
+
+/* }}} */
+
+/*
+ * StreamConnection
+ * ------------------------------------------------------------------
+ *
+ * Client connected on the server side.
+ */
+
+/* {{{ StreamConnection */
+
+/**
+ * @class StreamConnection
+ * @brief Connected client on the server side.
+ *
+ * This object is created from StreamServer when a new client is connected, it is the higher
+ * level object of sockets and completely asynchronous.
+ */
+template <typename Address, typename Protocol>
+class StreamConnection {
+public:
+	/**
+	 * Called when the output has changed.
+	 */
+	using WriteHandler = Callback<>;
+
+private:
+	/* Signals */
+	WriteHandler m_onWrite;
+
+	/* Sockets and output buffer */
+	Socket<Address, Protocol> m_socket;
+	std::string m_output;
+
+public:
+	/**
+	 * Create the connection.
+	 *
+	 * @param s the socket
+	 */
+	StreamConnection(Socket<Address, Protocol> s)
+		: m_socket{std::move(s)}
+	{
+		m_socket.set(net::option::SockBlockMode{false});
+	}
+
+	/**
+	 * Access the underlying socket.
+	 *
+	 * @return the socket
+	 * @warning use with care
+	 */
+	inline Socket<Address, Protocol> &socket() noexcept
+	{
+		return m_socket;
+	}
+
+	/**
+	 * Access the current output.
+	 *
+	 * @return the output
+	 */
+	inline const std::string &output() const noexcept
+	{
+		return m_output;
+	}
+
+	/**
+	 * Overloaded function
+	 *
+	 * @return the output
+	 * @warning use with care, avoid modifying the output if you don't know what you're doing
+	 */
+	inline std::string &output() noexcept
+	{
+		return m_output;
+	}
+
+	/**
+	 * Post some data to be sent asynchronously.
+	 *
+	 * @param str the data to append
+	 */
+	inline void send(std::string str)
+	{
+		m_output += str;
+		m_onWrite();
+	}
+
+	/**
+	 * Kill the client.
+	 */
+	inline void close()
+	{
+		m_socket.close();
+	}
+
+	/**
+	 * Set the write handler, the signal is emitted when the output has changed so that the StreamServer owner
+	 * knows that there are some data to send.
+	 *
+	 * @param handler the handler
+	 * @warning you usually never need to set this yourself
+	 */
+	inline void setWriteHandler(WriteHandler handler)
+	{
+		m_onWrite = std::move(handler);
+	}
+};
+
+/* }}} */
+
+/*
+ * StreamServer
+ * ------------------------------------------------------------------
+ *
+ * Convenient stream oriented server.
+ */
+
+/* {{{ StreamServer */
+
+/**
+ * @class StreamServer
+ * @brief Convenient stream server for TCP and TLS.
+ *
+ * This class does all the things for you as accepting new clients, listening for it and sending data. It works
+ * asynchronously without blocking to let you control your process workflow.
+ *
+ * This class is not thread safe and you must not call any of the functions from different threads.
+ */
+template <typename Address, typename Protocol>
+class StreamServer {
+public:
+	/**
+	 * Handler when a new client is connected.
+	 */
+	using ConnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
+
+	/**
+	 * Handler when a client is disconnected.
+	 */
+	using DisconnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
+
+	/**
+	 * Handler when data has been received from a client.
+	 */
+	using ReadHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
+
+	/**
+	 * Handler when data has been correctly sent to a client.
+	 */
+	using WriteHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
+
+	/**
+	 * Handler when an error occured.
+	 */
+	using ErrorHandler = Callback<const Error &>;
+
+	/**
+	 * Handler when there was a timeout.
+	 */
+	using TimeoutHandler = Callback<>;
+
+private:
+	using ClientMap = std::map<Handle, std::shared_ptr<StreamConnection<Address, Protocol>>>;
+
+	/* Signals */
+	ConnectionHandler m_onConnection;
+	DisconnectionHandler m_onDisconnection;
+	ReadHandler m_onRead;
+	WriteHandler m_onWrite;
+	ErrorHandler m_onError;
+	TimeoutHandler m_onTimeout;
+
+	/* Sockets */
+	Socket<Address, Protocol> m_master;
+	Listener<> m_listener;
+	ClientMap m_clients;
+
+	/*
+	 * Update flags depending on the required condition.
+	 */
+	void updateFlags(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
+	{
+		assert(client->socket().action() != Action::None);
+
+		m_listener.remove(client->socket().handle());
+		m_listener.set(client->socket().handle(), client->socket().condition());
+	}
+
+	/*
+	 * Continue accept process.
+	 */
+	template <typename AcceptCall>
+	void processAccept(std::shared_ptr<StreamConnection<Address, Protocol>> &client, const AcceptCall &acceptFunc)
+	{
+		try {
+			/* Do the accept */
+			acceptFunc();
+
+			/* 1. First remove completely the client */
+			m_listener.remove(client->socket().handle());
+
+			/* 2. If accept is not finished, wait for the appropriate condition */
+			if (client->socket().state() == State::Accepted) {
+				/* 3. Client is accepted, notify the user */
+				m_listener.set(client->socket().handle(), Condition::Readable);
+				m_onConnection(client);
+			} else {
+				/* Operation still in progress */
+				updateFlags(client);
+			}
+		} catch (const Error &error) {
+			m_clients.erase(client->socket().handle());
+			m_listener.remove(client->socket().handle());
+			m_onError(error);
+		}
+	}
+
+	/*
+	 * Process initial accept of master socket, this is the initial accepting process. Except on errors, the
+	 * socket is stored but the user will be notified only once the socket is completely accepted.
+	 */
+	void processInitialAccept()
+	{
+		// TODO: store address too.
+		std::shared_ptr<StreamConnection<Address, Protocol>> client = std::make_shared<StreamConnection<Address, Protocol>>(m_master.accept(nullptr));
+		std::weak_ptr<StreamConnection<Address, Protocol>> ptr{client};
+
+		/* 1. Register output changed to update listener */
+		client->setWriteHandler([this, ptr] () {
+			auto client = ptr.lock();
+
+			/* Do not update the listener immediately if an action is pending */
+			if (client && client->socket().action() == Action::None && !client->output().empty()) {
+				m_listener.set(client->socket().handle(), Condition::Writable);
+			}
+		});
+
+		/* 2. Add the client */
+		m_clients.insert(std::make_pair(client->socket().handle(), client));
+
+		/*
+		 * 2. Do an initial check to set the listener flags, at this moment the socket may or not be
+		 *    completely accepted.
+		 */
+		processAccept(client, [&] () {});
+	}
+
+	/*
+	 * Read or complete the read operation.
+	 */
+	void processRead(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
+	{
+		/*
+		 * Read because there is something to read or because the pending operation is
+		 * read and must complete.
+		 */
+		auto buffer = client->socket().recv(512);
+
+		/*
+		 * Now the receive operation may be completed, in that case, two possibilities:
+		 *
+		 * 1. The action is set to None (completed)
+		 * 2. The action is still not complete, update the flags
+		 */
+		if (client->socket().action() == Action::None) {
+			/* Empty mean normal disconnection */
+			if (buffer.empty()) {
+				m_listener.remove(client->socket().handle());
+				m_clients.erase(client->socket().handle());
+				m_onDisconnection(client);
+			} else {
+				/*
+				 * At this step, it is possible that we were completing a receive operation, in this
+				 * case the write flag may be removed, add it if required.
+				 */
+				if (!client->output().empty()) {
+					m_listener.set(client->socket().handle(), Condition::Writable);
+				}
+
+				m_onRead(client, buffer);
+			}
+		} else {
+			/* Operation in progress */
+			updateFlags(client);
+		}
+	}
+
+	/*
+	 * Flush the output buffer.
+	 */
+	void processWrite(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
+	{
+		auto &output = client->output();
+		auto nsent = client->socket().send(output);
+
+		if (client->socket().action() == Action::None) {
+			/* 1. Create a copy of content that has been sent */
+			auto sent = output.substr(0, nsent);
+
+			/* 2. Erase the content sent */
+			output.erase(0, nsent);
+
+			/* 3. Update listener */
+			if (output.empty()) {
+				m_listener.unset(client->socket().handle(), Condition::Writable);
+			}
+
+			/* 4. Notify user */
+			m_onWrite(client, sent);
+		} else {
+			updateFlags(client);
+		}
+	}
+
+	void processSync(std::shared_ptr<StreamConnection<Address, Protocol>> &client, Condition flags)
+	{
+		try {
+			auto action = client->socket().action();
+
+			if (action == Action::Receive ||
+			    (action == Action::None && (flags & Condition::Readable) == Condition::Readable)) {
+				processRead(client);
+			} else if ((flags & Condition::Writable) == Condition::Writable) {
+				processWrite(client);
+			}
+		} catch (const Error &error) {
+			m_onDisconnection(client);
+			m_listener.remove(client->socket().handle());
+			m_clients.erase(client->socket().handle());
+		}
+	}
+
+public:
+	/**
+	 * Create a stream server with the specified address to bind.
+	 *
+	 * @param protocol the protocol (Tcp or Tls)
+	 * @param address the address to bind
+	 * @param max the max number to listen
+	 * @throw Error on errors
+	 */
+	StreamServer(Protocol protocol, const Address &address, int max = 128)
+		: m_master{std::move(protocol), address}
+	{
+		// TODO: m_onError
+		m_master.set(SOL_SOCKET, SO_REUSEADDR, 1);
+		m_master.bind(address);
+		m_master.listen(max);
+		m_listener.set(m_master.handle(), Condition::Readable);
+	}
+
+	/**
+	 * Set the connection handler, called when a new client is connected.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setConnectionHandler(ConnectionHandler handler)
+	{
+		m_onConnection = std::move(handler);
+	}
+
+	/**
+	 * Set the disconnection handler, called when a client died.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setDisconnectionHandler(DisconnectionHandler handler)
+	{
+		m_onDisconnection = std::move(handler);
+	}
+
+	/**
+	 * Set the receive handler, called when a client has sent something.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setReadHandler(ReadHandler handler)
+	{
+		m_onRead = std::move(handler);
+	}
+
+	/**
+	 * Set the writing handler, called when some data has been sent to a client.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setWriteHandler(WriteHandler handler)
+	{
+		m_onWrite = std::move(handler);
+	}
+
+	/**
+	 * Set the error handler, called when unrecoverable error has occured.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setErrorHandler(ErrorHandler handler)
+	{
+		m_onError = std::move(handler);
+	}
+
+	/**
+	 * Set the timeout handler, called when the selection has timeout.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setTimeoutHandler(TimeoutHandler handler)
+	{
+		m_onTimeout = std::move(handler);
+	}
+
+	/**
+	 * Poll for the next event.
+	 *
+	 * @param timeout the timeout (-1 for indefinitely)
+	 * @throw Error on errors
+	 */
+	void poll(int timeout = -1)
+	{
+		try {
+			auto st = m_listener.wait(timeout);
+
+			if (st.socket == m_master.handle()) {
+				/* New client */
+				processInitialAccept();
+			} else {
+				/* Recv / Send / Accept on a client */
+				auto client = m_clients[st.socket];
+
+				if (client->socket().state() == State::Accepted) {
+					processSync(client, st.flags);
+				} else {
+					processAccept(client, [&] () { client->socket().accept(); });
+				}
+			}
+		} catch (const Error &error) {
+			if (error.code() == Error::Timeout) {
+				m_onTimeout();
+			} else {
+				m_onError(error);
+			}
+		}
+	}
+};
+
+/* }}} */
+
+/*
+ * StreamClient
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ StreamClient */
+
+/**
+ * @class StreamClient
+ * @brief Client side connection to a server.
+ *
+ * This class is not thread safe and you must not call any of the functions from different threads.
+ */
+template <typename Address, typename Protocol>
+class StreamClient {
+public:
+	/**
+	 * Handler when connection is complete.
+	 */
+	using ConnectionHandler = Callback<>;
+
+	/**
+	 * Handler when data has been received.
+	 */
+	using ReadHandler = Callback<const std::string &>;
+
+	/**
+	 * Handler when data has been sent correctly.
+	 */
+	using WriteHandler = Callback<const std::string &>;
+
+	/**
+	 * Handler when disconnected.
+	 */
+	using DisconnectionHandler = Callback<>;
+
+	/**
+	 * Handler on unrecoverable error.
+	 */
+	using ErrorHandler = Callback<const Error &>;
+
+	/**
+	 * Handler when timeout occured.
+	 */
+	using TimeoutHandler = Callback<>;
+
+private:
+	/* Signals */
+	ConnectionHandler m_onConnection;
+	ReadHandler m_onRead;
+	WriteHandler m_onWrite;
+	DisconnectionHandler m_onDisconnection;
+	ErrorHandler m_onError;
+	TimeoutHandler m_onTimeout;
+
+	/* Socket */
+	Socket<Address, Protocol> m_socket;
+	Listener<> m_listener;
+
+	/* Output buffer */
+	std::string m_output;
+
+	/*
+	 * Update the flags after an uncompleted operation. This function must only be called when the operation
+	 * has not complete (e.g. connect, recv, send).
+	 */
+	void updateFlags()
+	{
+		assert(m_socket.action() != Action::None);
+
+		m_listener.remove(m_socket.handle());
+		m_listener.set(m_socket.handle(), m_socket.condition());
+	}
+
+	/*
+	 * This is the generic connect helper, it will be used to both initiate the connection or to continue the
+	 * connection process if needed.
+	 *
+	 * Thus the template parameter is the appropriate function to call either, m_socket.connect(address) or
+	 * m_socket.connect().
+	 *
+	 * See poll() and connect() to understand.
+	 */
+	template <typename ConnectCall>
+	void processConnect(const ConnectCall &connectFunc)
+	{
+		/* Call m_socket.connect() or m_socket.connect(address) */
+		connectFunc();
+
+		/* Remove entirely */
+		m_listener.remove(m_socket.handle());
+
+		if (m_socket.state() == State::Connected) {
+			m_onConnection();
+			m_listener.set(m_socket.handle(), Condition::Readable);
+		} else {
+			/* Connection still in progress */
+			updateFlags();
+		}
+	}
+
+	/*
+	 * Receive or complete the receive command, if the command is not complete, the listener is updated
+	 * accordingly.
+	 */
+	void processRead()
+	{
+		auto received = m_socket.recv(512);
+
+		if (m_socket.action() == Action::None) {
+			/* 0 means disconnection */
+			if (received.empty()) {
+				m_onDisconnection();
+			} else {
+				/*
+				 * At this step, it is possible that we were completing a receive operation, in this
+				 * case the write flag may be removed, add it if required.
+				 */
+				if (m_output.empty()) {
+					m_listener.unset(m_socket.handle(), Condition::Writable);
+				}
+
+				m_onRead(received);
+			}
+		} else {
+			/* Receive operation in progress */
+			updateFlags();
+		}
+	}
+
+	/*
+	 * Send or complete the send command, if the command is not complete, the listener is updated
+	 * accordingly.
+	 */
+	void processWrite()
+	{
+		auto nsent = m_socket.send(m_output);
+
+		if (m_socket.action() == Action::None) {
+			/* 1. Make a copy of what has been sent */
+			auto sent = m_output.substr(0, nsent);
+
+			/* 2. Erase sent content */
+			m_output.erase(0, nsent);
+
+			/* 3. Update flags if needed */
+			if (m_output.empty()) {
+				m_listener.unset(m_socket.handle(), Condition::Writable);
+			}
+
+			/* 4. Notify user */
+			m_onWrite(sent);
+		} else {
+			/* Send operation in progress */
+			updateFlags();
+		}
+	}
+
+	/*
+	 * Receive or send.
+	 */
+	void processSync(Condition condition)
+	{
+		if ((m_socket.action() == Action::Receive) ||
+		    (m_socket.action() == Action::None && (condition & Condition::Readable) == Condition::Readable)) {
+			processRead();
+		} else {
+			processWrite();
+		}
+	}
+
+public:
+	/**
+	 * Create a client. The client is automatically marked as non-blocking.
+	 *
+	 * @param protocol the protocol (Tcp or Tls)
+	 * @param address the optional address
+	 * @throw net::Error on failures
+	 */
+	StreamClient(Protocol protocol = {}, const Address &address = {})
+		: m_socket{std::move(protocol), address}
+	{
+		m_socket.set(net::option::SockBlockMode{false});
+		m_listener.set(m_socket.handle(), Condition::Readable);
+	}
+
+	/**
+	 * Set the connection handler, called when the connection succeed.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setConnectionHandler(ConnectionHandler handler)
+	{
+		m_onConnection = std::move(handler);
+	}
+
+	/**
+	 * Set the disconnection handler, called when the server closed the connection.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setDisconnectionHandler(DisconnectionHandler handler)
+	{
+		m_onDisconnection = std::move(handler);
+	}
+
+	/**
+	 * Set the read handler, called when we received something.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setReadHandler(ReadHandler handler)
+	{
+		m_onRead = std::move(handler);
+	}
+
+	/**
+	 * Set the write handler, called when we successfully sent data.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setWriteHandler(WriteHandler handler)
+	{
+		m_onWrite = std::move(handler);
+	}
+
+	/**
+	 * Set the error handler, called when unexpected error occurs.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setErrorHandler(ErrorHandler handler)
+	{
+		m_onError = std::move(handler);
+	}
+
+	/**
+	 * Connect to a server, this function may connect immediately or not in any case the connection handler
+	 * will be called when the connection completed.
+	 *
+	 * @param address the address to connect to
+	 */
+	void connect(const Address &address) noexcept
+	{
+		assert(m_socket.state() == State::Open);
+
+		processConnect([&] () { m_socket.connect(address); });
+	}
+
+	/**
+	 * Asynchronously send data to the server.
+	 *
+	 * @param str the data to append
+	 */
+	void send(std::string str)
+	{
+		m_output += str;
+
+		/* Don't update the listener if there is a pending operation */
+		if (m_socket.state() == State::Connected && m_socket.action() == Action::None && !m_output.empty()) {
+			m_listener.set(m_socket.handle(), Condition::Writable);
+		}
+	}
+
+	/**
+	 * Wait for the next event.
+	 *
+	 * @param timeout the time to wait in milliseconds
+	 * @throw Error on errors
+	 */
+	void poll(int timeout = -1) noexcept
+	{
+		try {
+			auto st = m_listener.wait(timeout);
+
+			if (m_socket.state() != State::Connected) {
+				/* Continue the connection */
+				processConnect([&] () { m_socket.connect(); });
+			} else {
+				/* Read / Write */
+				processSync(st.flags);
+			}
+		} catch (const Error &error) {
+			if (error.code() == Error::Timeout) {
+				m_onTimeout();
+			} else {
+				m_listener.remove(m_socket.handle());
+				m_onError(error);
+			}
+		}
+	}
+};
+
+/* }}} */
+
+} // !net
+
+#endif // !_SOCKETS_H_
--- a/C++/modules/Xdg/Xdg.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Xdg.cpp -- XDG directory specifications
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <cstdlib>
-#include <stdexcept>
-#include <sstream>
-
-#include "Xdg.h"
-
-namespace {
-
-bool isabsolute(const std::string &path)
-{
-	return path.length() > 0 && path[0] == '/';
-}
-
-std::vector<std::string> split(const std::string &arg)
-{
-	std::stringstream iss(arg);
-	std::string item;
-	std::vector<std::string> elems;
-
-	while (std::getline(iss, item, ':'))
-		if (isabsolute(item))
-			elems.push_back(item);
-
-	return elems;
-}
-
-std::string envOrHome(const std::string &var, const std::string &repl)
-{
-	auto value = getenv(var.c_str());
-
-	if (value == nullptr || !isabsolute(value)) {
-		auto home = getenv("HOME");
-
-		if (home == nullptr)
-			throw std::runtime_error("could not get home directory");
-
-		return std::string(home) + "/" + repl;
-	}
-
-	return value;
-}
-
-std::vector<std::string> listOrDefaults(const std::string &var, const std::vector<std::string> &list)
-{
-	auto value = getenv(var.c_str());
-
-	if (!value)
-		return list;
-
-	// No valid item at all? Use defaults
-	auto result = split(value);
-
-	return (result.size() == 0) ? list : result;
-}
-
-} // !namespace
-
-Xdg::Xdg()
-{
-	m_configHome	= envOrHome("XDG_CONFIG_HOME", ".config");
-	m_dataHome	= envOrHome("XDG_DATA_HOME", ".local/share");
-	m_cacheHome	= envOrHome("XDG_CACHE_HOME", ".cache");
-
-	m_configDirs	= listOrDefaults("XDG_CONFIG_DIRS", { "/etc/xdg" });
-	m_dataDirs	= listOrDefaults("XDG_DATA_DIRS", { "/usr/local/share", "/usr/share" });
-
-	/*
-	 * Runtime directory is a special case and does not have a replacement, the
-	 * application should manage this by itself.
-	 */
-	auto runtime = getenv("XDG_RUNTIME_DIR");
-	if (runtime && isabsolute(runtime))
-		m_runtimeDir = runtime;
-}
-
-const std::string &Xdg::configHome() const noexcept
-{
-	return m_configHome;
-}
-
-const std::string &Xdg::dataHome() const noexcept
-{
-	return m_dataHome;
-}
-
-const std::string &Xdg::cacheHome() const noexcept
-{
-	return m_cacheHome;
-}
-
-const std::string &Xdg::runtimeDir() const
-{
-	if (m_runtimeDir.size() == 0)
-		throw std::runtime_error("XDG_RUNTIME_DIR is not set");
-
-	return m_runtimeDir;
-}
-
-const Xdg::List &Xdg::configDirs() const noexcept
-{
-	return m_configDirs;
-}
-
-const Xdg::List &Xdg::dataDirs() const noexcept
-{
-	return m_dataDirs;
-}
--- a/C++/modules/Xdg/Xdg.h	Thu Nov 12 11:46:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Xdg.h -- XDG directory specifications
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _XDG_H_
-#define _XDG_H_
-
-#include <vector>
-#include <string>
-
-/**
- * @class Xdg
- * @brief XDG specifications
- *
- * Read and get XDG directories. This file contains exports thingies so it can
- * compiles successfully on Windows but its usage is discouraged.
- */
-class Xdg {
-public:
-	using List	= std::vector<std::string>;
-
-private:
-	std::string	m_configHome;
-	std::string	m_dataHome;
-	std::string	m_cacheHome;
-	std::string	m_runtimeDir;
-	List		m_configDirs;
-	List		m_dataDirs;
-
-public:
-	/**
-	 * Open an xdg instance and load directories.
-	 *
-	 * @throw std::runtime_error on failures
-	 */
-	Xdg();
-
-	/**
-	 * Get the config directory. ${XDG_CONFIG_HOME} or ${HOME}/.config
-	 *
-	 * @return the config directory
-	 */
-	const std::string &configHome() const noexcept;
-
-	/**
-	 * Get the data directory. ${XDG_DATA_HOME} or ${HOME}/.local/share
-	 *
-	 * @return the data directory
-	 */
-	const std::string &dataHome() const noexcept;
-
-	/**
-	 * Get the cache directory. ${XDG_CACHE_HOME} or ${HOME}/.cache
-	 *
-	 * @return the cache directory
-	 */
-	const std::string &cacheHome() const noexcept;
-
-	/**
-	 * Get the runtime directory. ${XDG_RUNTIME_DIR} must be set,
-	 * if not, it throws an exception.
-	 *
-	 * The XDG standard says that application should handle XDG_RUNTIME_DIR by
-	 * themselves.
-	 *
-	 * @return the runtime directory
-	 * @throw std::runtime_error on error
-	 */
-	const std::string &runtimeDir() const;
-
-	/**
-	 * Get the standard config directories. ${XDG_CONFIG_DIRS} or { "/etc/xdg" }
-	 *
-	 * @return the list of config directories
-	 */
-	const List &configDirs() const noexcept;
-
-	/**
-	 * Get the data directories. ${XDG_DATA_DIRS} or { "/usr/local/share", "/usr/share" }
-	 *
-	 * @return the list of data directories
-	 */
-	const List &dataDirs() const noexcept;
-};
-
-#endif // !_XDG_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Xdg/xdg.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,125 @@
+/*
+ * xdg.cpp -- XDG directory specifications
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cstdlib>
+#include <stdexcept>
+#include <sstream>
+
+#include "xdg.h"
+
+namespace {
+
+bool isabsolute(const std::string &path)
+{
+	return path.length() > 0 && path[0] == '/';
+}
+
+std::vector<std::string> split(const std::string &arg)
+{
+	std::stringstream iss(arg);
+	std::string item;
+	std::vector<std::string> elems;
+
+	while (std::getline(iss, item, ':'))
+		if (isabsolute(item))
+			elems.push_back(item);
+
+	return elems;
+}
+
+std::string envOrHome(const std::string &var, const std::string &repl)
+{
+	auto value = getenv(var.c_str());
+
+	if (value == nullptr || !isabsolute(value)) {
+		auto home = getenv("HOME");
+
+		if (home == nullptr)
+			throw std::runtime_error("could not get home directory");
+
+		return std::string(home) + "/" + repl;
+	}
+
+	return value;
+}
+
+std::vector<std::string> listOrDefaults(const std::string &var, const std::vector<std::string> &list)
+{
+	auto value = getenv(var.c_str());
+
+	if (!value)
+		return list;
+
+	// No valid item at all? Use defaults
+	auto result = split(value);
+
+	return (result.size() == 0) ? list : result;
+}
+
+} // !namespace
+
+Xdg::Xdg()
+{
+	m_configHome	= envOrHome("XDG_CONFIG_HOME", ".config");
+	m_dataHome	= envOrHome("XDG_DATA_HOME", ".local/share");
+	m_cacheHome	= envOrHome("XDG_CACHE_HOME", ".cache");
+
+	m_configDirs	= listOrDefaults("XDG_CONFIG_DIRS", { "/etc/xdg" });
+	m_dataDirs	= listOrDefaults("XDG_DATA_DIRS", { "/usr/local/share", "/usr/share" });
+
+	/*
+	 * Runtime directory is a special case and does not have a replacement, the
+	 * application should manage this by itself.
+	 */
+	auto runtime = getenv("XDG_RUNTIME_DIR");
+	if (runtime && isabsolute(runtime))
+		m_runtimeDir = runtime;
+}
+
+const std::string &Xdg::configHome() const noexcept
+{
+	return m_configHome;
+}
+
+const std::string &Xdg::dataHome() const noexcept
+{
+	return m_dataHome;
+}
+
+const std::string &Xdg::cacheHome() const noexcept
+{
+	return m_cacheHome;
+}
+
+const std::string &Xdg::runtimeDir() const
+{
+	if (m_runtimeDir.size() == 0)
+		throw std::runtime_error("XDG_RUNTIME_DIR is not set");
+
+	return m_runtimeDir;
+}
+
+const Xdg::List &Xdg::configDirs() const noexcept
+{
+	return m_configDirs;
+}
+
+const Xdg::List &Xdg::dataDirs() const noexcept
+{
+	return m_dataDirs;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Xdg/xdg.h	Thu Nov 12 21:53:36 2015 +0100
@@ -0,0 +1,100 @@
+/*
+ * xdg.h -- XDG directory specifications
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _XDG_H_
+#define _XDG_H_
+
+#include <vector>
+#include <string>
+
+/**
+ * @class Xdg
+ * @brief XDG specifications
+ *
+ * Read and get XDG directories. This file contains exports thingies so it can
+ * compiles successfully on Windows but its usage is discouraged.
+ */
+class Xdg {
+public:
+	using List	= std::vector<std::string>;
+
+private:
+	std::string	m_configHome;
+	std::string	m_dataHome;
+	std::string	m_cacheHome;
+	std::string	m_runtimeDir;
+	List		m_configDirs;
+	List		m_dataDirs;
+
+public:
+	/**
+	 * Open an xdg instance and load directories.
+	 *
+	 * @throw std::runtime_error on failures
+	 */
+	Xdg();
+
+	/**
+	 * Get the config directory. ${XDG_CONFIG_HOME} or ${HOME}/.config
+	 *
+	 * @return the config directory
+	 */
+	const std::string &configHome() const noexcept;
+
+	/**
+	 * Get the data directory. ${XDG_DATA_HOME} or ${HOME}/.local/share
+	 *
+	 * @return the data directory
+	 */
+	const std::string &dataHome() const noexcept;
+
+	/**
+	 * Get the cache directory. ${XDG_CACHE_HOME} or ${HOME}/.cache
+	 *
+	 * @return the cache directory
+	 */
+	const std::string &cacheHome() const noexcept;
+
+	/**
+	 * Get the runtime directory. ${XDG_RUNTIME_DIR} must be set,
+	 * if not, it throws an exception.
+	 *
+	 * The XDG standard says that application should handle XDG_RUNTIME_DIR by
+	 * themselves.
+	 *
+	 * @return the runtime directory
+	 * @throw std::runtime_error on error
+	 */
+	const std::string &runtimeDir() const;
+
+	/**
+	 * Get the standard config directories. ${XDG_CONFIG_DIRS} or { "/etc/xdg" }
+	 *
+	 * @return the list of config directories
+	 */
+	const List &configDirs() const noexcept;
+
+	/**
+	 * Get the data directories. ${XDG_DATA_DIRS} or { "/usr/local/share", "/usr/share" }
+	 *
+	 * @return the list of data directories
+	 */
+	const List &dataDirs() const noexcept;
+};
+
+#endif // !_XDG_H_
--- a/C++/tests/Base64/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Base64/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <Base64.h>
+#include <base64.h>
 
 TEST(Lookup, lookup)
 {
--- a/C++/tests/Directory/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Directory/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <Directory.h>
+#include <directory.h>
 
 TEST(Filter, withDot)
 {
@@ -112,4 +112,4 @@
 	testing::InitGoogleTest(&argc, argv);
 
 	return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
--- a/C++/tests/Dynlib/Plugin.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Dynlib/Plugin.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -1,6 +1,6 @@
 #include <string>
 
-#include <Dynlib.h>
+#include <dynlib.h>
 
 extern "C" {
 
--- a/C++/tests/Dynlib/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Dynlib/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -20,7 +20,7 @@
 
 #include <gtest/gtest.h>
 
-#include <Dynlib.h>
+#include <dynlib.h>
 
 /*
  * NOTE: the EXTENSION is defined by CMake in the form of a string
--- a/C++/tests/Hash/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Hash/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <Hash.h>
+#include <hash.h>
 
 /*
  * We test the "Hello World" message in all cryptographic functions.
--- a/C++/tests/Ini/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Ini/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -20,7 +20,7 @@
 
 #include <gtest/gtest.h>
 
-#include <Ini.h>
+#include <ini.h>
 
 class BasicTest : public testing::Test {
 protected:
--- a/C++/tests/Js/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Js/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <Js.h>
+#include <js.h>
 
 /*
  * TODO:
@@ -751,12 +751,12 @@
 
 	{
 		Context context;
-	
+
 		ASSERT_EQ(0, context.top());
 		context.push(Pointer<Cat>{p});
 		Cat *p2 = context.get<Pointer<Cat>>(-1);
 		ASSERT_EQ(1, context.top());
-	
+
 		p2->m_updated = true;
 		ASSERT_TRUE(p->m_updated);
 	}
--- a/C++/tests/Json/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Json/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -21,7 +21,7 @@
 
 #include <gtest/gtest.h>
 
-#include "Json.h"
+#include "json.h"
 
 /*
  * Miscellaneous
--- a/C++/tests/OptionParser/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/OptionParser/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <OptionParser.h>
+#include <options.h>
 
 /* --------------------------------------------------------
  * Short options
@@ -28,12 +28,12 @@
 {
 	std::vector<std::string> args{"-a", "-b"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-a", false },
 		{ "-b", false }
 	};
 
-	parser::Result pack = parser::read(args, options);
+	option::Result pack = option::read(args, options);
 
 	ASSERT_EQ(2U, pack.size());
 	ASSERT_EQ(0U, args.size());
@@ -46,12 +46,12 @@
 {
 	std::vector<std::string> args{"-v", "-cfoo.conf"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-v", false },
 		{ "-c", true  }
 	};
 
-	parser::Result pack = parser::read(args, options);
+	option::Result pack = option::read(args, options);
 
 	ASSERT_EQ(2U, pack.size());
 	ASSERT_EQ(0U, args.size());
@@ -64,12 +64,12 @@
 {
 	std::vector<std::string> args{"-v", "-c", "foo.conf"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-v", false },
 		{ "-c", true  }
 	};
 
-	parser::Result pack = parser::read(args, options);
+	option::Result pack = option::read(args, options);
 
 	ASSERT_EQ(2U, pack.size());
 	ASSERT_EQ(0U, args.size());
@@ -82,13 +82,13 @@
 {
 	std::vector<std::string> args{"-abc"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-a", false },
 		{ "-b", false },
 		{ "-c", false },
 	};
 
-	parser::Result pack = parser::read(args, options);
+	option::Result pack = option::read(args, options);
 
 	ASSERT_EQ(3U, pack.size());
 	ASSERT_EQ(0U, args.size());
@@ -102,13 +102,13 @@
 {
 	std::vector<std::string> args{"-vdcfoo.conf"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-v", false },
 		{ "-d", false },
 		{ "-c", true },
 	};
 
-	parser::Result pack = parser::read(args, options);
+	option::Result pack = option::read(args, options);
 
 	ASSERT_EQ(3U, pack.size());
 	ASSERT_EQ(0U, args.size());
@@ -126,12 +126,12 @@
 {
 	std::vector<std::string> args{"--fullscreen"};
 
-	parser::Options options{
+	option::Options options{
 		{ "--verbose",		false },
 		{ "--fullscreen",	false }
 	};
 
-	parser::Result pack = parser::read(args, options);
+	option::Result pack = option::read(args, options);
 
 	ASSERT_EQ(1U, pack.size());
 	ASSERT_EQ(0U, args.size());
@@ -143,12 +143,12 @@
 {
 	std::vector<std::string> args{"--config", "config.conf", "--level", "2"};
 
-	parser::Options options{
+	option::Options options{
 		{ "--config",	true },
 		{ "--level",	true }
 	};
 
-	parser::Result pack = parser::read(args, options);
+	option::Result pack = option::read(args, options);
 
 	ASSERT_EQ(2U, pack.size());
 	ASSERT_EQ(0U, args.size());
@@ -166,11 +166,11 @@
 	std::vector<std::string> args{"-v", "install", "-y", "irccd"};
 	std::vector<std::string> expected{"install", "-y", "irccd"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-v",	false }
 	};
 
-	parser::Result pack = parser::read(args, options);
+	option::Result pack = option::read(args, options);
 
 	ASSERT_EQ(1U, pack.size());
 	ASSERT_EQ(3U, args.size());
@@ -183,15 +183,15 @@
 {
 	std::vector<std::string> args{"-c"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-c",	true }
 	};
 
 	try {
-		parser::Result pack = parser::read(args, options);
+		option::Result pack = option::read(args, options);
 
 		FAIL() << "exception expected";
-	} catch (const parser::MissingValue &) {
+	} catch (const option::MissingValue &) {
 	}
 }
 
@@ -199,16 +199,16 @@
 {
 	std::vector<std::string> args{"-vc"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-v", false },
 		{ "-c",	true }
 	};
 
 	try {
-		parser::Result pack = parser::read(args, options);
+		option::Result pack = option::read(args, options);
 
 		FAIL() << "exception expected";
-	} catch (const parser::MissingValue &) {
+	} catch (const option::MissingValue &) {
 	}
 }
 
@@ -216,15 +216,15 @@
 {
 	std::vector<std::string> args{"--config"};
 
-	parser::Options options{
+	option::Options options{
 		{ "--config", true }
 	};
 
 	try {
-		parser::Result pack = parser::read(args, options);
+		option::Result pack = option::read(args, options);
 
 		FAIL() << "exception expected";
-	} catch (const parser::MissingValue &) {
+	} catch (const option::MissingValue &) {
 	}
 }
 
@@ -232,15 +232,15 @@
 {
 	std::vector<std::string> args{"-x"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-v", true }
 	};
 
 	try {
-		parser::Result pack = parser::read(args, options);
+		option::Result pack = option::read(args, options);
 
 		FAIL() << "exception expected";
-	} catch (const parser::InvalidOption &) {
+	} catch (const option::InvalidOption &) {
 	}
 }
 
@@ -248,15 +248,15 @@
 {
 	std::vector<std::string> args{"--destroy"};
 
-	parser::Options options{
+	option::Options options{
 		{ "--verbose", true }
 	};
 
 	try {
-		parser::Result pack = parser::read(args, options);
+		option::Result pack = option::read(args, options);
 
 		FAIL() << "exception expected";
-	} catch (const parser::InvalidOption &) {
+	} catch (const option::InvalidOption &) {
 	}
 }
 
@@ -264,15 +264,15 @@
 {
 	std::vector<std::string> args{"-vx"};
 
-	parser::Options options{
+	option::Options options{
 		{ "-x", true }
 	};
 
 	try {
-		parser::Result pack = parser::read(args, options);
+		option::Result pack = option::read(args, options);
 
 		FAIL() << "exception expected";
-	} catch (const parser::InvalidOption &) {
+	} catch (const option::InvalidOption &) {
 	}
 }
 
--- a/C++/tests/Socket/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Socket/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -24,7 +24,7 @@
 
 #include <gtest/gtest.h>
 
-#include <Sockets.h>
+#include <sockets.h>
 
 using namespace net;
 using namespace net::address;
--- a/C++/tests/Xdg/main.cpp	Thu Nov 12 11:46:04 2015 +0100
+++ b/C++/tests/Xdg/main.cpp	Thu Nov 12 21:53:36 2015 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <Xdg.h>
+#include <xdg.h>
 
 using namespace testing;
 
--- a/CMakeLists.txt	Thu Nov 12 11:46:04 2015 +0100
+++ b/CMakeLists.txt	Thu Nov 12 21:53:36 2015 +0100
@@ -123,8 +123,8 @@
 	NAME Base64
 	DIRECTORY Base64
 	SOURCES
-		${code_SOURCE_DIR}/C++/modules/Base64/Base64.cpp
-		${code_SOURCE_DIR}/C++/modules/Base64/Base64.h
+		${code_SOURCE_DIR}/C++/modules/Base64/base64.cpp
+		${code_SOURCE_DIR}/C++/modules/Base64/base64.h
 )
 
 # ---------------------------------------------------------
@@ -142,8 +142,8 @@
 	NAME Directory
 	DIRECTORY Directory
 	SOURCES
-		${code_SOURCE_DIR}/C++/modules/Directory/Directory.cpp
-		${code_SOURCE_DIR}/C++/modules/Directory/Directory.h
+		${code_SOURCE_DIR}/C++/modules/Directory/directory.cpp
+		${code_SOURCE_DIR}/C++/modules/Directory/directory.h
 )
 
 # ---------------------------------------------------------
@@ -165,8 +165,8 @@
 	NAME Dynlib
 	DIRECTORY Dynlib
 	SOURCES
-		${code_SOURCE_DIR}/C++/modules/Dynlib/Dynlib.cpp
-		${code_SOURCE_DIR}/C++/modules/Dynlib/Dynlib.h
+		${code_SOURCE_DIR}/C++/modules/Dynlib/dynlib.cpp
+		${code_SOURCE_DIR}/C++/modules/Dynlib/dynlib.h
 )
 
 if (WITH_DYNLIB)
@@ -208,8 +208,8 @@
 		LIBRARIES ${OPENSSL_LIBRARIES}
 		INCLUDES ${OPENSSL_INCLUDE_DIR}
 		SOURCES
-			${code_SOURCE_DIR}/C++/modules/Hash/Hash.cpp
-			${code_SOURCE_DIR}/C++/modules/Hash/Hash.h
+			${code_SOURCE_DIR}/C++/modules/Hash/hash.cpp
+			${code_SOURCE_DIR}/C++/modules/Hash/hash.h
 	)
 endif ()
 
@@ -226,8 +226,8 @@
 	NAME Ini
 	DIRECTORY Ini
 	SOURCES
-		${code_SOURCE_DIR}/C++/modules/Ini/Ini.cpp
-		${code_SOURCE_DIR}/C++/modules/Ini/Ini.h
+		${code_SOURCE_DIR}/C++/modules/Ini/ini.cpp
+		${code_SOURCE_DIR}/C++/modules/Ini/ini.h
 	LIBRARIES
 		${INI_LIBRARIES}
 	RESOURCES
@@ -256,8 +256,8 @@
 	DIRECTORY Js
 	LIBRARIES duktape
 	SOURCES
-		${code_SOURCE_DIR}/C++/modules/Js/Js.cpp
-		${code_SOURCE_DIR}/C++/modules/Js/Js.h
+		${code_SOURCE_DIR}/C++/modules/Js/js.cpp
+		${code_SOURCE_DIR}/C++/modules/Js/js.h
 )
 
 # ---------------------------------------------------------
@@ -272,8 +272,8 @@
 		INCLUDES ${Jansson_INCLUDE_DIRS}
 		LIBRARIES ${Jansson_LIBRARIES}
 		SOURCES
-			${code_SOURCE_DIR}/C++/modules/Json/Json.cpp
-			${code_SOURCE_DIR}/C++/modules/Json/Json.h
+			${code_SOURCE_DIR}/C++/modules/Json/json.cpp
+			${code_SOURCE_DIR}/C++/modules/Json/json.h
 		RESOURCES
 			${code_SOURCE_DIR}/C++/tests/Json/data/array-all.json
 			${code_SOURCE_DIR}/C++/tests/Json/data/array.json
@@ -292,8 +292,8 @@
 	NAME OptionParser
 	DIRECTORY OptionParser
 	SOURCES
-		${code_SOURCE_DIR}/C++/modules/OptionParser/OptionParser.cpp
-		${code_SOURCE_DIR}/C++/modules/OptionParser/OptionParser.h
+		${code_SOURCE_DIR}/C++/modules/OptionParser/options.cpp
+		${code_SOURCE_DIR}/C++/modules/OptionParser/options.h
 )
 
 # ---------------------------------------------------------
@@ -314,8 +314,8 @@
 			${SOCKET_LIBRARIES}
 			${OPENSSL_LIBRARIES}
 		SOURCES
-			${code_SOURCE_DIR}/C++/modules/Socket/Sockets.cpp
-			${code_SOURCE_DIR}/C++/modules/Socket/Sockets.h
+			${code_SOURCE_DIR}/C++/modules/Socket/sockets.cpp
+			${code_SOURCE_DIR}/C++/modules/Socket/sockets.h
 		RESOURCES
 			${code_SOURCE_DIR}/C++/tests/Socket/test.crt
 			${code_SOURCE_DIR}/C++/tests/Socket/test.key
@@ -357,8 +357,8 @@
 		NAME Xdg
 		DIRECTORY Xdg
 		SOURCES
-			${code_SOURCE_DIR}/C++/modules/Xdg/Xdg.cpp
-			${code_SOURCE_DIR}/C++/modules/Xdg/Xdg.h
+			${code_SOURCE_DIR}/C++/modules/Xdg/xdg.cpp
+			${code_SOURCE_DIR}/C++/modules/Xdg/xdg.h
 	)
 endif ()