changeset 42:a47a4477f347

Misc: new style, closes #578
author David Demelier <markand@malikania.fr>
date Tue, 29 Nov 2016 21:21:36 +0100
parents 3645200f46bf
children fabbe1759cec
files client/main.cpp database/sqlite/src/account.cpp libclient-js/CMakeLists.txt libclient-js/malikania/js-animation.cpp libclient-js/malikania/js-animation.hpp libclient-js/malikania/js-animator.cpp libclient-js/malikania/js-animator.hpp libclient-js/malikania/js-client-resources-loader.cpp libclient-js/malikania/js-client-resources-loader.hpp libclient-js/malikania/js-client-target.cpp libclient-js/malikania/js-client-target.hpp libclient-js/malikania/js-client.cpp libclient-js/malikania/js-client.hpp libclient-js/malikania/js-color.cpp libclient-js/malikania/js-color.hpp libclient-js/malikania/js-font.cpp libclient-js/malikania/js-font.hpp libclient-js/malikania/js-image.cpp libclient-js/malikania/js-image.hpp libclient-js/malikania/js-line.cpp libclient-js/malikania/js-line.hpp libclient-js/malikania/js-point.cpp libclient-js/malikania/js-point.hpp libclient-js/malikania/js-rectangle.cpp libclient-js/malikania/js-rectangle.hpp libclient-js/malikania/js-size.cpp libclient-js/malikania/js-size.hpp libclient-js/malikania/js-sprite.cpp libclient-js/malikania/js-sprite.hpp libclient-js/malikania/js-window.cpp libclient-js/malikania/js-window.hpp libclient-js/malikania/js_animation.cpp libclient-js/malikania/js_animation.hpp libclient-js/malikania/js_animator.cpp libclient-js/malikania/js_animator.hpp libclient-js/malikania/js_client.cpp libclient-js/malikania/js_client.hpp libclient-js/malikania/js_client_resources_loader.cpp libclient-js/malikania/js_client_resources_loader.hpp libclient-js/malikania/js_client_target.cpp libclient-js/malikania/js_client_target.hpp libclient-js/malikania/js_color.cpp libclient-js/malikania/js_color.hpp libclient-js/malikania/js_font.cpp libclient-js/malikania/js_font.hpp libclient-js/malikania/js_image.cpp libclient-js/malikania/js_image.hpp libclient-js/malikania/js_line.cpp libclient-js/malikania/js_line.hpp libclient-js/malikania/js_point.cpp libclient-js/malikania/js_point.hpp libclient-js/malikania/js_rectangle.cpp libclient-js/malikania/js_rectangle.hpp libclient-js/malikania/js_size.cpp libclient-js/malikania/js_size.hpp libclient-js/malikania/js_sprite.cpp libclient-js/malikania/js_sprite.hpp libclient-js/malikania/js_window.cpp libclient-js/malikania/js_window.hpp libclient/CMakeLists.txt libclient/malikania/animation.hpp libclient/malikania/animator.cpp libclient/malikania/animator.hpp libclient/malikania/backend/sdl/font-backend.cpp libclient/malikania/backend/sdl/font-backend.hpp libclient/malikania/backend/sdl/font_backend.cpp libclient/malikania/backend/sdl/font_backend.hpp libclient/malikania/backend/sdl/image-backend.cpp libclient/malikania/backend/sdl/image-backend.hpp libclient/malikania/backend/sdl/image_backend.cpp libclient/malikania/backend/sdl/image_backend.hpp libclient/malikania/backend/sdl/window-backend.cpp libclient/malikania/backend/sdl/window-backend.hpp libclient/malikania/backend/sdl/window_backend.cpp libclient/malikania/backend/sdl/window_backend.hpp libclient/malikania/client-resources-loader.cpp libclient/malikania/client-resources-loader.hpp libclient/malikania/client.hpp libclient/malikania/client_resources_loader.cpp libclient/malikania/client_resources_loader.hpp libclient/malikania/color.cpp libclient/malikania/color.hpp libclient/malikania/font.cpp libclient/malikania/font.hpp libclient/malikania/image.cpp libclient/malikania/image.hpp libclient/malikania/line.hpp libclient/malikania/point.hpp libclient/malikania/rectangle.hpp libclient/malikania/size.hpp libclient/malikania/sprite.cpp libclient/malikania/sprite.hpp libclient/malikania/window.cpp libclient/malikania/window.hpp libcommon-js/CMakeLists.txt libcommon-js/malikania/js-elapsed-timer.cpp libcommon-js/malikania/js-elapsed-timer.hpp libcommon-js/malikania/js-resources-loader.cpp libcommon-js/malikania/js-resources-loader.hpp libcommon-js/malikania/js_elapsed_timer.cpp libcommon-js/malikania/js_elapsed_timer.hpp libcommon-js/malikania/js_resources_loader.cpp libcommon-js/malikania/js_resources_loader.hpp libcommon/CMakeLists.txt libcommon/malikania/application.cpp libcommon/malikania/application.hpp libcommon/malikania/backend/sdl/common-sdl.cpp libcommon/malikania/backend/sdl/common-sdl.hpp libcommon/malikania/backend/sdl/sdl_util.cpp libcommon/malikania/backend/sdl/sdl_util.hpp libcommon/malikania/game.hpp libcommon/malikania/id.hpp libcommon/malikania/resources-loader.cpp libcommon/malikania/resources-loader.hpp libcommon/malikania/resources-locator.cpp libcommon/malikania/resources-locator.hpp libcommon/malikania/resources_loader.cpp libcommon/malikania/resources_loader.hpp libcommon/malikania/resources_locator.cpp libcommon/malikania/resources_locator.hpp libcommon/malikania/signals.hpp libcommon/malikania/util.cpp libcommon/malikania/util.hpp libserver/CMakeLists.txt libserver/malikania/account.hpp libserver/malikania/account_dao.cpp libserver/malikania/account_dao.hpp libserver/malikania/connection-service.cpp libserver/malikania/connection-service.hpp libserver/malikania/connection-state-authenticating.cpp libserver/malikania/connection-state-authenticating.hpp libserver/malikania/connection-state-closing.cpp libserver/malikania/connection-state-closing.hpp libserver/malikania/connection-state-disconnected.cpp libserver/malikania/connection-state-disconnected.hpp libserver/malikania/connection-state-greeting.cpp libserver/malikania/connection-state-greeting.hpp libserver/malikania/connection-state-ready.cpp libserver/malikania/connection-state-ready.hpp libserver/malikania/connection-state.cpp libserver/malikania/connection-state.hpp libserver/malikania/connection_service.cpp libserver/malikania/connection_service.hpp libserver/malikania/connection_state.cpp libserver/malikania/connection_state.hpp libserver/malikania/connection_state_authenticating.cpp libserver/malikania/connection_state_authenticating.hpp libserver/malikania/connection_state_closing.cpp libserver/malikania/connection_state_closing.hpp libserver/malikania/connection_state_disconnected.cpp libserver/malikania/connection_state_disconnected.hpp libserver/malikania/connection_state_greeting.cpp libserver/malikania/connection_state_greeting.hpp libserver/malikania/connection_state_ready.cpp libserver/malikania/connection_state_ready.hpp libserver/malikania/dao-account.cpp libserver/malikania/dao-account.hpp libserver/malikania/database.cpp libserver/malikania/database.hpp server/main.cpp tests/libclient/animation/main.cpp tests/libclient/color/main.cpp tests/libclient/font/main.cpp tests/libclient/image/main.cpp tests/libclient/js-animation/main.cpp tests/libclient/js-color/main.cpp tests/libclient/js-font/main.cpp tests/libclient/js-image/main.cpp tests/libclient/js-line/main.cpp tests/libclient/js-point/main.cpp tests/libclient/js-rectangle/main.cpp tests/libclient/js-size/main.cpp tests/libclient/js-sprite/main.cpp tests/libclient/js-window/main.cpp tests/libclient/line/main.cpp tests/libclient/point/main.cpp tests/libclient/rectangle/main.cpp tests/libclient/size/main.cpp tests/libclient/sprite/main.cpp tests/libcommon/js-elapsed-timer/main.cpp tests/libserver/dao-account/main.cpp tests/libserver/dao-account/test.hpp tests/libserver/id/main.cpp
diffstat 183 files changed, 6525 insertions(+), 7090 deletions(-) [+]
line wrap: on
line diff
--- a/client/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/client/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -16,202 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <chrono>
-#include <iostream>
-#include <thread>
-
-#include <malikania/client-resources-loader.hpp>
-#include <malikania/resources-locator.hpp>
-
-#include <malikania/js-animation.hpp>
-#include <malikania/js-animator.hpp>
-#include <malikania/js-client.hpp>
-#include <malikania/js-client-target.hpp>
-#include <malikania/js-color.hpp>
-#include <malikania/js-font.hpp>
-#include <malikania/js-image.hpp>
-#include <malikania/js-line.hpp>
-#include <malikania/js-point.hpp>
-#include <malikania/js-rectangle.hpp>
-#include <malikania/js-size.hpp>
-#include <malikania/js-sprite.hpp>
-#include <malikania/js-window.hpp>
-
-#if 0
-
-using namespace malikania;
-
-namespace {
-
-int usage()
-{
-    std::cerr << "usage: mlk-client directory\n";
-
-    return 1;
-}
-
-duk::Context init()
+int main()
 {
-    duk::Context ctx;
-
-    /* TODO: Put Malikania global somewhere else */
-    duk::putGlobal(ctx, "Malikania", duk::Object());
-
-    loadMalikaniaAnimation(ctx);
-    loadMalikaniaAnimator(ctx);
-    loadMalikaniaColor(ctx);
-    loadMalikaniaFont(ctx);
-    loadMalikaniaImage(ctx);
-    loadMalikaniaLine(ctx);
-    loadMalikaniaPoint(ctx);
-    loadMalikaniaRectangle(ctx);
-    loadMalikaniaSize(ctx);
-    loadMalikaniaSprite(ctx);
-    loadMalikaniaWindow(ctx);
-    loadMalikaniaClient(ctx);
-    loadMalikaniaClientTarget(ctx);
-
-    return ctx;
-}
-
-void start(duk::Context &ctx, std::shared_ptr<Client> client)
-{
-    duk::getGlobal<void>(ctx, "start");
-
-    if (duk::is<duk::Function>(ctx, -1)) {
-        duk::push(ctx, std::move(client));
-        duk::pcall(ctx, 1);
-        duk::pop(ctx);
-    } else {
-        duk::pop(ctx);
-    }
-}
-
-void update(duk::Context &ctx, std::shared_ptr<Client> client)
-{
-    duk::getGlobal<void>(ctx, "update");
-
-    if (duk::is<duk::Function>(ctx, -1)) {
-        duk::push(ctx, std::move(client));
-        duk::pcall(ctx, 1);
-        duk::pop(ctx);
-    } else {
-        duk::pop(ctx);
-        client->update();
-    }
-}
-
-void draw(duk::Context &ctx, std::shared_ptr<Client> client)
-{
-    duk::getGlobal<void>(ctx, "draw");
-
-    if (duk::is<duk::Function>(ctx, -1)) {
-        duk::push(ctx, std::move(client));
-        duk::pcall(ctx, 1);
-        duk::pop(ctx);
-    } else {
-        duk::pop(ctx);
-        client->draw();
-    }
 }
 
-int run(duk::Context &ctx)
-{
-    auto running = true;
-    auto client = std::make_shared<Client>();
-
-    client->setOnQuit([&] () {
-        running = false;
-    });
-    client->setOnKeyDown([&] (unsigned key) {
-        duk::getGlobal<void>(ctx, "keyDown");
-
-        if (duk::is<duk::Function>(ctx, -1)) {
-            duk::push(ctx, static_cast<int>(key));
-            duk::pcall(ctx, 1);
-            duk::pop(ctx);
-        } else {
-            duk::pop(ctx);
-        }
-    });
-    client->setOnKeyDown([&] (unsigned key) {
-        duk::getGlobal<void>(ctx, "keyUp");
-
-        if (duk::is<duk::Function>(ctx, -1)) {
-            duk::push(ctx, static_cast<int>(key));
-            duk::pcall(ctx, 1);
-            duk::pop(ctx);
-        } else {
-            duk::pop(ctx);
-        }
-    });
-
-    start(ctx, client);
-
-    while (running) {
-        client->poll();
-
-        update(ctx, client);
-        draw(ctx, client);
-
-        // TODO: remove this with an appropriate FPS calculation.
-        std::this_thread::sleep_for(std::chrono::milliseconds(50));
-    }
-
-    return 0;
-}
-
-int boot(const std::string &directory)
-{
-    std::string path = directory + "/client.js";
-    duk::Context ctx = init();
-
-    /* Store the loader */
-    ResourcesLocatorDirectory locator(directory);
-    ClientResourcesLoader loader(locator);
-
-    duk::putGlobal(ctx, "\xff""\xff""loader", &loader);
-
-    if (duk::pevalFile(ctx, path) != 0) {
-        duk::Exception info = duk::exception(ctx, -1);
-
-        std::cerr << info.fileName << ":" << info.lineNumber << ": " << info.stack << std::endl;
-
-        return 1;
-    }
-
-    return run(ctx);
-}
-
-} // !namespace
-
-int main(int argc, char **argv)
-{
-#if 0
-    -- argc;
-    ++ argv;
-
-    if (argc < 1) {
-        return usage();
-    }
-
-    return boot(argv[0]);
-#endif
-    Client client;
-    ElapsedTimer timer;
-
-    while (timer.elapsed() < 5000) {
-        client.poll();
-        client.update();
-        client.draw();
-
-        std::this_thread::sleep_for(std::chrono::milliseconds(50));
-    }
-
-    return 0;
-}
-
-#endif
-
-int main() {}
-
--- a/database/sqlite/src/account.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/database/sqlite/src/account.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -67,16 +67,16 @@
     "select count(*) from mk_account"
 );
 
-Account to_account(sqlite::statement& stmt)
+account to_account(sqlite::statement& stmt)
 {
-    Account ac;
+    account ac;
 
-    ac.setId(sqlite3_column_int64(stmt.get(), 0));
-    ac.setName(reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 1)));
-    ac.setEmail(reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 2)));
-    ac.setFirstName(reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 3)));
-    ac.setLastName(reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 4)));
-    ac.setPassword(reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 5)));
+    ac.id = sqlite3_column_int64(stmt.get(), 0);
+    ac.name = reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 1));
+    ac.email = reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 2));
+    ac.first_name = reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 3));
+    ac.last_name = reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 4));
+    ac.password = reinterpret_cast<const char *>(sqlite3_column_text(stmt.get(), 5));
 
     return ac;
 }
@@ -87,51 +87,51 @@
 
 extern "C" {
 
-BOOST_SYMBOL_EXPORT void malikania_account_create(Account& account)
+BOOST_SYMBOL_EXPORT void malikania_account_create(account& account)
 {
     auto stmt = sqlite::prepare(create_query);
 
-    sqlite3_bind_text(stmt.get(), 1, account.name().c_str(), -1, nullptr);
-    sqlite3_bind_text(stmt.get(), 2, account.email().c_str(), -1, nullptr);
-    sqlite3_bind_text(stmt.get(), 3, account.firstName().c_str(), -1, nullptr);
-    sqlite3_bind_text(stmt.get(), 4, account.lastName().c_str(), -1, nullptr);
-    sqlite3_bind_text(stmt.get(), 5, account.password().c_str(), -1, nullptr);
+    sqlite3_bind_text(stmt.get(), 1, account.name.c_str(), -1, nullptr);
+    sqlite3_bind_text(stmt.get(), 2, account.email.c_str(), -1, nullptr);
+    sqlite3_bind_text(stmt.get(), 3, account.first_name.c_str(), -1, nullptr);
+    sqlite3_bind_text(stmt.get(), 4, account.last_name.c_str(), -1, nullptr);
+    sqlite3_bind_text(stmt.get(), 5, account.password.c_str(), -1, nullptr);
 
     if (sqlite3_step(stmt.get()) != SQLITE_DONE) {
         throw std::runtime_error(sqlite3_errmsg(sqlite::database.get()));
     }
 
-    account.setId(sqlite3_last_insert_rowid(sqlite::database.get()));
+    account.id = sqlite3_last_insert_rowid(sqlite::database.get());
 }
 
-BOOST_SYMBOL_EXPORT void malikania_account_update(Account& account)
+BOOST_SYMBOL_EXPORT void malikania_account_update(account& account)
 {
     auto stmt = sqlite::prepare(update_query);
 
-    sqlite3_bind_text(stmt.get(), 1, account.name().c_str(), -1, nullptr);
-    sqlite3_bind_text(stmt.get(), 2, account.email().c_str(), -1, nullptr);
-    sqlite3_bind_text(stmt.get(), 3, account.firstName().c_str(), -1, nullptr);
-    sqlite3_bind_text(stmt.get(), 4, account.lastName().c_str(), -1, nullptr);
-    sqlite3_bind_text(stmt.get(), 5, account.password().c_str(), -1, nullptr);
-    sqlite3_bind_int64(stmt.get(), 6, account.id());
+    sqlite3_bind_text(stmt.get(), 1, account.name.c_str(), -1, nullptr);
+    sqlite3_bind_text(stmt.get(), 2, account.email.c_str(), -1, nullptr);
+    sqlite3_bind_text(stmt.get(), 3, account.first_name.c_str(), -1, nullptr);
+    sqlite3_bind_text(stmt.get(), 4, account.last_name.c_str(), -1, nullptr);
+    sqlite3_bind_text(stmt.get(), 5, account.password.c_str(), -1, nullptr);
+    sqlite3_bind_int64(stmt.get(), 6, account.id);
 
     if (sqlite3_step(stmt.get()) != SQLITE_DONE) {
         throw std::runtime_error(sqlite3_errmsg(sqlite::database.get()));
     }
 }
 
-BOOST_SYMBOL_EXPORT void malikania_account_remove(const Account& account)
+BOOST_SYMBOL_EXPORT void malikania_account_remove(const account& account)
 {
     auto stmt = sqlite::prepare(delete_query);
 
-    sqlite3_bind_int64(stmt.get(), 1, account.id());
+    sqlite3_bind_int64(stmt.get(), 1, account.id);
 
     if (sqlite3_step(stmt.get()) != SQLITE_OK) {
         throw std::runtime_error(sqlite3_errmsg(sqlite::database.get()));
     }
 }
 
-BOOST_SYMBOL_EXPORT Account malikania_account_get(std::uint64_t id)
+BOOST_SYMBOL_EXPORT account malikania_account_get(std::uint64_t id)
 {
     auto stmt = sqlite::prepare(get_query);
 
@@ -144,11 +144,11 @@
     return to_account(stmt);
 }
 
-BOOST_SYMBOL_EXPORT std::vector<Account> malikania_account_list()
+BOOST_SYMBOL_EXPORT std::vector<account> malikania_account_list()
 {
     auto stmt = sqlite::prepare(list_query);
 
-    std::vector<Account> list;
+    std::vector<account> list;
 
     while (sqlite3_step(stmt.get()) == SQLITE_ROW) {
         list.push_back(to_account(stmt));
--- a/libclient-js/CMakeLists.txt	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient-js/CMakeLists.txt	Tue Nov 29 21:21:36 2016 +0100
@@ -20,37 +20,37 @@
 
 set(
     HEADERS
-    ${libclient-js_SOURCE_DIR}/malikania/js-animation.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-animator.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-client.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-client-resources-loader.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-client-target.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-color.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-font.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-image.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-line.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-point.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-rectangle.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-sprite.hpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-window.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_animation.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_animator.hpp
+#    ${libclient-js_SOURCE_DIR}/malikania/js_client.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_client_resources_loader.hpp
+#    ${libclient-js_SOURCE_DIR}/malikania/js_client_target.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_color.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_font.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_image.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_line.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_point.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_rectangle.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_sprite.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_window.hpp
 )
 
 set(
     SOURCES
-    ${libclient-js_SOURCE_DIR}/malikania/js-animation.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-animator.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-client.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-client-resources-loader.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-client-target.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-color.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-font.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-image.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-line.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-point.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-rectangle.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-sprite.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-size.cpp
-    ${libclient-js_SOURCE_DIR}/malikania/js-window.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_animation.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_animator.cpp
+#    ${libclient-js_SOURCE_DIR}/malikania/js_client.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_client_resources_loader.cpp
+#    ${libclient-js_SOURCE_DIR}/malikania/js_client_target.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_color.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_font.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_image.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_line.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_point.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_rectangle.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_sprite.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_size.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js_window.cpp
 )
 
 malikania_create_library(
--- a/libclient-js/malikania/js-animation.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * js-animation.cpp -- animation description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client-resources-loader.hpp"
-#include "js-animation.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-animation-ptr");
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "animation must be new-constructed");
-
-    try {
-        auto loader = dukx_get_client_loader(ctx);
-        auto animation = loader->loadAnimation(duk_require_string(ctx, 0));
-
-        dukx_new_animation(ctx, new Animation(std::move(animation)));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t destructor(duk_context *ctx)
-{
-    duk_get_prop_string(ctx, 0, Signature.c_str());
-    delete static_cast<Animation *>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-    duk_del_prop_string(ctx, 0, Signature.c_str());
-
-    return 0;
-}
-
-} // !namespace
-
-void dukx_new_animation(duk_context *ctx, Animation *animation)
-{
-    assert(ctx);
-    assert(animation);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, animation);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-Animation *dukx_require_animation(duk_context *ctx, duk_idx_t index)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_prop_string(ctx, index, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animation object");
-
-    return static_cast<Animation *>(ptr);
-}
-
-void dukx_load_animation(duk_context *ctx)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_push_c_function(ctx, destructor, 1);
-    duk_set_finalizer(ctx, -2);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Animation");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-animation.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * js-animation.hpp -- animation description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_ANIMATION_HPP
-#define MALIKANIA_JS_ANIMATION_HPP
-
-#include <malikania/duktape.hpp>
-
-#include "animation.hpp"
-
-namespace malikania {
-
-/**
- * Construct an Animation object as this.
- *
- * \pre ctx != nullptr
- * \pre animation != nullptr
- * \param ctx the context
- * \param animation the animation
- */
-void dukx_new_animation(duk_context *ctx, Animation *animation);
-
-/**
- * Get an Animation object at the given index or raise a JavaScript error.
- *
- * \pre ctx != nullptr
- * \param ctx the context
- * \param index the value index
- * \return the Animation object
- */
-Animation *dukx_require_animation(duk_context *ctx, duk_idx_t index);
-
-/**
- * Load the Animation module into the context.
- *
- * \pre ctx != nullptr
- * \param ctx the context
- */
-void dukx_load_animation(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_ANIMATION_HPP
--- a/libclient-js/malikania/js-animator.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * js-animator.cpp -- animation drawing object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 <string>
-
-#include "js-animation.hpp"
-#include "js-animator.hpp"
-#include "js-point.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-animator-ptr");
-
-Animator *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
-
-    return static_cast<Animator *>(ptr);
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "animator must be new-constructed");
-
-    // Be sure animation get not collected before.
-    dukx_new_animator(ctx, new Animator(*dukx_require_animation(ctx, 0)));
-    duk_push_this(ctx);
-    duk_dup(ctx, 0);
-    duk_put_prop_string(ctx, -2, "\xff""\xff""animation-ref");
-
-    return 0;
-}
-
-duk_ret_t destructor(duk_context *ctx)
-{
-    duk_get_prop_string(ctx, 0, Signature.c_str());
-    delete static_cast<Animator *>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-    duk_del_prop_string(ctx, 0, Signature.c_str());
-
-    return 0;
-}
-
-duk_ret_t draw(duk_context *ctx)
-{
-    try {
-        self(ctx)->draw(*dukx_require_window(ctx, 0), dukx_get_point(ctx, 1));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t update(duk_context *ctx)
-{
-    self(ctx)->update();
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "draw",   draw,       2 },
-    { "update", update,     0 },
-    { nullptr,  nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_new_animator(duk_context *ctx, Animator *animator)
-{
-    assert(ctx);
-    assert(animator);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, animator);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-Animator *dukx_require_animator(duk_context *ctx, duk_idx_t index)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_prop_string(ctx, index, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
-
-    return static_cast<Animator *>(ptr);
-}
-
-void dukx_load_animator(duk_context *ctx)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_push_c_function(ctx, destructor, 1);
-    duk_set_finalizer(ctx, -2);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Animator");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-animator.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * js-animator.hpp -- animation drawing object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_ANIMATOR_HPP
-#define MALIKANIA_JS_ANIMATOR_HPP
-
-#include "animator.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-/**
- * Construct an Animator object as this.
- *
- * \pre ctx != nullptr
- * \pre animator != nullptr
- * \param ctx the context
- * \param animator the animator
- */
-void dukx_new_animator(duk_context *ctx, Animator *animator);
-
-/**
- * Get the animator at the given index.
- *
- * \pre ctx != nullptr
- * \param ctx the context
- * \param index the value index
- * \return the animator
- */
-Animator *dukx_require_animator(duk_context *ctx, duk_idx_t index);
-
-void dukx_load_animator(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_ANIMATOR_HPP
--- a/libclient-js/malikania/js-client-resources-loader.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * js-client-resources-loader.cpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client-resources-loader.hpp"
-#include "js-resources-loader.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Variable("\xff""\xff""malikania-client-resources-loader");
-
-} // !namespace
-
-void dukx_put_client_loader(duk_context *ctx, ClientResourcesLoader *loader)
-{
-    assert(ctx);
-    assert(loader);
-
-    // Also store as parent.
-    dukx_put_loader(ctx, loader);
-
-    StackAssert sa(ctx);
-
-    duk_push_pointer(ctx, loader);
-    duk_put_global_string(ctx, Variable.c_str());
-}
-
-ClientResourcesLoader *dukx_get_client_loader(duk_context *ctx)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, Variable.c_str());
-    auto ptr = static_cast<ClientResourcesLoader *>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-
-    return static_cast<ClientResourcesLoader *>(ptr);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-client-resources-loader.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * js-client-resources-loader.hpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
-#define MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
-
-#include "client-resources-loader.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-void dukx_put_client_loader(duk_context *ctx, ClientResourcesLoader *);
-
-ClientResourcesLoader *dukx_get_client_loader(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
--- a/libclient-js/malikania/js-client-target.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * js-client-target.cpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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-client-target.hpp"
-
-namespace malikania {
-
-class JsTarget : public Client::Target {
-public:
-
-};
-
-namespace {
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    return 0;
-}
-
-duk_ret_t draw(duk_context *ctx)
-{
-    return 0;
-}
-
-} // !namespace
-
-void dukx_load_client_target(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_get_prop_string(ctx, -1, "Client");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_put_prop_string(ctx, -1, "prototype");
-    duk_put_prop_string(ctx, -2, "Target");
-    duk_pop_2(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-client-target.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * js-client-target.hpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_CLIENT_TARGET_HPP
-#define MALIKANIA_JS_CLIENT_TARGET_HPP
-
-#include "client-target.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-void dukx_load_client_target(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_CLIENT_TARGET_HPP
--- a/libclient-js/malikania/js-client.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * js-client.cpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client.hpp"
-#include "js-client-target.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-duk_ret_t draw(duk_context *)
-{
-#if 0
-    try {
-        duk::self<std::shared_ptr<Client>>(ctx)->draw();
-    } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-#endif
-
-    return 0;
-}
-
-duk_ret_t setTarget(duk_context *)
-{
-#if 0
-    auto self = duk::self<Client *>(ctx);
-    auto target = duk::get<std::shared_ptr<Client::Target>>(ctx, 0);
-
-    self->setTarget(std::move(target));
-#endif
-
-    return 0;
-}
-
-duk_ret_t update(duk_context *)
-{
-#if 0
-    try {
-        duk::self<std::shared_ptr<Client>>(ctx)->update();
-    } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-#endif
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "draw",       draw,       0 },
-    { "setTarget",  setTarget,  1 },
-    { "update",     update,     0 },
-    { nullptr,      nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_load_client(duk_context *ctx)
-{
-#if 0
-    duk::StackAssert sa(ctx);
-
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::push(ctx, duk::Object());
-    duk::push(ctx, duk::Object());
-    duk::TypeTraits<Window>::prototype(ctx);
-    duk::setPrototype(ctx, -2);
-    duk::put(ctx, methods);
-    duk::putProperty(ctx, -2, "prototype");
-    duk::putProperty(ctx, -2, "Client");
-    duk::pop(ctx);
-#endif
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-client.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * js-client.hpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_CLIENT_HPP
-#define MALIKANIA_JS_CLIENT_HPP
-
-#include "client.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-void dukx_load_client(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_CLIENT_HPP
--- a/libclient-js/malikania/js-color.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * js-color.cpp -- color description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-color.hpp"
-#include "util.hpp"
-
-namespace malikania {
-
-namespace {
-
-std::uint8_t clampComponent(duk_context *ctx, int value, bool required)
-{
-    if (value < 0 || value > 255) {
-        if (required)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range (0, 255)", value);
-        else
-            value = util::clamp(value, 0, 255);
-    }
-
-    return static_cast<std::uint8_t>(value);
-}
-
-Color parseString(duk_context *ctx, duk_idx_t index, bool required)
-{
-    assert(duk_is_string(ctx, index));
-
-    Color color;
-
-    try {
-        color = Color(duk_get_string(ctx, index));
-    } catch (const std::exception &ex) {
-        if (required)
-            duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return color;
-}
-
-Color parseObject(duk_context *ctx, duk_idx_t index, bool required)
-{
-    assert(duk_is_object(ctx, index));
-
-    auto require = [&] (const auto prop) -> std::uint8_t {
-        if (required && !duk_has_prop_string(ctx, index, prop))
-            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in color description", prop);
-
-        duk_get_prop_string(ctx, index, prop);
-        auto comp = duk_get_int(ctx, -1);
-        duk_pop(ctx);
-
-        return clampComponent(ctx, comp, required);
-    };
-
-    // Alpha is optional.
-    duk_get_prop_string(ctx, index, "alpha");
-    auto alpha = duk_is_number(ctx, -1) ? duk_to_int(ctx, -1) : 255;
-    duk_pop(ctx);
-
-    return Color(
-        require("red"),
-        require("green"),
-        require("blue"),
-        clampComponent(ctx, alpha, required)
-    );
-}
-
-Color parse(duk_context *ctx, duk_idx_t index, bool required, Color color = {})
-{
-    switch (duk_get_type(ctx, index)) {
-    case DUK_TYPE_STRING:
-        color = parseString(ctx, index, required);
-        break;
-    case DUK_TYPE_OBJECT:
-        color = parseObject(ctx, index, required);
-        break;
-    default:
-        if (required)
-            duk_error(ctx, DUK_ERR_TYPE_ERROR, "color (string, object) expected");
-
-        break;
-    }
-
-    return color;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Color color;
-
-    /*
-     * The constructor allows an additional signature that takes 4 number
-     * arguments, otherwise use the literal parsing functions.
-     */
-    if (duk_get_top(ctx) >= 3) {
-        // Alpha is optional.
-        auto alpha = duk_is_number(ctx, 3) ? duk_to_int(ctx, 3) : 255;
-
-        color = Color(
-            clampComponent(ctx, duk_require_int(ctx, 0), true),
-            clampComponent(ctx, duk_require_int(ctx, 1), true),
-            clampComponent(ctx, duk_require_int(ctx, 2), true),
-            clampComponent(ctx, alpha, true)
-        );
-    } else if (duk_get_top(ctx) == 1)
-        color = parse(ctx, 0, true);
-
-    duk_ret_t ret;
-
-    // Allow both constructor and non constructor calls.
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_color(ctx, color);
-        duk_pop(ctx);
-        ret = 0;
-    } else {
-        dukx_push_color(ctx, color);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} //! namespace
-
-Color dukx_get_color(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, false);
-}
-
-Color dukx_require_color(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, true);
-}
-
-Color dukx_optional_color(duk_context *ctx, duk_idx_t index, Color def)
-{
-    return parse(ctx, index, false, std::move(def));
-}
-
-void dukx_push_color(duk_context *ctx, const Color &color)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_color(ctx, color);
-}
-
-void dukx_put_color(duk_context *ctx, const Color &color)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx, 0);
-
-    duk_push_uint(ctx, color.red());
-    duk_put_prop_string(ctx, -2, "red");
-    duk_push_uint(ctx, color.green());
-    duk_put_prop_string(ctx, -2, "green");
-    duk_push_uint(ctx, color.blue());
-    duk_put_prop_string(ctx, -2, "blue");
-    duk_push_uint(ctx, color.alpha());
-    duk_put_prop_string(ctx, -2, "alpha");
-}
-
-void dukx_load_color(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Color");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-color.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * js-color.hpp -- color description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_COLOR_HPP
-#define MALIKANIA_JS_COLOR_HPP
-
-/**
- * \file js-color.h
- * \brief JavaScript binding for Color.
- *
- * Colors can be created from plain JavaScript object.
- *
- * ````
- * {
- *   red: 0,
- *   green: 255,
- *   blue: 255,
- *   alpha: 255
- * }
- * ````
- *
- * It can also takes strings like "#rrggbbaa" and SVG names.
- */
-
-#include "color.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-/**
- * Get a color.
- *
- * May return a default value or a color with adjusted components.
- *
- * @param ctx the context
- * @param index the index
- */
-Color dukx_get_color(duk_context *ctx, duk_idx_t index);
-
-/**
- * Require a color.
- *
- * If the color has any invalid component, raise a JavaScript error.
- *
- * @param ctx the context
- * @param index the index
- */
-Color dukx_require_color(duk_context *ctx, duk_idx_t index);
-
-/**
- * Like get, but return the default value only if the value at the given
- * index is not an object or not a string, otherwise, adjust invalid values.
- *
- * @param ctx the context
- * @param index the index
- * @param def the default value
- */
-Color dukx_optional_color(duk_context *ctx, duk_idx_t index, Color def);
-
-/**
- * Push the color as object.
- *
- * @param ctx the context
- * @param color the color
- */
-void dukx_push_color(duk_context *ctx, const Color &color);
-
-/**
- * Put the color properties into the object at the top of the stack.
- *
- * @pre the top value must be an object
- * @param ctx the context
- * @param color the color
- */
-void dukx_put_color(duk_context *ctx, const Color &color);
-
-void dukx_load_color(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_COLOR_HPP
--- a/libclient-js/malikania/js-font.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * js-font.cpp -- font object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client-resources-loader.hpp"
-#include "js-font.hpp"
-#include "js-size.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-font-ptr");
-
-Font *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Font object");
-
-    return static_cast<Font *>(ptr);
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "font must be new-constructed");
-
-    try {
-        auto loader = dukx_get_client_loader(ctx);
-        auto id = duk_require_string(ctx, 0);
-        auto size = duk_require_int(ctx, 1);
-
-        if (size < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d must not be negative", size);
-
-        dukx_new_font(ctx, new Font(loader->loadFont(id, static_cast<unsigned>(size))));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t clip(duk_context *ctx)
-{
-    try {
-        dukx_push_size(ctx, self(ctx)->clip(duk_require_string(ctx, 0)));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 1;
-}
-
-const duk_function_list_entry methods[] = {
-    { "clip",   clip,       1 },
-    { nullptr,  nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_new_font(duk_context *ctx, Font *font)
-{
-    assert(ctx);
-    assert(font);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, font);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-Font *dukx_require_font(duk_context *ctx, duk_idx_t index)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_prop_string(ctx, index, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Font object");
-
-    return static_cast<Font *>(ptr);
-}
-
-void dukx_load_font(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 2);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Font");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-font.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * js-font.hpp -- font object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_FONT_HPP
-#define MALIKANIA_JS_FONT_HPP
-
-#include "duktape.hpp"
-#include "font.hpp"
-
-namespace malikania {
-
-void dukx_new_font(duk_context *ctx, Font *font);
-
-Font *dukx_require_font(duk_context *ctx, duk_idx_t index);
-
-void dukx_load_font(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_FONT_HPP
--- a/libclient-js/malikania/js-image.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * js-image.cpp -- image object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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-client-resources-loader.hpp"
-#include "js-image.hpp"
-#include "js-point.hpp"
-#include "js-rectangle.hpp"
-#include "js-size.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-image-ptr");
-
-Image *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
-
-    return static_cast<Image *>(ptr);
-}
-
-duk_ret_t size(duk_context *ctx)
-{
-    try {
-        dukx_push_size(ctx, self(ctx)->size());
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 1;
-}
-
-duk_ret_t draw(duk_context *ctx)
-{
-    try {
-        auto image = self(ctx);
-        auto window = dukx_require_window(ctx, 0);
-
-        if (duk_get_top(ctx) == 2)
-            image->draw(*window, dukx_get_point(ctx, 1));
-        else if (duk_get_top(ctx) == 3)
-            image->draw(*window, dukx_get_rect(ctx, 1), dukx_get_rect(ctx, 2));
-        else
-            duk_error(ctx, DUK_ERR_TYPE_ERROR, "invalid number of arguments: #%d", duk_get_top(ctx));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "image must be new-constructed");
-
-    try {
-        auto loader = dukx_get_client_loader(ctx);
-        auto image = new Image(loader->loadImage(duk_require_string(ctx, 0)));
-
-        dukx_new_image(ctx, image);
-        duk_push_this(ctx);
-        duk_push_string(ctx, "size");
-        duk_push_c_function(ctx, size, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-        duk_pop(ctx);
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "draw",   draw,       DUK_VARARGS },
-    { nullptr,  nullptr,    0           }
-};
-
-} // !namespace
-
-void dukx_new_image(duk_context *ctx, Image *image)
-{
-    assert(ctx);
-    assert(image);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, image);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-void dukx_load_image(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Image");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-image.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * js-image.hpp -- image object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_IMAGE_HPP
-#define MALIKANIA_JS_IMAGE_HPP
-
-#include "duktape.hpp"
-#include "image.hpp"
-
-namespace malikania {
-
-void dukx_new_image(duk_context *ctx, Image *image);
-
-void dukx_load_image(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_IMAGE_HPP
--- a/libclient-js/malikania/js-line.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * js-line.cpp -- line description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-line.hpp"
-
-namespace malikania {
-
-namespace {
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Line line;
-
-    if (duk_get_top(ctx) == 4) {
-        line = Line(
-            duk_get_int(ctx, 0),
-            duk_get_int(ctx, 1),
-            duk_get_int(ctx, 2),
-            duk_get_int(ctx, 3)
-        );
-    } else if (duk_get_top(ctx) == 1)
-        line = dukx_require_line(ctx, 0);
-
-    duk_ret_t ret;
-
-    /* Allow both constructor and non constructor calls */
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_line(ctx, line);
-        ret = 0;
-    } else {
-        dukx_push_line(ctx, line);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} // !namespace
-
-Line dukx_get_line(duk_context *ctx, duk_idx_t index)
-{
-    auto get = [&] (auto name) {
-        StackAssert sa(ctx);
-
-        duk_get_prop_string(ctx, index, name);
-        auto v = duk_get_int(ctx, -1);
-        duk_pop(ctx);
-
-        return v;
-    };
-
-    return Line(get("x1"), get("y1"), get("x2"), get("y2"));
-}
-
-Line dukx_require_line(duk_context *ctx, duk_idx_t index)
-{
-    auto get = [&] (auto prop) {
-        if (!duk_has_prop_string(ctx, index, prop))
-            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in line description", prop);
-
-        duk_get_prop_string(ctx, index, prop);
-
-        if (!duk_is_number(ctx, -1)) {
-            duk_pop(ctx);
-            duk_error(ctx, DUK_ERR_TYPE_ERROR, "property %s is not an int", prop);
-        }
-
-        auto value = duk_to_int(ctx, -1);
-
-        duk_pop(ctx);
-
-        return value;
-    };
-
-    return Line(get("x1"), get("y1"), get("x2"), get("y2"));
-}
-
-Line dukx_optional_line(duk_context *ctx, duk_idx_t index, Line def)
-{
-    return duk_is_object(ctx, index) ? dukx_get_line(ctx, index) : def;
-}
-
-void dukx_push_line(duk_context *ctx, const Line &line)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_line(ctx, line);
-}
-
-void dukx_put_line(duk_context *ctx, const Line &line)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx);
-
-    duk_push_int(ctx, line.x1());
-    duk_put_prop_string(ctx, -2, "x1");
-    duk_push_int(ctx, line.y1());
-    duk_put_prop_string(ctx, -2, "y1");
-    duk_push_int(ctx, line.x2());
-    duk_put_prop_string(ctx, -2, "x2");
-    duk_push_int(ctx, line.y2());
-    duk_put_prop_string(ctx, -2, "y2");
-}
-
-void dukx_load_line(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Line");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-line.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * js-line.hpp -- line description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_LINE_HPP
-#define MALIKANIA_JS_LINE_HPP
-
-/**
- * \file js-line.h
- * \brief JavaScript binding for Line.
- *
- * Lines are plain objects.
- *
- * ````
- * {
- *   x1: 10,
- *   y1: 10,
- *   x2: 50,
- *   y2: 50
- * }
- * ````
- */
-
-#include "duktape.hpp"
-#include "line.hpp"
-
-namespace malikania {
-
-/**
- * Get a line.
- *
- * @param ctx the context
- * @param index the index
- * @return the line
- */
-Line dukx_get_line(duk_context *ctx, duk_idx_t index);
-
-/**
- * Require a line.
- *
- * If value is not an object or any property is invalid, raise a JavaScript error.
- *
- * @param ctx the context
- * @param index the index
- * @return the line
- */
-Line dukx_require_line(duk_context *ctx, duk_idx_t index);
-
-/**
- * Like get but return def if the value at the given index is not an object.
- *
- * @param ctx the context
- * @param index the index
- * @param def the default value
- * @return the line
- */
-Line dukx_optional_line(duk_context *ctx, duk_idx_t index, Line def);
-
-/**
- * Push the line as object.
- *
- * @param ctx the context
- * @param line the line
- */
-void dukx_push_line(duk_context *ctx, const Line &line);
-
-/**
- * Put the line properties into the object at the top of the stack.
- *
- * @param ctx the context
- * @param line the line
- */
-void dukx_put_line(duk_context *ctx, const Line &line);
-
-void dukx_load_line(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_LINE_HPP
--- a/libclient-js/malikania/js-point.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * js-point.cpp -- point description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-point.hpp"
-
-namespace malikania {
-
-namespace {
-
-Point parse(duk_context *ctx, duk_idx_t index, bool required, Point point = {})
-{
-    StackAssert sa(ctx);
-
-    if (duk_is_object(ctx, index)) {
-        if (required && !duk_has_prop_string(ctx, index, "x"))
-            duk_error(ctx, DUK_ERR_ERROR, "missing x property in point description");
-        else if (required && !duk_has_prop_string(ctx, index, "y"))
-            duk_error(ctx, DUK_ERR_ERROR, "missing y property in point description");
-
-        //point = Point(duk::getProperty<int>(ctx, index, "x"), duk::getProperty<int>(ctx, index, "y"));
-        int x;
-        int y;
-
-        duk_get_prop_string(ctx, index, "x");
-        x = duk_to_int(ctx, -1);
-        duk_pop(ctx);
-        duk_get_prop_string(ctx, index, "y");
-        y = duk_to_int(ctx, -1);
-        duk_pop(ctx);
-
-        point = Point(x, y);
-    } else if (required)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "point object expected");
-
-    return point;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Point point;
-
-    if (duk_get_top(ctx) == 2)
-        point = Point(duk_require_int(ctx, 0), duk_require_int(ctx, 1));
-    else if (duk_get_top(ctx) == 1)
-        point = parse(ctx, 0, true);
-
-    duk_ret_t ret;
-
-    // Allow both constructor and non constructor calls.
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_point(ctx, point);
-        duk_pop(ctx);
-        ret = 0;
-    } else {
-        dukx_push_point(ctx, point);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} // !namespace
-
-Point dukx_get_point(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, false);
-}
-
-Point dukx_require_point(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, true);
-}
-
-Point dukx_optional_point(duk_context *ctx, duk_idx_t index, Point def)
-{
-    return parse(ctx, index, false, std::move(def));
-}
-
-void dukx_push_point(duk_context *ctx, const Point &point)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_point(ctx, point);
-}
-
-void dukx_put_point(duk_context *ctx, const Point &point)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx);
-
-    duk_push_int(ctx, point.x());
-    duk_put_prop_string(ctx, -2, "x");
-    duk_push_int(ctx, point.y());
-    duk_put_prop_string(ctx, -2, "y");
-}
-
-void dukx_load_point(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Point");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-point.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * js-point.hpp -- point description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_POINT_HPP
-#define MALIKANIA_JS_POINT_HPP
-
-#include "duktape.hpp"
-#include "point.hpp"
-
-namespace malikania {
-
-Point dukx_require_point(duk_context *ctx, duk_idx_t index);
-
-Point dukx_get_point(duk_context *ctx, duk_idx_t index);
-
-void dukx_push_point(duk_context *ctx, const Point &point);
-
-void dukx_put_point(duk_context *ctx, const Point &point);
-
-void dukx_load_point(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_POINT_HPP
--- a/libclient-js/malikania/js-rectangle.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * js-rectangle.cpp -- rectangle description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-rectangle.hpp"
-
-namespace malikania {
-
-namespace {
-
-unsigned clamp(duk_context *ctx, int value, bool required)
-{
-    if (value < 0) {
-        if (required)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d can not be negative", value);
-        else
-            value = 0;
-    }
-
-    return static_cast<unsigned>(value);
-}
-
-Rectangle parse(duk_context *ctx, duk_idx_t index, bool required, Rectangle rect = {})
-{
-    StackAssert sa(ctx);
-
-    if (duk_is_object(ctx, index)) {
-        auto get = [&] (auto prop) {
-            if (required && !duk_has_prop_string(ctx, index, prop))
-                duk_error(ctx, DUK_ERR_ERROR, "missing '%s' property", prop);
-
-            duk_get_prop_string(ctx, index, prop);
-
-            if (required && !duk_is_number(ctx, -1)) {
-                duk_pop(ctx);
-                duk_error(ctx, DUK_ERR_ERROR, "invalid '%s' property (number expected)", prop);
-            }
-
-            auto value = duk_to_int(ctx, -1);
-
-            duk_pop(ctx);
-
-            return value;
-        };
-
-        rect = Rectangle(get("x"), get("y"),
-            clamp(ctx, get("width"), required), clamp(ctx, get("height"), required));
-    } else if (required)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "rectangle object expected");
-
-    return rect;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Rectangle rect;
-
-    if (duk_get_top(ctx) == 4) {
-        rect = Rectangle(
-            duk_require_int(ctx, 0),
-            duk_require_int(ctx, 1),
-            clamp(ctx, duk_require_int(ctx, 2), true),
-            clamp(ctx, duk_require_int(ctx, 3), true)
-        );
-    } else if (duk_get_top(ctx) == 1)
-        rect = parse(ctx, 0, true);
-
-    duk_ret_t ret;
-
-    // Allow both constructor and non constructor calls.
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_rect(ctx, rect);
-        duk_pop(ctx);
-        ret = 0;
-    } else {
-        dukx_push_rect(ctx, rect);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} // !namespace
-
-Rectangle dukx_get_rect(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, false);
-}
-
-Rectangle dukx_require_rect(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, true);
-}
-
-Rectangle dukx_optional_rect(duk_context *ctx, duk_idx_t index, Rectangle def)
-{
-    return parse(ctx, index, false, std::move(def));
-}
-
-void dukx_push_rect(duk_context *ctx, const Rectangle &rect)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_rect(ctx, rect);
-}
-
-void dukx_put_rect(duk_context *ctx, const Rectangle &rect)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx);
-
-    duk_push_int(ctx, rect.x());
-    duk_put_prop_string(ctx, -2, "x");
-    duk_push_int(ctx, rect.y());
-    duk_put_prop_string(ctx, -2, "y");
-    duk_push_uint(ctx, rect.width());
-    duk_put_prop_string(ctx, -2, "width");
-    duk_push_uint(ctx, rect.height());
-    duk_put_prop_string(ctx, -2, "height");
-}
-
-void dukx_load_rect(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Rectangle");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-rectangle.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * js-rectangle.hpp -- rectangle description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_RECTANGLE_HPP
-#define MALIKANIA_JS_RECTANGLE_HPP
-
-/**
- * \file js-rectangle.hpp
- * \brief JavaScript binding for Rectangle.
- *
- * Rectangles are plain objects.
- *
- * ````
- * {
- *   x: 10,
- *   y: 20,
- *   width: 100,
- *   height: 200
- * }
- * ````
- */
-
-#include "duktape.hpp"
-#include "rectangle.hpp"
-
-namespace malikania {
-
-/**
- * Get a rectangle.
- *
- * The rectangle may be adjusted if any values are incorrect.
- *
- * @param ctx the context
- * @param index the value index
- * @return the rectangle
- */
-Rectangle dukx_get_rect(duk_context *ctx, duk_idx_t index);
-
-/**
- * Require a rectangle.
- *
- * If the object is not a rectangle or if width, height are invalid, raise a JavaScript error.
- *
- * @param ctx the context
- * @param index the index
- * @return the rectangle
- */
-Rectangle dukx_require_rect(duk_context *ctx, duk_idx_t index);
-
-/**
- * Like get but return the default value if the value at the given index is not an object or invalid
- *
- * @param ctx the context
- * @param index the idnex
- * @param def the default value
- * @return the rectangle
- */
-Rectangle dukx_optional_rect(duk_context *ctx, duk_idx_t index, Rectangle def);
-
-/**
- * Push the rectangle as object.
- *
- * @param ctx the context
- * @param rect the rectangle
- */
-void dukx_push_rect(duk_context *ctx, const Rectangle &rect);
-
-/**
- * Put the rectangle properties into the object at the top of the stack.
- *
- * @param ctx the context
- * @param rect the rectangle
- */
-void dukx_put_rect(duk_context *ctx, const Rectangle &rect);
-
-void dukx_load_rect(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_RECTANGLE_HPP
--- a/libclient-js/malikania/js-size.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * js-size.cpp -- size description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-size.hpp"
-
-namespace malikania {
-
-namespace {
-
-Size parse(duk_context *ctx, duk_idx_t index, bool required, Size size = {})
-{
-    StackAssert sa(ctx);
-
-    if (duk_is_object(ctx, index)) {
-        if (required && !duk_has_prop_string(ctx, index, "width"))
-            duk_error(ctx, DUK_ERR_ERROR, "missing width property in size description");
-        else if (required && !duk_has_prop_string(ctx, index, "height"))
-            duk_error(ctx, DUK_ERR_ERROR, "missing height property in size description");
-
-        int width;
-        int height;
-
-        duk_get_prop_string(ctx, index, "width");
-        width = duk_to_int(ctx, -1);
-        duk_pop(ctx);
-        duk_get_prop_string(ctx, index, "height");
-        height = duk_to_int(ctx, -1);
-        duk_pop(ctx);
-
-        if (width < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "width can not be negative");
-        if (height < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "height can not be negative");
-
-        size = Size(width, height);
-    } else if (required)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "size object expected");
-
-    return size;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Size size;
-
-    if (duk_get_top(ctx) == 2) {
-        int width;
-        int height;
-
-        if ((width = duk_require_int(ctx, 0)) < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #0 can not be negative");
-        if ((height = duk_require_int(ctx, 1)) < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #1 can not be negative");
-
-        size = Size(static_cast<unsigned>(width), static_cast<unsigned>(height));
-    } else if (duk_get_top(ctx) == 1)
-        size = parse(ctx, 0, true);
-
-    duk_ret_t ret;
-
-    // Allow both constructor and non constructor calls.
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_size(ctx, size);
-        duk_pop(ctx);
-        ret = 0;
-    } else {
-        dukx_push_size(ctx, size);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} // !namespace
-
-Size dukx_get_size(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, false);
-}
-
-Size dukx_require_size(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, true);
-}
-
-Size dukx_optional_size(duk_context *ctx, duk_idx_t index, Size def)
-{
-    return parse(ctx, index, false, std::move(def));
-}
-
-void dukx_push_size(duk_context *ctx, const Size &size)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_size(ctx, size);
-}
-
-void dukx_put_size(duk_context *ctx, const Size &size)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx, 0);
-
-    duk_push_uint(ctx, size.width());
-    duk_put_prop_string(ctx, -2, "width");
-    duk_push_uint(ctx, size.height());
-    duk_put_prop_string(ctx, -2, "height");
-}
-
-void dukx_load_size(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Size");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-size.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * js-size.hpp -- size description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_SIZE_HPP
-#define MALIKANIA_JS_SIZE_HPP
-
-/**
- * \file js-size.h
- * \brief JavaScript binding for Size.
- *
- * Size are plain objects.
- *
- * ````
- * {
- *   width: 1000,
- *   height: 2000
- * }
- * ````
- */
-
-#include "duktape.hpp"
-#include "size.hpp"
-
-namespace malikania {
-
-/**
- * Get a size.
- *
- * The size may be adjusted if any values are incorrect.
- *
- * @param ctx the context
- * @param index the value index
- * @return the size
- */
-Size dukx_get_size(duk_context *ctx, duk_idx_t index);
-
-/**
- * Require a size
- *
- * If the object is not a size, raise a JavaScript error.
- *
- * @param ctx the context
- * @param index the index
- * @return the size
- */
-Size dukx_require_size(duk_context *ctx, duk_idx_t index);
-
-/**
- * Like get but return the default value if the value at the given index is not an object.
- *
- * @param ctx the context
- * @param index the idnex
- * @param def the default value
- * @return the size
- */
-Size dukx_optional_size(duk_context *ctx, duk_idx_t index, Size def);
-
-/**
- * Push the size as object.
- *
- * @param ctx the context
- * @param size the size
- */
-void dukx_push_size(duk_context *ctx, const Size &size);
-
-/**
- * Put the size properties into the object at the top of the stack.
- *
- * @param ctx the context
- * @param size the size
- */
-void dukx_put_size(duk_context *ctx, const Size &size);
-
-void dukx_load_size(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_SIZE_HPP
--- a/libclient-js/malikania/js-sprite.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * js-sprite.cpp -- sprite object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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-client-resources-loader.hpp"
-#include "js-point.hpp"
-#include "js-size.hpp"
-#include "js-sprite.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-sprite-ptr");
-
-Sprite *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Sprite object");
-
-    return static_cast<Sprite *>(ptr);
-}
-
-duk_ret_t cell(duk_context *ctx)
-{
-    dukx_push_size(ctx, self(ctx)->cell());
-
-    return 1;
-}
-
-duk_ret_t columns(duk_context *ctx)
-{
-    duk_push_uint(ctx, self(ctx)->columns());
-
-    return 1;
-}
-
-duk_ret_t margins(duk_context *ctx)
-{
-    dukx_push_size(ctx, self(ctx)->margin());
-
-    return 1;
-}
-
-duk_ret_t rows(duk_context *ctx)
-{
-    duk_push_uint(ctx, self(ctx)->rows());
-
-    return 1;
-}
-
-duk_ret_t space(duk_context *ctx)
-{
-    dukx_push_size(ctx, self(ctx)->space());
-
-    return 1;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "sprite must be new-constructed");
-
-    try {
-        auto loader = dukx_get_client_loader(ctx);
-        auto sprite = loader->loadSprite(duk_require_string(ctx, 0));
-
-        duk_push_this(ctx);
-        duk_push_pointer(ctx, new Sprite(std::move(sprite)));
-        duk_put_prop_string(ctx, -2, Signature.c_str());
-
-        // Cell.
-        duk_push_string(ctx, "cell");
-        duk_push_c_function(ctx, cell, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        // Columns.
-        duk_push_string(ctx, "columns");
-        duk_push_c_function(ctx, columns, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        // Margins.
-        duk_push_string(ctx, "margins");
-        duk_push_c_function(ctx, margins, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        // Rows.
-        duk_push_string(ctx, "rows");
-        duk_push_c_function(ctx, rows, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        // Space.
-        duk_push_string(ctx, "space");
-        duk_push_c_function(ctx, space, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        duk_pop(ctx);
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t draw(duk_context *ctx)
-{
-    try {
-        auto sprite = self(ctx);
-        auto window = dukx_require_window(ctx, 0);
-        auto cell = duk_require_uint(ctx, 1);
-        auto point = dukx_get_point(ctx, 2);
-
-        if (cell >= (sprite->rows() * sprite->columns()))
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range", cell);
-
-        sprite->draw(*window, cell, point);
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "draw",   draw,       3 },
-    { nullptr,  nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_load_sprite(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Sprite");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-sprite.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * js-sprite.hpp -- sprite object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_SPRITE_HPP
-#define MALIKANIA_JS_SPRITE_HPP
-
-#include "duktape.hpp"
-#include "sprite.hpp"
-
-namespace malikania {
-
-void dukx_load_sprite(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_SPRITE_HPP
--- a/libclient-js/malikania/js-window.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
-/*
- * js-window.cpp -- window management (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-color.hpp"
-#include "js-font.hpp"
-#include "js-line.hpp"
-#include "js-point.hpp"
-#include "js-rectangle.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-window-ptr");
-const std::string Prototype("\xff""\xff""malikania-window-prototype");
-
-Window *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Window object");
-
-    return static_cast<Window *>(ptr);
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "window must be new-constructed");
-
-    // TODO: add parameters.
-    try {
-        auto win = new Window;
-
-        duk_push_this(ctx);
-        duk_push_pointer(ctx, win);
-        duk_put_prop_string(ctx, -2, Signature.c_str());
-        duk_pop(ctx);
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t clear(duk_context *ctx)
-{
-    try {
-        self(ctx)->clear();
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t present(duk_context *ctx)
-{
-    try {
-        self(ctx)->present();
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawingColor(duk_context *ctx)
-{
-    try {
-        dukx_push_color(ctx, self(ctx)->drawingColor());
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 1;
-}
-
-duk_ret_t drawLine(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawLine(dukx_require_line(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawLines(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawLines(dukx_get_array(ctx, 0, dukx_get_point));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawPoint(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawPoint(dukx_require_point(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawPoints(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawPoints(dukx_get_array(ctx, 0, dukx_get_point));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawRectangle(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawRectangle(dukx_require_rect(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawRectangles(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawRectangles(dukx_get_array(ctx, 0, dukx_get_rect));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawText(duk_context *ctx)
-{
-    try {
-        auto win = self(ctx);
-        auto text = duk_require_string(ctx, 0);
-        auto font = dukx_require_font(ctx, 1);
-        auto rect = dukx_get_rect(ctx, 2);
-
-        if (!rect.isNull())
-            win->drawText(text, *font, rect);
-        else
-            win->drawText(text, *font, Point(rect.x(), rect.y()));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t fillRectangle(duk_context *ctx)
-{
-    try {
-        self(ctx)->fillRectangle(dukx_require_rect(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t fillRectangles(duk_context *ctx)
-{
-    try {
-        self(ctx)->fillRectangles(dukx_get_array(ctx, 0, dukx_get_rect));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t setDrawingColor(duk_context *ctx)
-{
-    try {
-        self(ctx)->setDrawingColor(dukx_require_color(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "clear",              clear,              0 },
-    { "drawingColor",       drawingColor,       0 },
-    { "drawLine",           drawLine,           1 },
-    { "drawLines",          drawLines,          1 },
-    { "drawPoint",          drawPoint,          1 },
-    { "drawPoints",         drawPoints,         1 },
-    { "drawRectangle",      drawRectangle,      1 },
-    { "drawRectangles",     drawRectangles,     1 },
-    { "drawText",           drawText,           3 },
-    { "fillRectangle",      fillRectangle,      1 },
-    { "fillRectangles",     fillRectangles,     1 },
-    { "present",            present,            0 },
-    { "setDrawingColor",    setDrawingColor,    1 },
-    { nullptr,              nullptr,            0 }
-};
-
-} // !namespace
-
-void dukx_new_window(duk_context *ctx, Window *window)
-{
-    assert(ctx);
-    assert(window);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, window);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-Window *dukx_require_window(duk_context *ctx, duk_idx_t index)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_prop_string(ctx, index, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Window object");
-
-    return static_cast<Window *>(ptr);
-}
-
-void dukx_load_window(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 0);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Window");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient-js/malikania/js-window.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * js-window.hpp -- window management (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_JS_WINDOW_HPP
-#define MALIKANIA_JS_WINDOW_HPP
-
-#include "duktape.hpp"
-#include "window.hpp"
-
-namespace malikania {
-
-Window *dukx_require_window(duk_context *ctx, duk_idx_t index);
-
-void dukx_load_window(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_WINDOW_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_animation.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,108 @@
+/*
+ * js_animation.cpp -- animation description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js_client_resources_loader.hpp"
+#include "js_animation.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string signature("\xff""\xff""malikania-animation-ptr");
+
+duk_ret_t constructor(duk_context* ctx)
+{
+    if (!duk_is_constructor_call(ctx)) {
+        duk_error(ctx, DUK_ERR_ERROR, "animation must be new-constructed");
+    }
+
+    try {
+        auto& loader = dukx_get_client_loader(ctx);
+        auto anim = loader.load_animation(duk_require_string(ctx, 0));
+
+        duk_push_this(ctx);
+        duk_push_pointer(ctx, new animation(std::move(anim)));
+        duk_put_prop_string(ctx, -2, signature.c_str());
+        duk_pop(ctx);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t destructor(duk_context* ctx)
+{
+    duk_get_prop_string(ctx, 0, signature.c_str());
+    delete static_cast<animation *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+    duk_del_prop_string(ctx, 0, signature.c_str());
+
+    return 0;
+}
+
+} // !namespace
+
+void dukx_new_animation(duk_context* ctx, animation& anim)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, new animation(std::move(anim)));
+    duk_put_prop_string(ctx, -2, signature.c_str());
+    duk_pop(ctx);
+}
+
+animation& dukx_require_animation(duk_context* ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_prop_string(ctx, index, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an animation object");
+    }
+
+    return *static_cast<animation*>(ptr);
+}
+
+void dukx_load_animation(duk_context* ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_push_c_function(ctx, destructor, 1);
+    duk_set_finalizer(ctx, -2);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Animation");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_animation.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,60 @@
+/*
+ * js_animation.hpp -- animation description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_ANIMATION_HPP
+#define MALIKANIA_JS_ANIMATION_HPP
+
+#include <malikania/duktape.hpp>
+
+#include "animation.hpp"
+
+namespace malikania {
+
+#if 0
+/**
+ * Construct an animation object as this.
+ *
+ * \pre ctx != nullptr
+ * \pre animation != nullptr
+ * \param ctx the context
+ * \param animation the animation
+ */
+void dukx_new_animation(duk_context* ctx, animation* animation);
+#endif
+
+/**
+ * Get an animation object at the given index or raise a Javascript error.
+ *
+ * \pre ctx != nullptr
+ * \param ctx the context
+ * \param index the value index
+ * \return the Animation object
+ */
+animation& dukx_require_animation(duk_context* ctx, duk_idx_t index);
+
+/**
+ * Load the animation module into the context.
+ *
+ * \pre ctx != nullptr
+ * \param ctx the context
+ */
+void dukx_load_animation(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_ANIMATION_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_animator.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,153 @@
+/*
+ * js_animator.cpp -- animation drawing object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 <string>
+
+#include "js_animation.hpp"
+#include "js_animator.hpp"
+#include "js_point.hpp"
+#include "js_window.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string signature("\xff""\xff""malikania-animator-ptr");
+
+animator& self(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an animator object");
+    }
+
+    return *static_cast<animator*>(ptr);
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    if (!duk_is_constructor_call(ctx)) {
+        duk_error(ctx, DUK_ERR_ERROR, "animator must be new-constructed");
+    }
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, new animator(dukx_require_animation(ctx, 0)));
+    duk_put_prop_string(ctx, -2, signature.c_str());
+
+    // Be sure animation get not collected before.
+    duk_dup(ctx, 0);
+    duk_put_prop_string(ctx, -2, "\xff""\xff""animation-ref");
+    duk_pop(ctx);
+
+    return 0;
+}
+
+duk_ret_t destructor(duk_context *ctx)
+{
+    duk_get_prop_string(ctx, 0, signature.c_str());
+    delete static_cast<animator *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+    duk_del_prop_string(ctx, 0, signature.c_str());
+
+    return 0;
+}
+
+duk_ret_t draw(duk_context *ctx)
+{
+    try {
+        self(ctx).draw(dukx_require_window(ctx, 0), dukx_get_point(ctx, 1));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t update(duk_context *ctx)
+{
+    self(ctx).update();
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "draw",   draw,       2 },
+    { "update", update,     0 },
+    { nullptr,  nullptr,    0 }
+};
+
+} // !namespace
+
+#if 0
+
+void dukx_new_animator(duk_context* ctx, animator& ator)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, new animator);
+    duk_put_prop_string(ctx, -2, signature.c_str());
+    duk_pop(ctx);
+}
+
+#endif
+
+animator& dukx_require_animator(duk_context* ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_prop_string(ctx, index, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an animator object");
+    }
+
+    return *static_cast<animator*>(ptr);
+}
+
+void dukx_load_animator(duk_context* ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_push_c_function(ctx, destructor, 1);
+    duk_set_finalizer(ctx, -2);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Animator");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_animator.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,55 @@
+/*
+ * js_animator.hpp -- animation drawing object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_ANIMATOR_HPP
+#define MALIKANIA_JS_ANIMATOR_HPP
+
+#include "animator.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+#if 0
+
+/**
+ * Construct an animator object as this.
+ *
+ * \pre ctx != nullptr
+ * \pre animator != nullptr
+ * \param ctx the context
+ * \param animator the animator
+ */
+void dukx_new_animator(duk_context* ctx, animator ator);
+
+#endif
+
+/**
+ * Get the animator at the given index.
+ *
+ * \pre ctx != nullptr
+ * \param ctx the context
+ * \param index the value index
+ * \return the animator
+ */
+animator& dukx_require_animator(duk_context* ctx, duk_idx_t index);
+
+void dukx_load_animator(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_ANIMATOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_client.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,93 @@
+/*
+* js-client.cpp -- client resources loader (JavaScript binding)
+*
+* Copyright (c) 2013-2016 Malikania Authors
+*
+* 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 "js_client.hpp"
+#include "js_client-target.hpp"
+#include "js_window.hpp"
+
+namespace malikania {
+
+namespace {
+
+duk_ret_t draw(duk_context*)
+{
+#if 0
+    try {
+        duk::self<std::shared_ptr<Client>>(ctx)->draw();
+    } catch (const std::exception &ex) {
+        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+#endif
+
+    return 0;
+}
+
+duk_ret_t setTarget(duk_context*)
+{
+#if 0
+    auto self = duk::self<Client*>(ctx);
+    auto target = duk::get<std::shared_ptr<Client::Target>>(ctx, 0);
+
+    self->setTarget(std::move(target));
+#endif
+
+    return 0;
+}
+
+duk_ret_t update(duk_context*)
+{
+#if 0
+    try {
+        duk::self<std::shared_ptr<Client>>(ctx)->update();
+    } catch (const std::exception &ex) {
+        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+#endif
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "draw",       draw,       0 },
+    { "setTarget",  setTarget,  1 },
+    { "update",     update,     0 },
+    { nullptr,      nullptr,    0 }
+};
+
+} // !namespace
+
+void dukx_load_client(duk_context* ctx)
+{
+#if 0
+    duk::StackAssert sa(ctx);
+
+    duk::getGlobal<void>(ctx, "Malikania");
+    duk::push(ctx, duk::Object());
+    duk::push(ctx, duk::Object());
+    duk::TypeTraits<Window>::prototype(ctx);
+    duk::setPrototype(ctx, -2);
+    duk::put(ctx, methods);
+    duk::putProperty(ctx, -2, "prototype");
+    duk::putProperty(ctx, -2, "Client");
+    duk::pop(ctx);
+#endif
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_client.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,31 @@
+/*
+ * js-client.hpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_CLIENT_HPP
+#define MALIKANIA_JS_CLIENT_HPP
+
+#include "client.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+void dukx_load_client(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_CLIENT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_client_resources_loader.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,58 @@
+/*
+ * js_client_resources_loader.cpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js_client_resources_loader.hpp"
+#include "js_resources_loader.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string variable("\xff""\xff""malikania-client-resources-loader");
+
+} // !namespace
+
+void dukx_put_client_loader(duk_context* ctx, client_resources_loader& loader)
+{
+    assert(ctx);
+
+    // Also store as parent.
+    dukx_put_loader(ctx, loader);
+
+    StackAssert sa(ctx);
+
+    duk_push_pointer(ctx, &loader);
+    duk_put_global_string(ctx, variable.c_str());
+}
+
+client_resources_loader& dukx_get_client_loader(duk_context* ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, variable.c_str());
+    auto ptr = static_cast<client_resources_loader*>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+
+    return *static_cast<client_resources_loader*>(ptr);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_client_resources_loader.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,33 @@
+/*
+ * js_client_resources_loader.hpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
+#define MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
+
+#include "client_resources_loader.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+void dukx_put_client_loader(duk_context* ctx, client_resources_loader&);
+
+client_resources_loader& dukx_get_client_loader(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_client_target.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,55 @@
+/*
+ * js-client-target.cpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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-client-target.hpp"
+
+namespace malikania {
+
+class JsTarget : public Client::Target {
+public:
+
+};
+
+namespace {
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    return 0;
+}
+
+duk_ret_t draw(duk_context *ctx)
+{
+    return 0;
+}
+
+} // !namespace
+
+void dukx_load_client_target(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_get_prop_string(ctx, -1, "Client");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_prop_string(ctx, -1, "prototype");
+    duk_put_prop_string(ctx, -2, "Target");
+    duk_pop_2(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_client_target.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,31 @@
+/*
+ * js-client-target.hpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_CLIENT_TARGET_HPP
+#define MALIKANIA_JS_CLIENT_TARGET_HPP
+
+#include "client-target.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+void dukx_load_client_target(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_CLIENT_TARGET_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_color.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,196 @@
+/*
+ * js_color.cpp -- color description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js_color.hpp"
+#include "util.hpp"
+
+namespace malikania {
+
+namespace {
+
+std::uint8_t clamp_component(duk_context* ctx, int value, bool required)
+{
+    if (value < 0 || value > 255) {
+        if (required) {
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range (0, 255)", value);
+        } else {
+            value = util::clamp(value, 0, 255);
+        }
+    }
+
+    return static_cast<std::uint8_t>(value);
+}
+
+color parse_string(duk_context* ctx, duk_idx_t index, bool required)
+{
+    assert(duk_is_string(ctx, index));
+
+    color ret;
+
+    try {
+        ret = color(duk_get_string(ctx, index));
+    } catch (const std::exception &ex) {
+        if (required) {
+            duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        }
+    }
+
+    return ret;
+}
+
+color parse_object(duk_context* ctx, duk_idx_t index, bool required)
+{
+    assert(duk_is_object(ctx, index));
+
+    auto require = [&] (const auto prop) -> std::uint8_t {
+        if (required && !duk_has_prop_string(ctx, index, prop)) {
+            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in color description", prop);
+        }
+
+        duk_get_prop_string(ctx, index, prop);
+        auto comp = duk_get_int(ctx, -1);
+        duk_pop(ctx);
+
+        return clamp_component(ctx, comp, required);
+    };
+
+    // Alpha is optional.
+    duk_get_prop_string(ctx, index, "alpha");
+    auto alpha = duk_is_number(ctx, -1) ? duk_to_int(ctx, -1) : 255;
+    duk_pop(ctx);
+
+    return color(
+        require("red"),
+        require("green"),
+        require("blue"),
+        clamp_component(ctx, alpha, required)
+    );
+}
+
+color parse(duk_context* ctx, duk_idx_t index, bool required, color ret = {})
+{
+    switch (duk_get_type(ctx, index)) {
+    case DUK_TYPE_STRING:
+        ret = parse_string(ctx, index, required);
+        break;
+    case DUK_TYPE_OBJECT:
+        ret = parse_object(ctx, index, required);
+        break;
+    default:
+        if (required) {
+            duk_error(ctx, DUK_ERR_TYPE_ERROR, "color (string, object) expected");
+        }
+
+        break;
+    }
+
+    return ret;
+}
+
+duk_ret_t constructor(duk_context* ctx)
+{
+    color obj;
+
+    /*
+     * The constructor allows an additional signature that takes 4 number
+     * arguments, otherwise use the literal parsing functions.
+     */
+    if (duk_get_top(ctx) >= 3) {
+        // Alpha is optional.
+        auto alpha = duk_is_number(ctx, 3) ? duk_to_int(ctx, 3) : 255;
+
+        obj = color(
+            clamp_component(ctx, duk_require_int(ctx, 0), true),
+            clamp_component(ctx, duk_require_int(ctx, 1), true),
+            clamp_component(ctx, duk_require_int(ctx, 2), true),
+            clamp_component(ctx, alpha, true)
+        );
+    } else if (duk_get_top(ctx) == 1) {
+        obj = parse(ctx, 0, true);
+    }
+
+    duk_ret_t ret;
+
+    // Allow both constructor and non constructor calls.
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_color(ctx, obj);
+        duk_pop(ctx);
+        ret = 0;
+    } else {
+        dukx_push_color(ctx, obj);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} //! namespace
+
+color dukx_get_color(duk_context* ctx, duk_idx_t index)
+{
+    return parse(ctx, index, false);
+}
+
+color dukx_require_color(duk_context* ctx, duk_idx_t index)
+{
+    return parse(ctx, index, true);
+}
+
+color dukx_optional_color(duk_context* ctx, duk_idx_t index, color def)
+{
+    return parse(ctx, index, false, std::move(def));
+}
+
+void dukx_push_color(duk_context* ctx, const color& color)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_color(ctx, color);
+}
+
+void dukx_put_color(duk_context* ctx, const color &color)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx, 0);
+
+    duk_push_uint(ctx, color.red());
+    duk_put_prop_string(ctx, -2, "red");
+    duk_push_uint(ctx, color.green());
+    duk_put_prop_string(ctx, -2, "green");
+    duk_push_uint(ctx, color.blue());
+    duk_put_prop_string(ctx, -2, "blue");
+    duk_push_uint(ctx, color.alpha());
+    duk_put_prop_string(ctx, -2, "alpha");
+}
+
+void dukx_load_color(duk_context* ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Color");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_color.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,96 @@
+/*
+ * js_color.hpp -- color description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_COLOR_HPP
+#define MALIKANIA_JS_COLOR_HPP
+
+/**
+ * \file js_color.hpp
+ * \brief JavaScript binding for color.
+ *
+ * colors can be created from plain JavaScript object.
+ *
+ * ````
+ * {
+ *   red: 0,
+ *   green: 255,
+ *   blue: 255,
+ *   alpha: 255
+ * }
+ * ````
+ *
+ * It can also takes strings like "#rrggbbaa" and SVG names.
+ */
+
+#include "color.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+/**
+ * Get a color.
+ *
+ * May return a default value or a color with adjusted components.
+ *
+ * \param ctx the context
+ * \param index the index
+ */
+color dukx_get_color(duk_context* ctx, duk_idx_t index);
+
+/**
+ * Require a color.
+ *
+ * If the color has any invalid component, raise a JavaScript error.
+ *
+ * \param ctx the context
+ * \param index the index
+ */
+color dukx_require_color(duk_context* ctx, duk_idx_t index);
+
+/**
+ * Like get, but return the default value only if the value at the given
+ * index is not an object or not a string, otherwise, adjust invalid values.
+ *
+ * \param ctx the context
+ * \param index the index
+ * \param def the default value
+ */
+color dukx_optional_color(duk_context* ctx, duk_idx_t index, color def);
+
+/**
+ * Push the color as object.
+ *
+ * \param ctx the context
+ * \param color the color
+ */
+void dukx_push_color(duk_context* ctx, const color& color);
+
+/**
+ * Put the color properties into the object at the top of the stack.
+ *
+ * \pre the top value must be an object
+ * \param ctx the context
+ * \param color the color
+ */
+void dukx_put_color(duk_context* ctx, const color& color);
+
+void dukx_load_color(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_COLOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_font.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,140 @@
+/*
+ * js_font.cpp -- font object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 SOTWARE 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 "js_client_resources_loader.hpp"
+#include "js_font.hpp"
+#include "js_size.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string signature("\xff""\xff""malikania-font-ptr");
+
+font& self(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a font object");
+    }
+
+    return *static_cast<font*>(ptr);
+}
+
+duk_ret_t constructor(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    if (!duk_is_constructor_call(ctx)) {
+        duk_error(ctx, DUK_ERR_ERROR, "font must be new-constructed");
+    }
+
+    try {
+        auto& loader = dukx_get_client_loader(ctx);
+        auto id = duk_require_string(ctx, 0);
+        auto size = duk_require_int(ctx, 1);
+
+        if (size < 0) {
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d must not be negative", size);
+        }
+
+        duk_push_this(ctx);
+        duk_push_pointer(ctx, new font(loader.load_font(id, static_cast<unsigned>(size))));
+        duk_put_prop_string(ctx, -2, signature.c_str());
+        duk_pop(ctx);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t clip(duk_context* ctx)
+{
+    try {
+        dukx_push_size(ctx, self(ctx).clip(duk_require_string(ctx, 0)));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 1;
+}
+
+const duk_function_list_entry methods[] = {
+    { "clip",   clip,       1 },
+    { nullptr,  nullptr,    0 }
+};
+
+} // !namespace
+
+#if 0
+
+void dukx_new_font(duk_context* ctx, font *font)
+{
+    assert(ctx);
+    assert(font);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, font);
+    duk_put_prop_string(ctx, -2, signature.c_str());
+    duk_pop(ctx);
+}
+
+#endif
+
+font& dukx_require_font(duk_context* ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_prop_string(ctx, index, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a font object");
+    }
+
+    return *static_cast<font*>(ptr);
+}
+
+void dukx_load_font(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 2);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Font");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_font.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,37 @@
+/*
+ * js_font.hpp -- font object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_FONT_HPP
+#define MALIKANIA_JS_FONT_HPP
+
+#include "duktape.hpp"
+#include "font.hpp"
+
+namespace malikania {
+
+#if 0
+void dukx_new_font(duk_context *ctx, Font *font);
+#endif
+
+font& dukx_require_font(duk_context* ctx, duk_idx_t index);
+
+void dukx_load_font(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_FONT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_image.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,135 @@
+/*
+ * js_image.cpp -- image object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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_client_resources_loader.hpp"
+#include "js_image.hpp"
+#include "js_point.hpp"
+#include "js_rectangle.hpp"
+#include "js_size.hpp"
+#include "js_window.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string signature("\xff""\xff""malikania-image-ptr");
+
+image& self(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
+    }
+
+    return *static_cast<image *>(ptr);
+}
+
+duk_ret_t size(duk_context* ctx)
+{
+    try {
+        dukx_push_size(ctx, self(ctx).size());
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 1;
+}
+
+duk_ret_t draw(duk_context* ctx)
+{
+    try {
+        auto& image = self(ctx);
+        auto& window = dukx_require_window(ctx, 0);
+
+        if (duk_get_top(ctx) == 2) {
+            image.draw(window, dukx_get_point(ctx, 1));
+        } else if (duk_get_top(ctx) == 3) {
+            image.draw(window, dukx_get_rect(ctx, 1), dukx_get_rect(ctx, 2));
+        } else {
+            duk_error(ctx, DUK_ERR_TYPE_ERROR, "invalid number of arguments: #%d", duk_get_top(ctx));
+        }
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t constructor(duk_context* ctx)
+{
+    if (!duk_is_constructor_call(ctx)) {
+        duk_error(ctx, DUK_ERR_ERROR, "image must be new-constructed");
+    }
+
+    try {
+        auto& loader = dukx_get_client_loader(ctx);
+
+        duk_push_this(ctx);
+        duk_push_pointer(ctx, new image(loader.load_image(duk_require_string(ctx, 0))));
+        duk_put_prop_string(ctx, -2, signature.c_str());
+        duk_push_string(ctx, "size");
+        duk_push_c_function(ctx, size, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+        duk_pop(ctx);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "draw",   draw,       DUK_VARARGS },
+    { nullptr,  nullptr,    0           }
+};
+
+} // !namespace
+
+void dukx_new_image(duk_context* ctx, image *image)
+{
+    assert(ctx);
+    assert(image);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, image);
+    duk_put_prop_string(ctx, -2, signature.c_str());
+    duk_pop(ctx);
+}
+
+void dukx_load_image(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Image");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_image.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,35 @@
+/*
+ * js_image.hpp -- image object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_IMAGE_HPP
+#define MALIKANIA_JS_IMAGE_HPP
+
+#include "duktape.hpp"
+#include "image.hpp"
+
+namespace malikania {
+
+#if 0
+void dukx_new_image(duk_context* ctx, image& image);
+#endif
+
+void dukx_load_image(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_IMAGE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_line.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,136 @@
+/*
+ * js_line.cpp -- line description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js_line.hpp"
+
+namespace malikania {
+
+namespace {
+
+duk_ret_t constructor(duk_context* ctx)
+{
+    line obj;
+
+    if (duk_get_top(ctx) == 4) {
+        obj = line(
+            duk_get_int(ctx, 0),
+            duk_get_int(ctx, 1),
+            duk_get_int(ctx, 2),
+            duk_get_int(ctx, 3)
+        );
+    } else if (duk_get_top(ctx) == 1) {
+        obj = dukx_require_line(ctx, 0);
+    }
+
+    duk_ret_t ret;
+
+    // Allow both constructor and non constructor calls.
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_line(ctx, obj);
+        ret = 0;
+    } else {
+        dukx_push_line(ctx, obj);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} // !namespace
+
+line dukx_get_line(duk_context* ctx, duk_idx_t index)
+{
+    auto get = [&] (auto name) {
+        StackAssert sa(ctx);
+
+        duk_get_prop_string(ctx, index, name);
+        auto v = duk_get_int(ctx, -1);
+        duk_pop(ctx);
+
+        return v;
+    };
+
+    return line(get("x1"), get("y1"), get("x2"), get("y2"));
+}
+
+line dukx_require_line(duk_context* ctx, duk_idx_t index)
+{
+    auto get = [&] (auto prop) {
+        if (!duk_has_prop_string(ctx, index, prop))
+            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in line description", prop);
+
+        duk_get_prop_string(ctx, index, prop);
+
+        if (!duk_is_number(ctx, -1)) {
+            duk_pop(ctx);
+            duk_error(ctx, DUK_ERR_TYPE_ERROR, "property %s is not an int", prop);
+        }
+
+        auto value = duk_to_int(ctx, -1);
+
+        duk_pop(ctx);
+
+        return value;
+    };
+
+    return line(get("x1"), get("y1"), get("x2"), get("y2"));
+}
+
+line dukx_optional_line(duk_context* ctx, duk_idx_t index, line def)
+{
+    return duk_is_object(ctx, index) ? dukx_get_line(ctx, index) : def;
+}
+
+void dukx_push_line(duk_context* ctx, const line& line)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_line(ctx, line);
+}
+
+void dukx_put_line(duk_context* ctx, const line& line)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx);
+
+    duk_push_int(ctx, line.x1());
+    duk_put_prop_string(ctx, -2, "x1");
+    duk_push_int(ctx, line.y1());
+    duk_put_prop_string(ctx, -2, "y1");
+    duk_push_int(ctx, line.x2());
+    duk_put_prop_string(ctx, -2, "x2");
+    duk_push_int(ctx, line.y2());
+    duk_put_prop_string(ctx, -2, "y2");
+}
+
+void dukx_load_line(duk_context* ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Line");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_line.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,93 @@
+/*
+ * js_line.hpp -- line description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_LINE_HPP
+#define MALIKANIA_JS_LINE_HPP
+
+/**
+ * \file js_line.hpp
+ * \brief JavaScript binding for line.
+ *
+ * lines are plain objects.
+ *
+ * ````
+ * {
+ *   x1: 10,
+ *   y1: 10,
+ *   x2: 50,
+ *   y2: 50
+ * }
+ * ````
+ */
+
+#include "duktape.hpp"
+#include "line.hpp"
+
+namespace malikania {
+
+/**
+ * Get a line.
+ *
+ * \param ctx the context
+ * \param index the index
+ * \return the line
+ */
+line dukx_get_line(duk_context* ctx, duk_idx_t index);
+
+/**
+ * Require a line.
+ *
+ * If value is not an object or any property is invalid, raise a JavaScript error.
+ *
+ * \param ctx the context
+ * \param index the index
+ * \return the line
+ */
+line dukx_require_line(duk_context* ctx, duk_idx_t index);
+
+/**
+ * Like get but return def if the value at the given index is not an object.
+ *
+ * \param ctx the context
+ * \param index the index
+ * \param def the default value
+ * \return the line
+ */
+line dukx_optional_line(duk_context* ctx, duk_idx_t index, line def);
+
+/**
+ * Push the line as object.
+ *
+ * \param ctx the context
+ * \param line the line
+ */
+void dukx_push_line(duk_context* ctx, const line &line);
+
+/**
+ * Put the line properties into the object at the top of the stack.
+ *
+ * \param ctx the context
+ * \param line the line
+ */
+void dukx_put_line(duk_context* ctx, const line &line);
+
+void dukx_load_line(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_LINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_point.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,130 @@
+/*
+ * js_point.cpp -- point description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js_point.hpp"
+
+namespace malikania {
+
+namespace {
+
+point parse(duk_context* ctx, duk_idx_t index, bool required, point ret = {})
+{
+    StackAssert sa(ctx);
+
+    if (duk_is_object(ctx, index)) {
+        if (required && !duk_has_prop_string(ctx, index, "x")) {
+            duk_error(ctx, DUK_ERR_ERROR, "missing x property in point description");
+        }
+        else if (required && !duk_has_prop_string(ctx, index, "y")) {
+            duk_error(ctx, DUK_ERR_ERROR, "missing y property in point description");
+        }
+
+        int x;
+        int y;
+
+        duk_get_prop_string(ctx, index, "x");
+        x = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+        duk_get_prop_string(ctx, index, "y");
+        y = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+
+        ret = point(x, y);
+    } else if (required) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "point object expected");
+    }
+
+    return ret;
+}
+
+duk_ret_t constructor(duk_context* ctx)
+{
+    point obj;
+
+    if (duk_get_top(ctx) == 2) {
+        obj = point(duk_require_int(ctx, 0), duk_require_int(ctx, 1));
+    } else if (duk_get_top(ctx) == 1) {
+        obj = parse(ctx, 0, true);
+    }
+
+    duk_ret_t ret;
+
+    // Allow both constructor and non constructor calls.
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_point(ctx, obj);
+        duk_pop(ctx);
+        ret = 0;
+    } else {
+        dukx_push_point(ctx, obj);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} // !namespace
+
+point dukx_get_point(duk_context* ctx, duk_idx_t index)
+{
+    return parse(ctx, index, false);
+}
+
+point dukx_require_point(duk_context* ctx, duk_idx_t index)
+{
+    return parse(ctx, index, true);
+}
+
+point dukx_optional_point(duk_context* ctx, duk_idx_t index, point def)
+{
+    return parse(ctx, index, false, std::move(def));
+}
+
+void dukx_push_point(duk_context* ctx, const point &point)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_point(ctx, point);
+}
+
+void dukx_put_point(duk_context* ctx, const point& point)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx);
+
+    duk_push_int(ctx, point.x());
+    duk_put_prop_string(ctx, -2, "x");
+    duk_push_int(ctx, point.y());
+    duk_put_prop_string(ctx, -2, "y");
+}
+
+void dukx_load_point(duk_context* ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Point");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_point.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,39 @@
+/*
+ * js_point.hpp -- point description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_POINT_HPP
+#define MALIKANIA_JS_POINT_HPP
+
+#include "duktape.hpp"
+#include "point.hpp"
+
+namespace malikania {
+
+point dukx_require_point(duk_context* ctx, duk_idx_t index);
+
+point dukx_get_point(duk_context* ctx, duk_idx_t index);
+
+void dukx_push_point(duk_context* ctx, const point& point);
+
+void dukx_put_point(duk_context* ctx, const point& point);
+
+void dukx_load_point(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_POINT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_rectangle.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,151 @@
+/*
+ * js_rectangle.cpp -- rectangle description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js_rectangle.hpp"
+
+namespace malikania {
+
+namespace {
+
+unsigned clamp(duk_context* ctx, int value, bool required)
+{
+    if (value < 0) {
+        if (required)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d can not be negative", value);
+        else
+            value = 0;
+    }
+
+    return static_cast<unsigned>(value);
+}
+
+rectangle parse(duk_context* ctx, duk_idx_t index, bool required, rectangle rect = {})
+{
+    StackAssert sa(ctx);
+
+    if (duk_is_object(ctx, index)) {
+        auto get = [&] (auto prop) {
+            if (required && !duk_has_prop_string(ctx, index, prop))
+                duk_error(ctx, DUK_ERR_ERROR, "missing '%s' property", prop);
+
+            duk_get_prop_string(ctx, index, prop);
+
+            if (required && !duk_is_number(ctx, -1)) {
+                duk_pop(ctx);
+                duk_error(ctx, DUK_ERR_ERROR, "invalid '%s' property (number expected)", prop);
+            }
+
+            auto value = duk_to_int(ctx, -1);
+
+            duk_pop(ctx);
+
+            return value;
+        };
+
+        rect = rectangle(get("x"), get("y"),
+            clamp(ctx, get("width"), required), clamp(ctx, get("height"), required));
+    } else if (required)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "rectangle object expected");
+
+    return rect;
+}
+
+duk_ret_t constructor(duk_context* ctx)
+{
+    rectangle rect;
+
+    if (duk_get_top(ctx) == 4) {
+        rect = rectangle(
+            duk_require_int(ctx, 0),
+            duk_require_int(ctx, 1),
+            clamp(ctx, duk_require_int(ctx, 2), true),
+            clamp(ctx, duk_require_int(ctx, 3), true)
+        );
+    } else if (duk_get_top(ctx) == 1)
+        rect = parse(ctx, 0, true);
+
+    duk_ret_t ret;
+
+    // Allow both constructor and non constructor calls.
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_rect(ctx, rect);
+        duk_pop(ctx);
+        ret = 0;
+    } else {
+        dukx_push_rect(ctx, rect);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} // !namespace
+
+rectangle dukx_get_rect(duk_context* ctx, duk_idx_t index)
+{
+    return parse(ctx, index, false);
+}
+
+rectangle dukx_require_rect(duk_context* ctx, duk_idx_t index)
+{
+    return parse(ctx, index, true);
+}
+
+rectangle dukx_optional_rect(duk_context* ctx, duk_idx_t index, rectangle def)
+{
+    return parse(ctx, index, false, std::move(def));
+}
+
+void dukx_push_rect(duk_context* ctx, const rectangle& rect)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_rect(ctx, rect);
+}
+
+void dukx_put_rect(duk_context* ctx, const rectangle& rect)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx);
+
+    duk_push_int(ctx, rect.x());
+    duk_put_prop_string(ctx, -2, "x");
+    duk_push_int(ctx, rect.y());
+    duk_put_prop_string(ctx, -2, "y");
+    duk_push_uint(ctx, rect.width());
+    duk_put_prop_string(ctx, -2, "width");
+    duk_push_uint(ctx, rect.height());
+    duk_put_prop_string(ctx, -2, "height");
+}
+
+void dukx_load_rect(duk_context* ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Rectangle");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_rectangle.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,95 @@
+/*
+ * js_rectangle.hpp -- rectangle description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_RECTANGLE_HPP
+#define MALIKANIA_JS_RECTANGLE_HPP
+
+/**
+ * \file js_rectangle.hpp
+ * \brief JavaScript binding for rectangle.
+ *
+ * rectangles are plain objects.
+ *
+ * ````
+ * {
+ *   x: 10,
+ *   y: 20,
+ *   width: 100,
+ *   height: 200
+ * }
+ * ````
+ */
+
+#include "duktape.hpp"
+#include "rectangle.hpp"
+
+namespace malikania {
+
+/**
+ * Get a rectangle.
+ *
+ * The rectangle may be adjusted if any values are incorrect.
+ *
+ * \param ctx the context
+ * \param index the value index
+ * \return the rectangle
+ */
+rectangle dukx_get_rect(duk_context* ctx, duk_idx_t index);
+
+/**
+ * Require a rectangle.
+ *
+ * If the object is not a rectangle or if width, height are invalid, raise a JavaScript error.
+ *
+ * \param ctx the context
+ * \param index the index
+ * \return the rectangle
+ */
+rectangle dukx_require_rect(duk_context* ctx, duk_idx_t index);
+
+/**
+ * Like get but return the default value if the value at the given index is not an object or invalid
+ *
+ * \param ctx the context
+ * \param index the idnex
+ * \param def the default value
+ * \return the rectangle
+ */
+rectangle dukx_optional_rect(duk_context* ctx, duk_idx_t index, rectangle def);
+
+/**
+ * Push the rectangle as object.
+ *
+ * \param ctx the context
+ * \param rect the rectangle
+ */
+void dukx_push_rect(duk_context* ctx, const rectangle &rect);
+
+/**
+ * Put the rectangle properties into the object at the top of the stack.
+ *
+ * \param ctx the context
+ * \param rect the rectangle
+ */
+void dukx_put_rect(duk_context* ctx, const rectangle& rect);
+
+void dukx_load_rect(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_RECTANGLE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_size.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,146 @@
+/*
+ * js_size.cpp -- size description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js_size.hpp"
+
+namespace malikania {
+
+namespace {
+
+size parse(duk_context* ctx, duk_idx_t index, bool required, size ret = {})
+{
+    StackAssert sa(ctx);
+
+    if (duk_is_object(ctx, index)) {
+        if (required && !duk_has_prop_string(ctx, index, "width")) {
+            duk_error(ctx, DUK_ERR_ERROR, "missing width property in size description");
+        } else if (required && !duk_has_prop_string(ctx, index, "height")) {
+            duk_error(ctx, DUK_ERR_ERROR, "missing height property in size description");
+        }
+
+        int width;
+        int height;
+
+        duk_get_prop_string(ctx, index, "width");
+        width = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+        duk_get_prop_string(ctx, index, "height");
+        height = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+
+        if (width < 0) {
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "width can not be negative");
+        }
+        if (height < 0) {
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "height can not be negative");
+        }
+
+        ret = size(width, height);
+    } else if (required) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "size object expected");
+    }
+
+    return ret;
+}
+
+duk_ret_t constructor(duk_context* ctx)
+{
+    size obj;
+
+    if (duk_get_top(ctx) == 2) {
+        int width;
+        int height;
+
+        if ((width = duk_require_int(ctx, 0)) < 0) {
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #0 can not be negative");
+        }
+        if ((height = duk_require_int(ctx, 1)) < 0) {
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #1 can not be negative");
+        }
+
+        obj = size(static_cast<unsigned>(width), static_cast<unsigned>(height));
+    } else if (duk_get_top(ctx) == 1) {
+        obj = parse(ctx, 0, true);
+    }
+
+    duk_ret_t ret;
+
+    // Allow both constructor and non constructor calls.
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_size(ctx, obj);
+        duk_pop(ctx);
+        ret = 0;
+    } else {
+        dukx_push_size(ctx, obj);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} // !namespace
+
+size dukx_get_size(duk_context* ctx, duk_idx_t index)
+{
+    return parse(ctx, index, false);
+}
+
+size dukx_require_size(duk_context* ctx, duk_idx_t index)
+{
+    return parse(ctx, index, true);
+}
+
+size dukx_optional_size(duk_context* ctx, duk_idx_t index, size def)
+{
+    return parse(ctx, index, false, std::move(def));
+}
+
+void dukx_push_size(duk_context* ctx, const size& size)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_size(ctx, size);
+}
+
+void dukx_put_size(duk_context* ctx, const size& size)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx, 0);
+
+    duk_push_uint(ctx, size.width());
+    duk_put_prop_string(ctx, -2, "width");
+    duk_push_uint(ctx, size.height());
+    duk_put_prop_string(ctx, -2, "height");
+}
+
+void dukx_load_size(duk_context* ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Size");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_size.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,93 @@
+/*
+ * js_size.hpp -- size description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_SIZE_HPP
+#define MALIKANIA_JS_SIZE_HPP
+
+/**
+ * \file js_size.hpp
+ * \brief JavaScript binding for size.
+ *
+ * size are plain objects.
+ *
+ * ````
+ * {
+ *   width: 1000,
+ *   height: 2000
+ * }
+ * ````
+ */
+
+#include "duktape.hpp"
+#include "size.hpp"
+
+namespace malikania {
+
+/**
+ * Get a size.
+ *
+ * The size may be adjusted if any values are incorrect.
+ *
+ * \param ctx the context
+ * \param index the value index
+ * \return the size
+ */
+size dukx_get_size(duk_context* ctx, duk_idx_t index);
+
+/**
+ * Require a size
+ *
+ * If the object is not a size, raise a JavaScript error.
+ *
+ * \param ctx the context
+ * \param index the index
+ * \return the size
+ */
+size dukx_require_size(duk_context* ctx, duk_idx_t index);
+
+/**
+ * Like get but return the default value if the value at the given index is not an object.
+ *
+ * \param ctx the context
+ * \param index the idnex
+ * \param def the default value
+ * \return the size
+ */
+size dukx_optional_size(duk_context* ctx, duk_idx_t index, size def);
+
+/**
+ * Push the size as object.
+ *
+ * \param ctx the context
+ * \param size the size
+ */
+void dukx_push_size(duk_context* ctx, const size& size);
+
+/**
+ * Put the size properties into the object at the top of the stack.
+ *
+ * \param ctx the context
+ * \param size the size
+ */
+void dukx_put_size(duk_context* ctx, const size& size);
+
+void dukx_load_size(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_SIZE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_sprite.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,169 @@
+/*
+ * js_sprite.cpp -- sprite object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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_client_resources_loader.hpp"
+#include "js_point.hpp"
+#include "js_size.hpp"
+#include "js_sprite.hpp"
+#include "js_window.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string signature("\xff""\xff""malikania-sprite-ptr");
+
+sprite& self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a sprite object");
+    }
+
+    return *static_cast<sprite*>(ptr);
+}
+
+duk_ret_t cell(duk_context* ctx)
+{
+    dukx_push_size(ctx, self(ctx).cell());
+
+    return 1;
+}
+
+duk_ret_t columns(duk_context* ctx)
+{
+    duk_push_uint(ctx, self(ctx).columns());
+
+    return 1;
+}
+
+duk_ret_t margins(duk_context *ctx)
+{
+    dukx_push_size(ctx, self(ctx).margin());
+
+    return 1;
+}
+
+duk_ret_t rows(duk_context *ctx)
+{
+    duk_push_uint(ctx, self(ctx).rows());
+
+    return 1;
+}
+
+duk_ret_t space(duk_context *ctx)
+{
+    dukx_push_size(ctx, self(ctx).space());
+
+    return 1;
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    if (!duk_is_constructor_call(ctx)) {
+        duk_error(ctx, DUK_ERR_ERROR, "sprite must be new-constructed");
+    }
+
+    try {
+        auto& loader = dukx_get_client_loader(ctx);
+        auto sp = loader.load_sprite(duk_require_string(ctx, 0));
+
+        duk_push_this(ctx);
+        duk_push_pointer(ctx, new sprite(std::move(sp)));
+        duk_put_prop_string(ctx, -2, signature.c_str());
+
+        // Cell.
+        duk_push_string(ctx, "cell");
+        duk_push_c_function(ctx, cell, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        // Columns.
+        duk_push_string(ctx, "columns");
+        duk_push_c_function(ctx, columns, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        // Margins.
+        duk_push_string(ctx, "margins");
+        duk_push_c_function(ctx, margins, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        // Rows.
+        duk_push_string(ctx, "rows");
+        duk_push_c_function(ctx, rows, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        // Space.
+        duk_push_string(ctx, "space");
+        duk_push_c_function(ctx, space, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        duk_pop(ctx);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t draw(duk_context *ctx)
+{
+    try {
+        auto& sprite = self(ctx);
+        auto& window = dukx_require_window(ctx, 0);
+        auto cell = duk_require_uint(ctx, 1);
+        auto point = dukx_get_point(ctx, 2);
+
+        if (cell >= (sprite.rows() * sprite.columns())) {
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range", cell);
+        }
+
+        sprite.draw(window, cell, point);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "draw",   draw,       3 },
+    { nullptr,  nullptr,    0 }
+};
+
+} // !namespace
+
+void dukx_load_sprite(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Sprite");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_sprite.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,31 @@
+/*
+ * js_sprite.hpp -- sprite object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_SPRITE_HPP
+#define MALIKANIA_JS_SPRITE_HPP
+
+#include "duktape.hpp"
+#include "sprite.hpp"
+
+namespace malikania {
+
+void dukx_load_sprite(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_SPRITE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_window.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,290 @@
+/*
+ * js_window.cpp -- window management (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js_color.hpp"
+#include "js_font.hpp"
+#include "js_line.hpp"
+#include "js_point.hpp"
+#include "js_rectangle.hpp"
+#include "js_window.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string signature("\xff""\xff""malikania-window-ptr");
+const std::string prototype("\xff""\xff""malikania-window-prototype");
+
+window& self(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Window object");
+    }
+
+    return *static_cast<window*>(ptr);
+}
+
+duk_ret_t constructor(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    if (!duk_is_constructor_call(ctx)) {
+        duk_error(ctx, DUK_ERR_ERROR, "window must be new-constructed");
+    }
+
+    // TODO: add parameters.
+    try {
+        duk_push_this(ctx);
+        duk_push_pointer(ctx, new window);
+        duk_put_prop_string(ctx, -2, signature.c_str());
+        duk_pop(ctx);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t clear(duk_context* ctx)
+{
+    try {
+        self(ctx).clear();
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t present(duk_context* ctx)
+{
+    try {
+        self(ctx).present();
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawingColor(duk_context* ctx)
+{
+    try {
+        dukx_push_color(ctx, self(ctx).drawing_color());
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 1;
+}
+
+duk_ret_t drawLine(duk_context* ctx)
+{
+    try {
+        self(ctx).draw_line(dukx_require_line(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawLines(duk_context* ctx)
+{
+    try {
+        self(ctx).draw_lines(dukx_get_array(ctx, 0, dukx_get_point));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawPoint(duk_context* ctx)
+{
+    try {
+        self(ctx).draw_point(dukx_require_point(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawPoints(duk_context* ctx)
+{
+    try {
+        self(ctx).draw_points(dukx_get_array(ctx, 0, dukx_get_point));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawRectangle(duk_context* ctx)
+{
+    try {
+        self(ctx).draw_rectangle(dukx_require_rect(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawRectangles(duk_context* ctx)
+{
+    try {
+        self(ctx).draw_rectangles(dukx_get_array(ctx, 0, dukx_get_rect));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawText(duk_context* ctx)
+{
+    try {
+        auto& win = self(ctx);
+        auto text = duk_require_string(ctx, 0);
+        auto& font = dukx_require_font(ctx, 1);
+        auto rect = dukx_get_rect(ctx, 2);
+
+        if (!rect.is_null()) {
+            win.draw_text(text, font, rect);
+        } else {
+            win.draw_text(text, font, point{rect.x(), rect.y()});
+        }
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t fillRectangle(duk_context* ctx)
+{
+    try {
+        self(ctx).fill_rectangle(dukx_require_rect(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t fillRectangles(duk_context* ctx)
+{
+    try {
+        self(ctx).fill_rectangles(dukx_get_array(ctx, 0, dukx_get_rect));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t setDrawingColor(duk_context* ctx)
+{
+    try {
+        self(ctx).set_drawing_color(dukx_require_color(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "clear",              clear,              0 },
+    { "drawingColor",       drawingColor,       0 },
+    { "drawLine",           drawLine,           1 },
+    { "drawLines",          drawLines,          1 },
+    { "drawPoint",          drawPoint,          1 },
+    { "drawPoints",         drawPoints,         1 },
+    { "drawRectangle",      drawRectangle,      1 },
+    { "drawRectangles",     drawRectangles,     1 },
+    { "drawText",           drawText,           3 },
+    { "fillRectangle",      fillRectangle,      1 },
+    { "fillRectangles",     fillRectangles,     1 },
+    { "present",            present,            0 },
+    { "setDrawingColor",    setDrawingColor,    1 },
+    { nullptr,              nullptr,            0 }
+};
+
+} // !namespace
+
+#if 0
+
+void dukx_new_window(duk_context* ctx, window*window)
+{
+    assert(ctx);
+    assert(window);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, window);
+    duk_put_prop_string(ctx, -2, signature.c_str());
+    duk_pop(ctx);
+}
+
+#endif
+
+window& dukx_require_window(duk_context* ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_prop_string(ctx, index, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Window object");
+    }
+
+    return *static_cast<window*>(ptr);
+}
+
+void dukx_load_window(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 0);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Window");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js_window.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,33 @@
+/*
+ * js_window.hpp -- window management (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_JS_WINDOW_HPP
+#define MALIKANIA_JS_WINDOW_HPP
+
+#include "duktape.hpp"
+#include "window.hpp"
+
+namespace malikania {
+
+window& dukx_require_window(duk_context* ctx, duk_idx_t index);
+
+void dukx_load_window(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_WINDOW_HPP
--- a/libclient/CMakeLists.txt	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/CMakeLists.txt	Tue Nov 29 21:21:36 2016 +0100
@@ -20,42 +20,42 @@
     HEADERS
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/animation.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/animator.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-resources-loader.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target-loading.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target-map.hpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client.hpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client_resources_loader.hpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target.hpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target-loading.hpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target-map.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/color.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/font.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/image.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/label.hpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/label.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/line.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/point.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/rectangle.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/size.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/sprite.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/window.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/font-backend.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/image-backend.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/window-backend.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/font_backend.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/image_backend.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/window_backend.hpp
 )
 
 set(
     SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/animator.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-resources-loader.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target-loading.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target-map.cpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client_resources_loader.cpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target-loading.cpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-target-map.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/color.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/font.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/image.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/label.cpp
+#    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/label.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/sprite.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/window.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/font-backend.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/image-backend.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/window-backend.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/font_backend.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/image_backend.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/window_backend.cpp
 )
 
 find_package(SDL2 REQUIRED)
--- a/libclient/malikania/animation.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/animation.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -33,16 +33,15 @@
 
 namespace malikania {
 
-class Window;
+class window;
 
 /**
- * \class AnimationFrame
  * \brief Animation frame description.
  *
- * A frame is a duration before switching to the next sprite cell. It is currently implemented as a class for future
- * usage.
+ * A frame is a duration before switching to the next sprite cell. It is
+ * currently implemented as a class for future usage.
  */
-class AnimationFrame {
+class animation_frame {
 private:
     std::uint16_t m_delay;
 
@@ -52,7 +51,7 @@
      *
      * \param delay the optional delay
      */
-    inline AnimationFrame(std::uint16_t delay = 100) noexcept
+    inline animation_frame(std::uint16_t delay = 100) noexcept
         : m_delay(delay)
     {
     }
@@ -71,25 +70,25 @@
 /**
  * \brief List of frames.
  */
-using AnimationFrames = std::vector<AnimationFrame>;
+using animation_frames = std::vector<animation_frame>;
 
 /**
- * \class Animation
  * \brief Animation description.
  *
- * An animation is a sprite with a set of frames containing a delay for showing all sprites in a specific amount of
- * time.
+ * An animation is a sprite with a set of frames containing a delay for showing
+ * all sprites in a specific amount of time.
  *
- * Because an animation contains an image, a state (time, current cell) it must be constructed with an Animator object
- * so the user is able to use the same animation on different parts of the screen without having to duplicate
+ * Because an animation contains an image, a state (time, current cell) it must
+ * be constructed with an animator object so the user is able to use the same
+ * animation on different parts of the screen without having to duplicate
  * resources.
  *
  * \see Animator
  */
-class Animation {
+class animation {
 private:
-    Sprite m_sprite;
-    AnimationFrames m_frames;
+    malikania::sprite m_sprite;
+    malikania::animation_frames m_frames;
 
 public:
     /**
@@ -98,7 +97,7 @@
      * \param sprite the sprite image
      * \param frames the frames to show
      */
-    inline Animation(Sprite sprite, AnimationFrames frames) noexcept
+    inline animation(malikania::sprite sprite, animation_frames frames) noexcept
         : m_sprite(std::move(sprite))
         , m_frames(std::move(frames))
     {
@@ -109,7 +108,7 @@
      *
      * \return the sprite
      */
-    inline const Sprite &sprite() const noexcept
+    inline const malikania::sprite& sprite() const noexcept
     {
         return m_sprite;
     }
@@ -119,7 +118,7 @@
      *
      * \return the sprite
      */
-    inline Sprite &sprite() noexcept
+    inline malikania::sprite& sprite() noexcept
     {
         return m_sprite;
     }
@@ -129,7 +128,7 @@
      *
      * \return the frames
      */
-    inline const AnimationFrames &frames() const noexcept
+    inline const animation_frames& frames() const noexcept
     {
         return m_frames;
     }
@@ -141,7 +140,7 @@
      * \param index the index
      * \return the frame
      */
-    inline const AnimationFrame &operator[](unsigned index) const noexcept
+    inline const animation_frame& operator[](unsigned index) const noexcept
     {
         assert(index < m_frames.size());
 
--- a/libclient/malikania/animator.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/animator.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,17 +21,18 @@
 
 namespace malikania {
 
-Animator::Animator(Animation &animation) noexcept
+animator::animator(animation& animation) noexcept
     : m_animation(animation)
 {
 }
 
-void Animator::update() noexcept
+void animator::update() noexcept
 {
-    unsigned total = m_animation.sprite().rows() * m_animation.sprite().columns();
+    auto total = m_animation.sprite().rows() * m_animation.sprite().columns();
 
-    if (m_current >= total)
+    if (m_current >= total) {
         return;
+    }
 
     if (m_timer.elapsed().wall / 1000000LL >= m_animation[m_current].delay()) {
         m_current ++;
@@ -39,11 +40,11 @@
     }
 }
 
-void Animator::draw(Window &window, const Point &point)
+void animator::draw(window& window, const point& point)
 {
-    // TODO: assert ?
-    if (m_current >= m_animation.sprite().rows() * m_animation.sprite().columns())
+    if (m_current >= m_animation.sprite().rows() * m_animation.sprite().columns()) {
         return;
+    }
 
     m_animation.sprite().draw(window, m_current, point);
 }
--- a/libclient/malikania/animator.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/animator.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -28,20 +28,19 @@
 
 namespace malikania {
 
-class Animation;
-class Point;
-class Window;
+class animation;
+class point;
+class window;
 
 /**
- * \class Animator
  * \brief Object for drawing animations.
  *
  * The animator contains an animation and a state.
  */
-class Animator {
+class animator {
 private:
     boost::timer::cpu_timer m_timer;
-    Animation &m_animation;
+    animation& m_animation;
     unsigned m_current{0};
 
 public:
@@ -51,12 +50,13 @@
      * \pre animation must not be null
      * \param animation the animation
      */
-    Animator(Animation &animation) noexcept;
+    animator(animation& animation) noexcept;
 
     /**
      * Update the animator state.
      *
-     * This function should be called in the main loop to update the cell to draw before calling draw().
+     * This function should be called in the main loop to update the cell to
+     * draw before calling draw().
      */
     void update() noexcept;
 
@@ -66,7 +66,7 @@
      * \param window the window
      * \param position the position in the window
      */
-    void draw(Window &window, const Point &position);
+    void draw(window& window, const point& position);
 };
 
 } // !malikania
--- a/libclient/malikania/backend/sdl/font-backend.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * font-backend.cpp -- font object (SDL2 implementation)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 <malikania/backend/sdl/common-sdl.hpp>
-
-#include <malikania/size.hpp>
-#include <malikania/font.hpp>
-
-#include "font-backend.hpp"
-
-using namespace std::string_literals;
-
-namespace malikania {
-
-Font::Backend::Backend(std::string data, unsigned size)
-    : m_font(nullptr, nullptr)
-{
-    auto rw = SDLx_RWFromBinary(std::move(data));
-
-    if (rw == nullptr)
-        throw std::runtime_error(SDL_GetError());
-
-    m_font = Handle(TTF_OpenFontRW(rw, true, size), TTF_CloseFont);
-
-    if (m_font == NULL)
-        throw std::runtime_error(TTF_GetError());
-}
-
-Size Font::Backend::clip(const Font &, const std::string &text) const
-{
-    int width, height;
-
-    if (TTF_SizeUTF8(m_font.get(), text.c_str(), &width, &height) != 0)
-        throw std::runtime_error(SDL_GetError());
-
-    return Size(static_cast<unsigned>(width), static_cast<unsigned>(height));
-}
-
-} // !malikania
--- a/libclient/malikania/backend/sdl/font-backend.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * font-backend.hpp -- font object (SDL2 implementation)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_FONT_BACKEND_HPP
-#define MALIKANIA_FONT_BACKEND_HPP
-
-#include <memory>
-
-#include <SDL.h>
-#include <SDL_ttf.h>
-
-#include <malikania/font.hpp>
-
-namespace malikania {
-
-class Font;
-class Size;
-
-class Font::Backend {
-private:
-    using Handle = std::unique_ptr<TTF_Font, void (*)(TTF_Font*)>;
-
-    Handle m_font;
-
-public:
-    Backend(std::string data, unsigned size);
-
-    inline TTF_Font *font() noexcept
-    {
-        return m_font.get();
-    }
-
-    Size clip(const Font &self, const std::string &text) const;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_FONT_BACKEND_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/font_backend.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,57 @@
+/*
+ * font_backend.cpp -- font object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 <malikania/backend/sdl/sdl_util.hpp>
+
+#include <malikania/size.hpp>
+#include <malikania/font.hpp>
+
+#include "font_backend.hpp"
+
+using namespace std::string_literals;
+
+namespace malikania {
+
+font::backend_impl::backend_impl(std::string data, unsigned size)
+    : m_font(nullptr, nullptr)
+{
+    auto rw = SDLx_RWFromBinary(std::move(data));
+
+    if (rw == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    m_font = {TTF_OpenFontRW(rw, true, size), TTF_CloseFont};
+
+    if (m_font == nullptr) {
+        throw std::runtime_error(TTF_GetError());
+    }
+}
+
+size font::backend_impl::clip(const malikania::font&, const std::string& text) const
+{
+    int width, height;
+
+    if (TTF_SizeUTF8(m_font.get(), text.c_str(), &width, &height) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    return malikania::size(static_cast<unsigned>(width), static_cast<unsigned>(height));
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/font_backend.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,51 @@
+/*
+ * font_backend.hpp -- font object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_FONT_BACKEND_HPP
+#define MALIKANIA_FONT_BACKEND_HPP
+
+#include <memory>
+
+#include <SDL.h>
+#include <SDL_ttf.h>
+
+#include <malikania/font.hpp>
+
+namespace malikania {
+
+class font;
+class size;
+
+class font::backend_impl {
+private:
+    std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> m_font;
+
+public:
+    backend_impl(std::string data, unsigned size);
+
+    inline TTF_Font* font() noexcept
+    {
+        return m_font.get();
+    }
+
+    malikania::size clip(const malikania::font& self, const std::string& text) const;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_FONT_BACKEND_HPP
--- a/libclient/malikania/backend/sdl/image-backend.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * image-backend.cpp -- image object (SDL2 implementation)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 <SDL_image.h>
-
-#include <malikania/backend/sdl/common-sdl.hpp>
-
-#include "image-backend.hpp"
-#include "window-backend.hpp"
-
-using namespace std::string_literals;
-
-namespace malikania {
-
-void Image::Backend::createTexture(Window &window)
-{
-    m_texture = Texture(SDL_CreateTextureFromSurface(window.backend().renderer(), m_surface.get()), SDL_DestroyTexture);
-
-    if (m_texture == nullptr)
-        throw std::runtime_error(SDL_GetError());
-}
-
-Image::Backend::Backend(Image &, std::string data)
-    : m_surface(nullptr, nullptr)
-    , m_texture(nullptr, nullptr)
-{
-    // Initialize the texture.
-    auto rw = SDLx_RWFromBinary(std::move(data));
-
-    if (rw == nullptr)
-        throw std::runtime_error(SDL_GetError());
-
-    m_surface = Surface(IMG_Load_RW(rw, true), SDL_FreeSurface);
-
-    if (!m_surface)
-        throw std::runtime_error(SDL_GetError());
-
-    m_size = Size(static_cast<unsigned>(m_surface->w), static_cast<unsigned>(m_surface->h));
-}
-
-void Image::Backend::draw(Window &window, const Point &point)
-{
-    if (!m_texture)
-        createTexture(window);
-
-    SDL_Rect target;
-
-    target.x = static_cast<int>(point.x());
-    target.y = static_cast<int>(point.y());
-    target.w = static_cast<int>(m_size.width());
-    target.h = static_cast<int>(m_size.height());
-
-    if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), nullptr, &target) < 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Image::Backend::draw(Window &window, const Rectangle &source, const Rectangle &target)
-{
-    if (!m_texture)
-        createTexture(window);
-
-    SDL_Rect sr, st;
-
-    sr.x = source.x();
-    sr.y = source.y();
-    sr.w = static_cast<int>(source.width());
-    sr.h = static_cast<int>(source.height());
-
-    st.x = target.x();
-    st.y = target.y();
-    st.w = static_cast<int>(target.width());
-    st.h = static_cast<int>(target.height());
-
-    /* Readjust .w, .h if null */
-    if (source.isNull()) {
-        sr.w = static_cast<int>(m_size.width());
-        sr.h = static_cast<int>(m_size.height());
-    }
-    if (target.isNull()) {
-        st.w = static_cast<int>(m_size.width());
-        st.h = static_cast<int>(m_size.height());
-    }
-
-    if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), &sr, &st) < 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-} // !malikania
--- a/libclient/malikania/backend/sdl/image-backend.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * image-backend.hpp -- image object (SDL2 implementation)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_IMAGE_BACKEND_HPP
-#define MALIKANIA_IMAGE_BACKEND_HPP
-
-#include <memory>
-
-#include <SDL.h>
-
-#include <malikania/size.hpp>
-#include <malikania/image.hpp>
-
-namespace malikania {
-
-class Image;
-class Point;
-class Rectangle;
-class Window;
-
-class Image::Backend {
-private:
-    using Surface = std::unique_ptr<SDL_Surface, void (*)(SDL_Surface *)>;
-    using Texture = std::unique_ptr<SDL_Texture, void (*)(SDL_Texture *)>;
-
-    Surface m_surface;
-    Texture m_texture;
-    Size m_size;
-
-    void createTexture(Window &window);
-
-public:
-    Backend(Image &self, std::string data);
-
-    inline SDL_Texture *texture() noexcept
-    {
-        return m_texture.get();
-    }
-
-    inline const Size &size() const noexcept
-    {
-        return m_size;
-    }
-
-    void draw(Window &window, const Point &position);
-
-    void draw(Window &window, const Rectangle &source, const Rectangle &target);
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_IMAGE_BACKEND_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/image_backend.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,119 @@
+/*
+ * image_backend.cpp -- image object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 <SDL_image.h>
+
+#include <malikania/backend/sdl/sdl_util.hpp>
+
+#include "image_backend.hpp"
+#include "window_backend.hpp"
+
+using namespace std::string_literals;
+
+namespace malikania {
+
+void image::backend_impl::create_texture(window& window)
+{
+    m_texture = {
+        SDL_CreateTextureFromSurface(window.backend().renderer(), m_surface.get()),
+        SDL_DestroyTexture
+    };
+
+    if (m_texture == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+image::backend_impl::backend_impl(image&, std::string data)
+    : m_surface(nullptr, nullptr)
+    , m_texture(nullptr, nullptr)
+{
+    auto rw = SDLx_RWFromBinary(std::move(data));
+
+    if (rw == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    m_surface = {IMG_Load_RW(rw, true), SDL_FreeSurface};
+
+    if (!m_surface) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    m_size = malikania::size(
+        static_cast<unsigned>(m_surface->w),
+        static_cast<unsigned>(m_surface->h)
+    );
+}
+
+void image::backend_impl::draw(window& window, const point& point)
+{
+    /*
+     * Create texture at this step so the image constructor does not need the
+     * window.
+     */
+    if (!m_texture) {
+        create_texture(window);
+    }
+
+    SDL_Rect target;
+
+    target.x = static_cast<int>(point.x());
+    target.y = static_cast<int>(point.y());
+    target.w = static_cast<int>(m_size.width());
+    target.h = static_cast<int>(m_size.height());
+
+    if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), nullptr, &target) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void image::backend_impl::draw(window& window, const rectangle& source, const rectangle& target)
+{
+    if (!m_texture) {
+        create_texture(window);
+    }
+
+    SDL_Rect sr, st;
+
+    sr.x = source.x();
+    sr.y = source.y();
+    sr.w = static_cast<int>(source.width());
+    sr.h = static_cast<int>(source.height());
+
+    st.x = target.x();
+    st.y = target.y();
+    st.w = static_cast<int>(target.width());
+    st.h = static_cast<int>(target.height());
+
+    // Readjust .w, .h if null.
+    if (source.is_null()) {
+        sr.w = static_cast<int>(m_size.width());
+        sr.h = static_cast<int>(m_size.height());
+    }
+    if (target.is_null()) {
+        st.w = static_cast<int>(m_size.width());
+        st.h = static_cast<int>(m_size.height());
+    }
+
+    if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), &sr, &st) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/image_backend.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,65 @@
+/*
+ * image_backend.hpp -- image object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_IMAGE_BACKEND_HPP
+#define MALIKANIA_IMAGE_BACKEND_HPP
+
+#include <memory>
+
+#include <SDL.h>
+
+#include <malikania/size.hpp>
+#include <malikania/image.hpp>
+
+namespace malikania {
+
+class image;
+class point;
+class rectangle;
+class window;
+
+class image::backend_impl {
+private:
+    std::unique_ptr<SDL_Surface, void (*)(SDL_Surface *)> m_surface;
+    std::unique_ptr<SDL_Texture, void (*)(SDL_Texture *)> m_texture;
+
+    malikania::size m_size;
+
+    void create_texture(window& window);
+
+public:
+    backend_impl(image& self, std::string data);
+
+    inline SDL_Texture* texture() noexcept
+    {
+        return m_texture.get();
+    }
+
+    inline const malikania::size& size() const noexcept
+    {
+        return m_size;
+    }
+
+    void draw(window& window, const point& position);
+
+    void draw(window& window, const rectangle& source, const rectangle& target);
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_IMAGE_BACKEND_HPP
--- a/libclient/malikania/backend/sdl/window-backend.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * window-backend.cpp -- window object (SDL2 implementation)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 <SDL.h>
-#include <SDL_ttf.h>
-
-#include <stdexcept>
-
-#include <malikania/color.hpp>
-#include <malikania/line.hpp>
-#include <malikania/point.hpp>
-#include <malikania/rectangle.hpp>
-
-#include "font-backend.hpp"
-#include "window-backend.hpp"
-
-namespace malikania {
-
-Window::Backend::Backend(Window &, unsigned width, unsigned height, const std::string &title)
-    : m_window(nullptr, nullptr)
-    , m_renderer(nullptr, nullptr)
-{
-    SDL_SetMainReady();
-    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
-
-    m_window = WindowHandle(
-        SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL),
-        SDL_DestroyWindow
-    );
-
-    if (m_window == nullptr)
-        throw std::runtime_error(SDL_GetError());
-
-    // Create renderer.
-    m_renderer = RendererHandle(
-        SDL_CreateRenderer(m_window.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
-        SDL_DestroyRenderer
-    );
-
-    if (m_renderer == nullptr)
-        throw std::runtime_error(SDL_GetError());
-
-    if (TTF_Init() == -1)
-        throw std::runtime_error(TTF_GetError());
-}
-
-void Window::Backend::poll(Window &self)
-{
-    SDL_Event event;
-
-    while (SDL_PollEvent(&event)) {
-        switch (event.type) {
-        case SDL_KEYUP:
-            self.onKeyUp(event.key.keysym.sym);
-            break;
-        case SDL_KEYDOWN:
-            self.onKeyDown(event.key.keysym.sym);
-            break;
-        case SDL_QUIT:
-            self.onQuit();
-            break;
-        default:
-            break;
-        }
-    }
-}
-
-void Window::Backend::clear()
-{
-    SDL_RenderClear(m_renderer.get());
-}
-
-void Window::Backend::present()
-{
-    SDL_RenderPresent(m_renderer.get());
-}
-
-#if 0
-
-// TODO: see later if it's really needed
-
-Size Window::Backend::resolution()
-{
-    SDL_DisplayMode current;
-    int width = 0;
-    int height = 0;
-    for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
-        int error = SDL_GetCurrentDisplayMode(i, &current);
-        if (error == 0) {
-            // Get the last one
-            // TODO test with only one display mode, but we have to test with more than that
-            width = current.w;
-            height = current.hpp;
-        } else {
-            throw std::runtime_error("Could not get display mode for video display" + std::string(SDL_GetError()));
-        }
-    }
-
-    return Size((unsigned)width, (unsigned)height);
-}
-
-#endif
-
-Color Window::Backend::drawingColor() const
-{
-    SDL_Color color;
-
-    if (SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a) < 0)
-        throw std::runtime_error(SDL_GetError());
-
-    return Color(color.r, color.g, color.b, color.a);
-}
-
-void Window::Backend::setDrawingColor(const Color &color)
-{
-    if (SDL_SetRenderDrawColor(m_renderer.get(), color.red(), color.green(), color.blue(), color.alpha()) < 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Window::Backend::drawLine(const Line &line)
-{
-    if (SDL_RenderDrawLine(m_renderer.get(), line.x1(), line.y1(), line.x2(), line.y2()) != 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Window::Backend::drawLines(const std::vector<Point> &points)
-{
-    std::vector<SDL_Point> sdlPoints(points.size());
-
-    for (unsigned i = 0; i < points.size(); ++i)
-        sdlPoints[i] = SDL_Point{points[i].x(), points[i].y()};
-
-    if (SDL_RenderDrawLines(m_renderer.get(), sdlPoints.data(), sdlPoints.size()) < 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Window::Backend::drawPoint(const Point &point)
-{
-    if (SDL_RenderDrawPoint(m_renderer.get(), point.x(), point.y()) != 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Window::Backend::drawPoints(const std::vector<Point> &points)
-{
-    std::vector<SDL_Point> sdlPoints(points.size());
-
-    for (unsigned i = 0; i < points.size(); ++i)
-        sdlPoints[i] = SDL_Point{points[i].x(), points[i].y()};
-
-    if (SDL_RenderDrawPoints(m_renderer.get(), sdlPoints.data(), sdlPoints.size()) != 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Window::Backend::drawRectangle(const Rectangle &rectangle)
-{
-    SDL_Rect rect{rectangle.x(), rectangle.y(), static_cast<int>(rectangle.width()), static_cast<int>(rectangle.height())};
-
-    if (SDL_RenderDrawRect(m_renderer.get(), &rect) < 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Window::Backend::drawRectangles(const std::vector<Rectangle> &rectangles)
-{
-    std::vector<SDL_Rect> sdlRects(rectangles.size());
-
-    for (unsigned i = 0; i < rectangles.size(); ++i)
-        sdlRects[i] = SDL_Rect{rectangles[i].x(), rectangles[i].y(),
-                               static_cast<int>(rectangles[i].width()), static_cast<int>(rectangles[i].height())};
-
-    if (SDL_RenderDrawRects(m_renderer.get(), sdlRects.data(), sdlRects.size()) != 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Window::Backend::fillRectangle(const Rectangle &rectangle)
-{
-    SDL_Rect rect{rectangle.x(), rectangle.y(), static_cast<int>(rectangle.width()), static_cast<int>(rectangle.height())};
-
-    if (SDL_RenderFillRect(m_renderer.get(), &rect) < 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Window::Backend::fillRectangles(const std::vector<Rectangle> &rectangles)
-{
-    std::vector<SDL_Rect> sdlRects(rectangles.size());
-
-    for (unsigned i = 0; i < rectangles.size(); ++i)
-        sdlRects[i] = SDL_Rect{rectangles[i].x(), rectangles[i].y(),
-                               static_cast<int>(rectangles[i].width()), static_cast<int>(rectangles[i].height())};
-
-    if (SDL_RenderFillRects(m_renderer.get(), sdlRects.data(), sdlRects.size()) != 0)
-        throw std::runtime_error(SDL_GetError());
-}
-
-void Window::Backend::drawText(const std::string &text, Font &font, const Rectangle &rectangle)
-{
-    SDL_Color color = {0, 0, 0, 255};
-    SDL_Surface *message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
-    SDL_Texture *texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
-    SDL_Rect rect{rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
-    SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
-    SDL_FreeSurface(message);
-    SDL_DestroyTexture(texture);
-}
-
-void Window::Backend::drawText(const std::string &text, Font &font, const Point &point)
-{
-    SDL_Color color = {0, 0, 0, 0};
-    SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a);
-    SDL_Surface *message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
-    SDL_Texture *texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
-    SDL_Rect rect{point.x(), point.y(), message->w, message->h};
-    SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
-    SDL_FreeSurface(message);
-    SDL_DestroyTexture(texture);
-}
-
-void Window::Backend::close()
-{
-}
-
-} // !malikania
--- a/libclient/malikania/backend/sdl/window-backend.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * window-backend.hpp -- window object (SDL2 implementation)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_WINDOW_BACKEND_HPP
-#define MALIKANIA_WINDOW_BACKEND_HPP
-
-#include <memory>
-#include <vector>
-
-#include <SDL.h>
-
-#include <malikania/window.hpp>
-
-namespace malikania {
-
-class Window::Backend {
-private:
-    using WindowHandle = std::unique_ptr<SDL_Window, void (*)(SDL_Window *)>;
-    using RendererHandle = std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer *)>;
-
-    WindowHandle m_window;
-    RendererHandle m_renderer;
-
-public:
-    Backend(Window &self, unsigned width, unsigned height, const std::string &title);
-
-    inline SDL_Renderer *renderer() noexcept
-    {
-        return m_renderer.get();
-    }
-
-    void poll(Window &self);
-
-    void close();
-
-    void clear();
-
-    void present();
-
-    Color drawingColor() const;
-
-    void setDrawingColor(const Color &color);
-
-    void drawLine(const Line &line);
-
-    void drawLines(const std::vector<Point> &points);
-
-    void drawPoint(const Point &point);
-
-    void drawPoints(const std::vector<Point> &points);
-
-    void drawRectangle(const Rectangle &rect);
-
-    void drawRectangles(const std::vector<Rectangle> &rects);
-
-    void fillRectangle(const Rectangle &rect);
-
-    void fillRectangles(const std::vector<Rectangle> &rects);
-
-    void drawText(const std::string &text, Font &font, const Rectangle &rectangle);
-
-    void drawText(const std::string &text, Font &font, const Point &point);
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_WINDOW_BACKEND_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/window_backend.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,270 @@
+/*
+ * window_backend.cpp -- window object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 <SDL.h>
+#include <SDL_ttf.h>
+
+#include <stdexcept>
+
+#include <malikania/color.hpp>
+#include <malikania/line.hpp>
+#include <malikania/point.hpp>
+#include <malikania/rectangle.hpp>
+
+#include "font_backend.hpp"
+#include "window_backend.hpp"
+
+namespace malikania {
+
+window::backend_impl::backend_impl(window&, unsigned width, unsigned height, const std::string& title)
+    : m_window(nullptr, nullptr)
+    , m_renderer(nullptr, nullptr)
+{
+    SDL_SetMainReady();
+    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
+
+    m_window = {
+        SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL),
+        SDL_DestroyWindow
+    };
+
+    if (m_window == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    // Create renderer.
+    m_renderer = {
+        SDL_CreateRenderer(m_window.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
+        SDL_DestroyRenderer
+    };
+
+    if (m_renderer == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+    if (TTF_Init() == -1) {
+        throw std::runtime_error(TTF_GetError());
+    }
+}
+
+void window::backend_impl::poll(window&)
+{
+    SDL_Event event;
+
+    while (SDL_PollEvent(&event)) {
+        switch (event.type) {
+        case SDL_KEYUP:
+            //self.onKeyUp(event.key.keysym.sym);
+            break;
+        case SDL_KEYDOWN:
+            //self.onKeyDown(event.key.keysym.sym);
+            break;
+        case SDL_QUIT:
+            //self.onQuit();
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+void window::backend_impl::clear()
+{
+    SDL_RenderClear(m_renderer.get());
+}
+
+void window::backend_impl::present()
+{
+    SDL_RenderPresent(m_renderer.get());
+}
+
+#if 0
+
+// TODO: see later if it's really needed
+
+Size window::backend_impl::resolution()
+{
+    SDL_DisplayMode current;
+    int width = 0;
+    int height = 0;
+    for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
+        int error = SDL_GetCurrentDisplayMode(i, &current);
+        if (error == 0) {
+            // Get the last one
+            // TODO test with only one display mode, but we have to test with more than that
+            width = current.w;
+            height = current.hpp;
+        } else {
+            throw std::runtime_error("Could not get display mode for video display" + std::string(SDL_GetError()));
+        }
+    }
+
+    return Size((unsigned)width, (unsigned)height);
+}
+
+#endif
+
+color window::backend_impl::drawing_color() const
+{
+    SDL_Color color;
+
+    if (SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    return {color.r, color.g, color.b, color.a};
+}
+
+void window::backend_impl::set_drawing_color(const color& color)
+{
+    if (SDL_SetRenderDrawColor(m_renderer.get(), color.red(), color.green(), color.blue(), color.alpha()) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_line(const line& line)
+{
+    if (SDL_RenderDrawLine(m_renderer.get(), line.x1(), line.y1(), line.x2(), line.y2()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_lines(const std::vector<point>& points)
+{
+    std::vector<SDL_Point> sdlpoints(points.size());
+
+    for (unsigned i = 0; i < points.size(); ++i) {
+        sdlpoints[i] = {points[i].x(), points[i].y()};
+    }
+
+    if (SDL_RenderDrawLines(m_renderer.get(), sdlpoints.data(), sdlpoints.size()) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_point(const point& point)
+{
+    if (SDL_RenderDrawPoint(m_renderer.get(), point.x(), point.y()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_points(const std::vector<point>& points)
+{
+    std::vector<SDL_Point> sdlpoints(points.size());
+
+    for (unsigned i = 0; i < points.size(); ++i) {
+        sdlpoints[i] = {points[i].x(), points[i].y()};
+    }
+
+    if (SDL_RenderDrawPoints(m_renderer.get(), sdlpoints.data(), sdlpoints.size()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_rectangle(const rectangle& rectangle)
+{
+    SDL_Rect rect{
+        rectangle.x(),
+        rectangle.y(),
+        static_cast<int>(rectangle.width()),
+        static_cast<int>(rectangle.height())
+    };
+
+    if (SDL_RenderDrawRect(m_renderer.get(), &rect) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_rectangles(const std::vector<rectangle>& rectangles)
+{
+    std::vector<SDL_Rect> sdlrects(rectangles.size());
+
+    for (unsigned i = 0; i < rectangles.size(); ++i) {
+        sdlrects[i] = {
+            rectangles[i].x(),
+            rectangles[i].y(),
+            static_cast<int>(rectangles[i].width()),
+            static_cast<int>(rectangles[i].height())
+        };
+    }
+
+    if (SDL_RenderDrawRects(m_renderer.get(), sdlrects.data(), sdlrects.size()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::fill_rectangle(const rectangle& rectangle)
+{
+    SDL_Rect rect{
+        rectangle.x(),
+        rectangle.y(),
+        static_cast<int>(rectangle.width()),
+        static_cast<int>(rectangle.height())
+    };
+
+    if (SDL_RenderFillRect(m_renderer.get(), &rect) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::fill_rectangles(const std::vector<rectangle>& rectangles)
+{
+    std::vector<SDL_Rect> sdlrects(rectangles.size());
+
+    for (unsigned i = 0; i < rectangles.size(); ++i) {
+        sdlrects[i] = {
+            rectangles[i].x(),
+            rectangles[i].y(),
+            static_cast<int>(rectangles[i].width()),
+            static_cast<int>(rectangles[i].height())
+        };
+    }
+
+    if (SDL_RenderFillRects(m_renderer.get(), sdlrects.data(), sdlrects.size()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_text(const std::string& text, font& font, const rectangle& rectangle)
+{
+    SDL_Color color = {0, 0, 0, 255};
+    SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
+    SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
+    SDL_Rect rect = {rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
+    SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
+    SDL_FreeSurface(message);
+    SDL_DestroyTexture(texture);
+}
+
+void window::backend_impl::draw_text(const std::string &text, font& font, const point& point)
+{
+    SDL_Color color = {0, 0, 0, 0};
+    SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a);
+    SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
+    SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
+    SDL_Rect rect = {point.x(), point.y(), message->w, message->h};
+    SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
+    SDL_FreeSurface(message);
+    SDL_DestroyTexture(texture);
+}
+
+void window::backend_impl::close()
+{
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/window_backend.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,79 @@
+/*
+ * window_backend.hpp -- window object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_WINDOW_BACKEND_HPP
+#define MALIKANIA_WINDOW_BACKEND_HPP
+
+#include <memory>
+#include <vector>
+
+#include <SDL.h>
+
+#include <malikania/window.hpp>
+
+namespace malikania {
+
+class window::backend_impl {
+private:
+    std::unique_ptr<SDL_Window, void (*)(SDL_Window *)> m_window;
+    std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer *)> m_renderer;
+
+public:
+    backend_impl(window& self, unsigned width, unsigned height, const std::string& title);
+
+    inline SDL_Renderer* renderer() noexcept
+    {
+        return m_renderer.get();
+    }
+
+    void poll(window& self);
+
+    void close();
+
+    void clear();
+
+    void present();
+
+    color drawing_color() const;
+
+    void set_drawing_color(const color& color);
+
+    void draw_line(const line& line);
+
+    void draw_lines(const std::vector<point>& points);
+
+    void draw_point(const point& point);
+
+    void draw_points(const std::vector<point>& points);
+
+    void draw_rectangle(const rectangle& rect);
+
+    void draw_rectangles(const std::vector<rectangle>& rects);
+
+    void fill_rectangle(const rectangle& rect);
+
+    void fill_rectangles(const std::vector<rectangle>& rects);
+
+    void draw_text(const std::string& text, font& font, const rectangle& rectangle);
+
+    void draw_text(const std::string& text, font& font, const point& point);
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_WINDOW_BACKEND_HPP
--- a/libclient/malikania/client-resources-loader.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * client-resources-loader.cpp -- load shared resources files for the client
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "animation.hpp"
-#include "client-resources-loader.hpp"
-#include "size.hpp"
-#include "sprite.hpp"
-
-using json = nlohmann::json;
-
-namespace malikania {
-
-Size ClientResourcesLoader::requireSize(const std::string &id, const json &object, const std::string &property) const
-{
-    assert(object.is_object());
-
-    auto it = object.find(property);
-
-    if (it == object.end() || !it->is_array())
-        throw std::runtime_error(id + ": missing '" + property + "' property (array expected)");
-    if (it->size() != 2)
-        throw std::runtime_error(id + ": property '" + property + "' must have two values");
-    if (!(*it)[0].is_number_integer() || !(*it)[1].is_number_integer())
-        throw std::runtime_error(id + ": property '" + property + "' must have to integer values");
-
-    return Size((*it)[0].get<int>(), (*it)[1].get<int>());
-}
-
-Size ClientResourcesLoader::getSize(const std::string &, const json &object, const std::string &key) const noexcept
-{
-    assert(object.is_object());
-
-    auto it = object.find(key);
-
-    if (it == object.end() || !it->is_array() || it->size() != 2 || !(*it)[0].is_number_integer() || !(*it)[1].is_number_integer())
-        return Size();
-
-    return Size((*it)[0].get<int>(), (*it)[1].get<int>());
-}
-
-Font ClientResourcesLoader::loadFont(const std::string &id, unsigned size)
-{
-    return Font(locator().read(id), size);
-}
-
-Image ClientResourcesLoader::loadImage(const std::string &id)
-{
-    return Image(locator().read(id));
-}
-
-Sprite ClientResourcesLoader::loadSprite(const std::string &id)
-{
-    auto value = json::parse(locator().read(id));
-
-    if (!value.is_object())
-        throw std::runtime_error(id + ": not a JSON object");
-
-    return Sprite(
-        loadImage(requireString(id, value, "image")),
-        requireSize(id, value, "cell"),
-        getSize(id, value, "size"),
-        getSize(id, value, "space"),
-        getSize(id, value, "margin")
-    );
-}
-
-Animation ClientResourcesLoader::loadAnimation(const std::string &id)
-{
-    auto value = json::parse(locator().read(id));
-
-    if (!value.is_object())
-        throw std::runtime_error(id + ": not a JSON object");
-
-    Sprite sprite = loadSprite(requireString(id, value, "sprite"));
-
-    // Load all frames.
-    json property = value["frames"];
-
-    if (!property.is_array())
-        throw std::runtime_error(id + ": missing 'frames' property (array expected)");
-
-    AnimationFrames frames;
-
-    int index = 0;
-    for (auto it = property.begin(); it != property.end(); ++it) {
-        if (!it->is_object())
-            throw std::runtime_error(id + ": frame " + std::to_string(index) + ": not a JSON object");
-
-        auto delay = it->find("delay");
-
-        if (delay == it->end() || !delay->is_number_integer())
-            throw std::runtime_error(id + ": frame " + std::to_string(index) + ": missing 'delay' property (int expected)");
-
-        frames.emplace_back(delay->get<int>());
-    }
-
-    return Animation(std::move(sprite), std::move(frames));
-}
-
-} // !malikania
--- a/libclient/malikania/client-resources-loader.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * client-resources-loader.hpp -- load shared resources files for the client
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
-#define MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
-
-#include <malikania/resources-loader.hpp>
-
-#include "animation.hpp"
-#include "font.hpp"
-#include "image.hpp"
-#include "size.hpp"
-#include "sprite.hpp"
-
-namespace malikania {
-
-/**
- * \class ClientResourcesLoader
- * \brief Load client resources.
- */
-class ClientResourcesLoader : public ResourcesLoader {
-protected:
-    /**
-     * Require a size object from an object property.
-     *
-     * The size is an array of two integers (e.g. [ 1, 2 ]).
-     *
-     * \pre object.isObject()
-     * \param id the resource id
-     * \param object the object
-     * \param property the property
-     * \return the size
-     * \throw std::runtime_error if the property is not a size
-     */
-    Size requireSize(const std::string &id, const nlohmann::json &object, const std::string &property) const;
-
-    /**
-     * Get a size object or a default one if not present or invalid.
-     *
-     * \pre object.isObject()
-     * \param id the resource id
-     * \param object the object
-     * \param property the property
-     * \return the size or default one
-     */
-    Size getSize(const std::string &id, const nlohmann::json &object, const std::string &property) const noexcept;
-
-public:
-    /**
-     * Client resources loader constructor.
-     *
-     * The window is required because some of the resources require it.
-     *
-     * \param window the window
-     * \param locator the resources locator
-     */
-    inline ClientResourcesLoader(ResourcesLocator &locator)
-        : ResourcesLoader(locator)
-    {
-    }
-
-    /**
-     * Load a font.
-     *
-     * \param id the resource id
-     * \param size the desired size
-     * \return the font
-     * \throw std::runtime_error on errors
-     */
-    virtual Font loadFont(const std::string &id, unsigned size);
-
-    /**
-     * Load an image.
-     *
-     * \param id the resource id
-     * \return the image
-     * \throw std::runtime_error on errors
-     */
-    virtual Image loadImage(const std::string &id);
-
-    /**
-     * Load a sprite.
-     *
-     * \param id the resource id
-     * \return the sprite
-     * \throw std::runtime_error on errors
-     */
-    virtual Sprite loadSprite(const std::string &id);
-
-    /**
-     * Load an animation.
-     *
-     * \param id the resource id
-     * \return the animation
-     * \throw std::runtime_error on errors
-     */
-    virtual Animation loadAnimation(const std::string &id);
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
--- a/libclient/malikania/client.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/client.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -19,6 +19,8 @@
 #ifndef MALIKANIA_CLIENT_HPP
 #define MALIKANIA_CLIENT_HPP
 
+#if 0
+
 #include <memory>
 
 #include "window.hpp"
@@ -70,4 +72,6 @@
 
 } // !malikania
 
+#endif
+
 #endif // !MALIKANIA_CLIENT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client_resources_loader.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,134 @@
+/*
+ * client_resources_loader.cpp -- load shared resources files for the client
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 <boost/format.hpp>
+
+#include <cassert>
+
+#include "animation.hpp"
+#include "client_resources_loader.hpp"
+#include "size.hpp"
+#include "sprite.hpp"
+
+using boost::str;
+using boost::format;
+
+namespace malikania {
+
+size client_resources_loader::require_size(const std::string& id,
+                                           const nlohmann::json& object,
+                                           const std::string& property) const
+{
+    assert(object.is_object());
+
+    auto it = object.find(property);
+
+    if (it == object.end() || !it->is_array()) {
+        throw std::runtime_error(str(format("%s: missing '%' property (array expected)") % id % property));
+    }
+    if (it->size() != 2) {
+        throw std::runtime_error(str(format("%s: property '%s' muve have two values") % id % property));
+    }
+    if (!(*it)[0].is_number_integer() || !(*it)[1].is_number_integer()) {
+        throw std::runtime_error(str(format("%s: property '%s' must contains two ints")));
+    }
+
+    return size((*it)[0].get<int>(), (*it)[1].get<int>());
+}
+
+size client_resources_loader::get_size(const std::string&,
+                                       const nlohmann::json& object,
+                                       const std::string& key) const noexcept
+{
+    assert(object.is_object());
+
+    auto it = object.find(key);
+
+    if (it == object.end() || !it->is_array() || it->size() != 2 ||
+        !(*it)[0].is_number_integer() || !(*it)[1].is_number_integer()) {
+        return size();
+    }
+
+    return size((*it)[0].get<int>(), (*it)[1].get<int>());
+}
+
+font client_resources_loader::load_font(const std::string& id, unsigned size)
+{
+    return font(locator().read(id), size);
+}
+
+image client_resources_loader::load_image(const std::string& id)
+{
+    return image(locator().read(id));
+}
+
+sprite client_resources_loader::load_sprite(const std::string& id)
+{
+    auto value = nlohmann::json::parse(locator().read(id));
+
+    if (!value.is_object()) {
+        throw std::runtime_error(id + ": not a JSON object");
+    }
+
+    return sprite(
+        load_image(require_string(id, value, "image")),
+        require_size(id, value, "cell"),
+        get_size(id, value, "size"),
+        get_size(id, value, "space"),
+        get_size(id, value, "margin")
+    );
+}
+
+animation client_resources_loader::load_animation(const std::string& id)
+{
+    auto value = nlohmann::json::parse(locator().read(id));
+
+    if (!value.is_object()) {
+        throw std::runtime_error(id + ": not a JSON object");
+    }
+
+    auto sprite = load_sprite(require_string(id, value, "sprite"));
+
+    // Load all frames.
+    auto property = value["frames"];
+
+    if (!property.is_array()) {
+        throw std::runtime_error(id + ": missing 'frames' property (array expected)");
+    }
+
+    animation_frames frames;
+    int index = 0;
+
+    for (auto it = property.begin(); it != property.end(); ++it) {
+        if (!it->is_object()) {
+            throw std::runtime_error(id + ": frame " + std::to_string(index) + ": not a JSON object");
+        }
+
+        auto delay = it->find("delay");
+
+        if (delay == it->end() || !delay->is_number_integer()) {
+            throw std::runtime_error(id + ": frame " + std::to_string(index) + ": missing 'delay' property (int expected)");
+        }
+
+        frames.emplace_back(delay->get<int>());
+    }
+
+    return animation(std::move(sprite), std::move(frames));
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client_resources_loader.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,125 @@
+/*
+ * client_resources_loader.hpp -- load shared resources files for the client
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
+#define MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
+
+/*
+ * \file client_resources_loader.hpp
+ * \brief Load client assets.
+ */
+
+#include <malikania/resources_loader.hpp>
+
+#include "animation.hpp"
+#include "font.hpp"
+#include "image.hpp"
+#include "size.hpp"
+#include "sprite.hpp"
+
+namespace malikania {
+
+/**
+ * \brief Load client resources.
+ */
+class client_resources_loader : public resources_loader {
+protected:
+    /**
+     * Require a size object from an object property.
+     *
+     * The size is an array of two integers (e.g. [ 1, 2 ]).
+     *
+     * \pre object.is_object()
+     * \param id the resource id
+     * \param object the object
+     * \param property the property
+     * \return the size
+     * \throw std::runtime_error if the property is not a size
+     */
+    size require_size(const std::string& id,
+                      const nlohmann::json& object,
+                      const std::string& property) const;
+
+    /**
+     * Get a size object or a default one if not present or invalid.
+     *
+     * \pre object.is_object()
+     * \param id the resource id
+     * \param object the object
+     * \param property the property
+     * \return the size or default one
+     */
+    size get_size(const std::string& id,
+                  const nlohmann::json& object,
+                  const std::string& property) const noexcept;
+
+public:
+    /**
+     * Client resources loader constructor.
+     *
+     * The window is required because some of the resources require it.
+     *
+     * \param window the window
+     * \param locator the resources locator
+     */
+    inline client_resources_loader(resources_locator& locator)
+        : resources_loader(locator)
+    {
+    }
+
+    /**
+     * Load a font.
+     *
+     * \param id the resource id
+     * \param size the desired size
+     * \return the font
+     * \throw std::runtime_error on errors
+     */
+    virtual font load_font(const std::string& id, unsigned size);
+
+    /**
+     * Load an image.
+     *
+     * \param id the resource id
+     * \return the image
+     * \throw std::runtime_error on errors
+     */
+    virtual image load_image(const std::string& id);
+
+    /**
+     * Load a sprite.
+     *
+     * \param id the resource id
+     * \return the sprite
+     * \throw std::runtime_error on errors
+     */
+    virtual sprite load_sprite(const std::string& id);
+
+    /**
+     * Load an animation.
+     *
+     * \param id the resource id
+     * \return the animation
+     * \throw std::runtime_error on errors
+     */
+    virtual animation load_animation(const std::string& id);
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
--- a/libclient/malikania/color.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/color.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -16,8 +16,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cctype>
+#include <locale>
 #include <unordered_map>
-#include <cctype>
 
 #include "color.hpp"
 
@@ -35,10 +36,12 @@
  */
 std::uint8_t value(char digit)
 {
-    if (std::isdigit(digit))
+    if (std::isdigit(digit, {})) {
         return digit - '0';
-    if ((digit = std::toupper(digit)) < 'A' || digit > 'F')
+    }
+    if ((digit = std::toupper(digit, {})) < 'A' || digit > 'F') {
         throw std::invalid_argument("invalid hexadecimal value: " + std::to_string(digit));
+    }
 
     return digit - 55;
 }
@@ -201,7 +204,7 @@
 
 } // !namespace
 
-Color::Color(const std::string &name)
+color::color(const std::string& name)
 {
     if (!name.empty()) {
         // Parse #rrggbb or #rgb.
@@ -214,14 +217,16 @@
                 m_red   = value(name[1], name[1]);
                 m_green = value(name[2], name[2]);
                 m_blue  = value(name[3], name[3]);
-            } else
+            } else {
                 throw std::invalid_argument("invalid format");
+            }
         } else {
             // Name lookup.
             auto it = colors.find(name);
 
-            if (it == colors.end())
+            if (it == colors.end()) {
                 throw std::invalid_argument(name + " is not a valid color");
+            }
 
             // Assign the color to *this.
             *this = it->second;
--- a/libclient/malikania/color.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/color.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -19,16 +19,20 @@
 #ifndef MALIKANIA_COLOR_HPP
 #define MALIKANIA_COLOR_HPP
 
+/**
+ * \file color.hpp
+ * \brief Colors.
+ */
+
 #include <cstdint>
 #include <string>
 
 namespace malikania {
 
 /**
- * \class Color
- * \brief Color description
+ * \brief color description
  */
-class Color {
+class color {
 private:
     std::uint8_t m_red{0};
     std::uint8_t m_green{0};
@@ -39,7 +43,7 @@
     /**
      * Default color to black.
      */
-    inline Color() noexcept = default;
+    inline color() noexcept = default;
 
     /**
      * Constructor with all fields.
@@ -49,7 +53,7 @@
      * \param blue the blue value
      * \param alpha the alpha value
      */
-    inline Color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha) noexcept
+    inline color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha) noexcept
         : m_red(red)
         , m_green(green)
         , m_blue(blue)
@@ -62,7 +66,7 @@
      *
      * \param hex the color
      */
-    inline Color(std::uint32_t hex) noexcept
+    inline color(std::uint32_t hex) noexcept
         : m_red((hex >> 16) & 0xff)
         , m_green((hex >> 8) & 0xff)
         , m_blue(hex & 0xff)
@@ -78,7 +82,7 @@
      * \param name the color name
      * \throw std::invalid_argument if the color does not exist or is invalid
      */
-    Color(const std::string &name);
+    color(const std::string& name);
 
     /**
      * Get the red value.
--- a/libclient/malikania/font.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/font.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -16,25 +16,25 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "font-backend.hpp"
+#include "font_backend.hpp"
 
 namespace malikania {
 
-Font::Font(std::string data, unsigned size)
-    : m_backend(std::make_unique<Backend>(std::move(data), size))
+font::font(std::string data, unsigned size)
+    : m_backend(std::make_unique<backend_impl>(std::move(data), size))
     , m_size(size)
 {
 }
 
-Font::Font(Font &&other) noexcept = default;
+font::font(font&& other) noexcept = default;
 
-Font::~Font() noexcept = default;
+font::~font() noexcept = default;
 
-Size Font::clip(const std::string &text) const
+size font::clip(const std::string& text) const
 {
     return m_backend->clip(*this, text);
 }
 
-Font &Font::operator=(Font &&other) noexcept = default;
+font& font::operator=(font&& other) noexcept = default;
 
 } // !malikania
--- a/libclient/malikania/font.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/font.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -20,8 +20,8 @@
 #define MALIKANIA_FONT_HPP
 
 /**
- * \file Font.hpp
- * \brief Fonts.
+ * \file font.hpp
+ * \brief fonts.
  */
 
 #include <memory>
@@ -32,14 +32,13 @@
 namespace malikania {
 
 /**
- * \class Font
- * \brief Font object.
+ * \brief font object.
  */
-class Font {
+class font {
 private:
-    class Backend;
+    class backend_impl;
 
-    std::unique_ptr<Backend> m_backend;
+    std::unique_ptr<backend_impl> m_backend;
     unsigned m_size;
 
 public:
@@ -49,19 +48,19 @@
      * \param data the raw data
      * \param size the size
      */
-    Font(std::string data, unsigned size);
+    font(std::string data, unsigned size);
 
     /**
      * Default move constructor.
      *
      * \param other the other font
      */
-    Font(Font &&other) noexcept;
+    font(font&& other) noexcept;
 
     /**
      * Default destructor.
      */
-    virtual ~Font() noexcept;
+    virtual ~font() noexcept;
 
     /**
      * Get the font size.
@@ -78,7 +77,7 @@
      *
      * \return the backend
      */
-    inline const Backend &backend() const noexcept
+    inline const backend_impl& backend() const noexcept
     {
         return *m_backend;
     }
@@ -88,7 +87,7 @@
      *
      * \return the backend
      */
-    inline Backend &backend() noexcept
+    inline backend_impl& backend() noexcept
     {
         return *m_backend;
     }
@@ -99,7 +98,7 @@
      * \param text the text to clip
      * \return the required size
      */
-    Size clip(const std::string &text) const;
+    malikania::size clip(const std::string& text) const;
 
     /**
      * Default move assignment operator.
@@ -107,7 +106,7 @@
      * \param other the other font
      * \return this
      */
-    Font &operator=(Font &&other) noexcept;
+    font& operator=(font&& other) noexcept;
 };
 
 } // !malikania
--- a/libclient/malikania/image.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/image.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -16,34 +16,34 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "image-backend.hpp"
+#include "image_backend.hpp"
 
 namespace malikania {
 
-Image::Image(std::string data)
-    : m_backend(std::make_unique<Backend>(*this, std::move(data)))
+image::image(std::string data)
+    : m_backend(new backend_impl(*this, std::move(data)))
 {
 }
 
-Image::Image(Image &&) noexcept = default;
+image::image(image&&) noexcept = default;
 
-Image::~Image() noexcept = default;
+image::~image() noexcept = default;
 
-const Size &Image::size() const noexcept
+const malikania::size& image::size() const noexcept
 {
     return m_backend->size();
 }
 
-void Image::draw(Window &window, const Point &position)
+void image::draw(window& window, const point& position)
 {
     m_backend->draw(window, position);
 }
 
-void Image::draw(Window &window, const Rectangle &source, const Rectangle &target)
+void image::draw(window& window, const rectangle& source, const rectangle& target)
 {
     m_backend->draw(window, source, target);
 }
 
-Image &Image::operator=(Image &&) noexcept = default;
+image& image::operator=(image&&) noexcept = default;
 
 } // !malikania
--- a/libclient/malikania/image.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/image.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -33,17 +33,16 @@
 
 namespace malikania {
 
-class Window;
+class window;
 
 /**
- * \class Image
  * \brief Image object.
  */
-class Image {
+class image {
 private:
-    class Backend;
+    class backend_impl;
 
-    std::unique_ptr<Backend> m_backend;
+    std::unique_ptr<backend_impl> m_backend;
 
 public:
     /**
@@ -52,26 +51,26 @@
      * \param window the window
      * \param data the data
      */
-    Image(std::string data);
+    image(std::string data);
 
     /**
      * Default move constructor.
      *
      * \param other the other image
      */
-    Image(Image &&other) noexcept;
+    image(image&& other) noexcept;
 
     /**
      * Default destructor.
      */
-    ~Image() noexcept;
+    ~image() noexcept;
 
     /**
      * Overloaded function.
      *
      * \return the backend
      */
-    inline Backend &backend() noexcept
+    inline class backend_impl& backend() noexcept
     {
         return *m_backend;
     }
@@ -81,7 +80,7 @@
      *
      * \return the backend
      */
-    inline const Backend &backend() const noexcept
+    inline const backend_impl& backend() const noexcept
     {
         return *m_backend;
     }
@@ -91,7 +90,7 @@
      *
      * \return the size
      */
-    const Size &size() const noexcept;
+    const malikania::size& size() const noexcept;
 
     /**
      * Draw the image to the window.
@@ -99,7 +98,7 @@
      * \param window the window
      * \param position the position
      */
-    void draw(Window &window, const Point &position = {0, 0});
+    void draw(window& window, const point& position = {0, 0});
 
     /**
      * Overloaded function.
@@ -108,7 +107,7 @@
      * \param source the source to clip
      * \param target the target destination
      */
-    void draw(Window &window, const Rectangle &source, const Rectangle &target);
+    void draw(window& window, const rectangle& source, const rectangle& target);
 
     /**
      * Default move assignment operator.
@@ -116,7 +115,7 @@
      * \param other the other image
      * \return this
      */
-    Image &operator=(Image &&image) noexcept;
+    image& operator=(image&& image) noexcept;
 };
 
 } // !malikania
--- a/libclient/malikania/line.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/line.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,18 +21,17 @@
 
 /**
  * \file line.hpp
- * \brief Line description.
+ * \brief line description.
  */
 
 namespace malikania {
 
 /**
- * \class Line
- * \brief Line description.
+ * \brief line description.
  *
  * A line has an origin (x, y) and a destination (x, y).
  */
-class Line {
+class line {
 private:
     int m_x1;
     int m_y1;
@@ -48,7 +47,7 @@
      * \param x2 the second x
      * \param y2 the second y
      */
-    inline Line(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0) noexcept
+    inline line(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0) noexcept
         : m_x1(x1)
         , m_y1(y1)
         , m_x2(x2)
@@ -104,7 +103,7 @@
  * \param l2 the second line
  * \return true if they equal
  */
-inline bool operator==(const Line &l1, const Line &l2) noexcept
+inline bool operator==(const line& l1, const line& l2) noexcept
 {
     return l1.x1() == l2.x1() && l1.x2() == l2.x2() && l1.y1() == l2.y1() && l1.y2() == l2.y2();
 }
@@ -116,7 +115,7 @@
  * \param l2 the second line
  * \return false if they equal
  */
-inline bool operator!=(const Line &l1, const Line &l2) noexcept
+inline bool operator!=(const line& l1, const line& l2) noexcept
 {
     return !(l1 == l2);
 }
--- a/libclient/malikania/point.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/point.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,16 +21,15 @@
 
 /**
  * \file point.hpp
- * \brief Point description.
+ * \brief point description.
  */
 
 namespace malikania {
 
 /**
- * \class Point
- * \brief Point coordinate.
+ * \brief point coordinate.
  */
-class Point {
+class point {
 private:
     int m_x;
     int m_y;
@@ -42,7 +41,7 @@
      * \param x the x
      * \param y the y
      */
-    inline Point(int x = 0, int y = 0) noexcept
+    inline point(int x = 0, int y = 0) noexcept
         : m_x(x)
         , m_y(y)
     {
@@ -76,7 +75,7 @@
  * \param p2 the second point
  * \return true if they equal
  */
-inline bool operator==(const Point &p1, const Point &p2) noexcept
+inline bool operator==(const point& p1, const point& p2) noexcept
 {
     return p1.x() == p2.x() && p1.y() == p2.y();
 }
@@ -88,7 +87,7 @@
  * \param p2 the second point
  * \return false if they equal
  */
-inline bool operator!=(const Point &p1, const Point &p2) noexcept
+inline bool operator!=(const point& p1, const point& p2) noexcept
 {
     return !(p1 == p2);
 }
--- a/libclient/malikania/rectangle.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/rectangle.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,20 +21,19 @@
 
 /**
  * \file rectangle.hpp
- * \brief Rectangle description.
+ * \brief rectangle description.
  */
 
 namespace malikania {
 
 /**
- * \class Rectangle
- * \brief Rectangle description.
+ * \brief rectangle description.
  *
  * A rectangle has coordinates (x, y) and dimensions (width, height).
  *
  * They are commonly used for clipping images into the window.
  */
-class Rectangle {
+class rectangle {
 private:
     int m_x;
     int m_y;
@@ -50,7 +49,7 @@
      * \param width the width
      * \param height the height
      */
-    inline Rectangle(int x = 0, int y = 0, unsigned width = 0, unsigned height = 0) noexcept
+    inline rectangle(int x = 0, int y = 0, unsigned width = 0, unsigned height = 0) noexcept
         : m_x(x)
         , m_y(y)
         , m_width(width)
@@ -103,7 +102,7 @@
      *
      * \return true if weight and height are 0
      */
-    inline bool isNull() const noexcept
+    inline bool is_null() const noexcept
     {
         return m_width == 0 && m_height == 0;
     }
@@ -116,9 +115,10 @@
  * \param r2 the second rectangle
  * \return true if they equal
  */
-inline bool operator==(const Rectangle &r1, const Rectangle &r2) noexcept
+inline bool operator==(const rectangle& r1, const rectangle& r2) noexcept
 {
-    return r1.x() == r2.x() && r1.y() == r2.y() && r1.width() == r2.width() && r1.height() == r2.height();
+    return r1.x() == r2.x() && r1.y() == r2.y() &&
+           r1.width() == r2.width() && r1.height() == r2.height();
 }
 
 /**
@@ -128,7 +128,7 @@
  * \param r2 the second rectangle
  * \return false if they equal
  */
-inline bool operator!=(const Rectangle &r1, const Rectangle &r2) noexcept
+inline bool operator!=(const rectangle& r1, const rectangle& r2) noexcept
 {
     return !(r1 == r2);
 }
--- a/libclient/malikania/size.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/size.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -22,10 +22,9 @@
 namespace malikania {
 
 /**
- * \class Size
- * \brief Size description.
+ * \brief size description.
  */
-class Size {
+class size {
 private:
     unsigned m_width;
     unsigned m_height;
@@ -37,7 +36,7 @@
      * \param width the size width
      * \param height the size height
      */
-    inline Size(unsigned width = 0, unsigned height = 0) noexcept
+    inline size(unsigned width = 0, unsigned height = 0) noexcept
         : m_width(width)
         , m_height(height)
     {
@@ -68,7 +67,7 @@
      *
      * \return true if height and width are 0
      */
-    inline bool isNull() const noexcept
+    inline bool is_null() const noexcept
     {
         return m_height == 0 && m_width == 0;
     }
@@ -81,7 +80,7 @@
  * \param s2 the second size
  * \return true if they equal
  */
-inline bool operator==(const Size &s1, const Size &s2) noexcept
+inline bool operator==(const size& s1, const size& s2) noexcept
 {
     return s1.width() == s2.width() && s1.height() == s2.height();
 }
@@ -93,7 +92,7 @@
  * \param s2 the second size
  * \return false if they equal
  */
-inline bool operator!=(const Size &s1, const Size &s2) noexcept
+inline bool operator!=(const size& s1, const size& s2) noexcept
 {
     return !(s1 == s2);
 }
--- a/libclient/malikania/sprite.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/sprite.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -22,7 +22,11 @@
 
 namespace malikania {
 
-Sprite::Sprite(Image image, Size cell, Size size, Size space, Size margin) noexcept
+sprite::sprite(malikania::image image,
+               malikania::size cell,
+               malikania::size size,
+               malikania::size space,
+               malikania::size margin) noexcept
     : m_image(std::move(image))
     , m_cell(std::move(cell))
     , m_margin(std::move(margin))
@@ -33,15 +37,16 @@
     assert(m_cell.height() > 0);
 
     // If size is not specified, take from image.
-    if (m_size.isNull())
+    if (m_size.is_null()) {
         m_size = m_image.size();
+    }
 
     // Compute number of cells.
     m_rows = (m_size.height() - (margin.height() * 2) + m_space.height()) / (m_cell.height() + m_space.height());
     m_columns = (m_size.width() - (m_margin.width() * 2) + m_space.width()) / (m_cell.width() + m_space.width());
 }
 
-void Sprite::draw(Window &window, unsigned cell, const Point &point)
+void sprite::draw(window& window, unsigned cell, const point& point)
 {
     assert(cell < m_rows * m_columns);
 
@@ -53,8 +58,8 @@
     int x = m_margin.width() + (hindex * m_space.width()) + (hindex * m_cell.width());
     int y = m_margin.height() + (vindex * m_space.height()) + (vindex * m_cell.height());
 
-    Rectangle source(x, y, m_cell.width(), m_cell.height());
-    Rectangle target(point.x(), point.y(), m_cell.width(), m_cell.height());
+    rectangle source(x, y, m_cell.width(), m_cell.height());
+    rectangle target(point.x(), point.y(), m_cell.width(), m_cell.height());
 
     m_image.draw(window, source, target);
 }
--- a/libclient/malikania/sprite.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/sprite.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -28,20 +28,16 @@
 
 namespace malikania {
 
-class Point;
-class Window;
-
 /**
- * \class Sprite
  * \brief A Sprite is an image divided into cells.
  */
-class Sprite {
+class sprite {
 private:
-    Image m_image;
-    Size m_cell;
-    Size m_margin;
-    Size m_space;
-    Size m_size;
+    malikania::image m_image;
+    malikania::size m_cell;
+    malikania::size m_margin;
+    malikania::size m_space;
+    malikania::size m_size;
     unsigned m_rows;
     unsigned m_columns;
 
@@ -56,14 +52,18 @@
      * \param space the optional space between cells
      * \param size the sprite size (if 0, taken from the image)
      */
-    Sprite(Image image, Size cell, Size margin = { 0, 0 }, Size space = { 0, 0 }, Size size = { 0, 0 }) noexcept;
+    sprite(malikania::image image,
+           malikania::size cell,
+           malikania::size margin = { 0, 0 },
+           malikania::size space = { 0, 0 },
+           malikania::size size = { 0, 0 }) noexcept;
 
     /**
      * Get the underlying image.
      *
      * \return the image
      */
-    inline const Image &image() const noexcept
+    inline const malikania::image& image() const noexcept
     {
         return m_image;
     }
@@ -73,7 +73,7 @@
      *
      * \return the image
      */
-    inline Image &image() noexcept
+    inline malikania::image& image() noexcept
     {
         return m_image;
     }
@@ -83,7 +83,7 @@
      *
      * \return the cell size
      */
-    inline const Size &cell() const noexcept
+    inline const size& cell() const noexcept
     {
         return m_cell;
     }
@@ -93,7 +93,7 @@
      *
      * \return the margin size
      */
-    inline const Size &margin() noexcept
+    inline const size& margin() noexcept
     {
         return m_margin;
     }
@@ -103,7 +103,7 @@
      *
      * \return the space size
      */
-    inline const Size &space() const noexcept
+    inline const size& space() const noexcept
     {
         return m_space;
     }
@@ -136,7 +136,7 @@
      * \param cell the cell index
      * \param position the position in the window
      */
-    void draw(Window &window, unsigned cell, const Point &position);
+    void draw(window& window, unsigned cell, const point& position);
 };
 
 } // !malikania
--- a/libclient/malikania/window.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/window.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -19,100 +19,100 @@
 #include <stdexcept>
 
 #include "color.hpp"
-#include "window-backend.hpp"
+#include "window_backend.hpp"
 
 namespace malikania {
 
-Window::Window(unsigned width, unsigned height, const std::string &title)
-    : m_backend(std::make_unique<Backend>(*this, width, height, title))
+window::window(unsigned width, unsigned height, const std::string& title)
+    : m_backend(std::make_unique<backend_impl>(*this, width, height, title))
 {
 }
 
-Window::Window(Window &&) = default;
+window::window(window&&) noexcept = default;
 
-Window::~Window() = default;
+window::~window() noexcept = default;
 
-void Window::poll()
+void window::poll()
 {
     m_backend->poll(*this);
 }
 
-void Window::clear()
+void window::clear()
 {
     m_backend->clear();
 }
 
-void Window::present()
+void window::present()
 {
     m_backend->present();
 }
 
-void Window::close() noexcept
+void window::close() noexcept
 {
-    m_isOpen = false;
+    m_is_open = false;
     m_backend->close();
 }
 
-Color Window::drawingColor() const
+color window::drawing_color() const
 {
-    return m_backend->drawingColor();
+    return m_backend->drawing_color();
 }
 
-void Window::setDrawingColor(const Color &color)
+void window::set_drawing_color(const color& color)
 {
-    m_backend->setDrawingColor(color);
+    m_backend->set_drawing_color(color);
 }
 
-void Window::drawLine(const Line &line)
+void window::draw_line(const line& line)
 {
-    m_backend->drawLine(line);
+    m_backend->draw_line(line);
 }
 
-void Window::drawLines(const std::vector<Point> &points)
+void window::draw_lines(const std::vector<point>& points)
 {
-    m_backend->drawLines(points);
+    m_backend->draw_lines(points);
 }
 
-void Window::drawPoint(const Point &point)
+void window::draw_point(const point& point)
 {
-    m_backend->drawPoint(point);
+    m_backend->draw_point(point);
 }
 
-void Window::drawPoints(const std::vector<Point> &points)
+void window::draw_points(const std::vector<point>& points)
 {
-    m_backend->drawPoints(points);
+    m_backend->draw_points(points);
 }
 
-void Window::drawRectangle(const Rectangle &rectangle)
+void window::draw_rectangle(const rectangle& rectangle)
 {
-    m_backend->drawRectangle(rectangle);
+    m_backend->draw_rectangle(rectangle);
 }
 
-void Window::drawRectangles(const std::vector<Rectangle> &rectangles)
+void window::draw_rectangles(const std::vector<rectangle>& rectangles)
 {
-    m_backend->drawRectangles(rectangles);
+    m_backend->draw_rectangles(rectangles);
 }
 
-void Window::fillRectangle(const Rectangle &rectangle)
+void window::fill_rectangle(const rectangle& rectangle)
 {
-    m_backend->fillRectangle(rectangle);
+    m_backend->fill_rectangle(rectangle);
 }
 
-void Window::fillRectangles(const std::vector<Rectangle> &rectangles)
+void window::fill_rectangles(const std::vector<rectangle>& rectangles)
 {
-    m_backend->fillRectangles(rectangles);
+    m_backend->fill_rectangles(rectangles);
 }
 
-void Window::drawText(const std::string &text, Font &font, const Rectangle &rectangle)
+void window::draw_text(const std::string& text, font& font, const rectangle& rectangle)
 {
-    m_backend->drawText(text, font, rectangle);
+    m_backend->draw_text(text, font, rectangle);
 }
 
-void Window::drawText(const std::string &text, Font &font, const Point &point)
+void window::draw_text(const std::string& text, font& font, const point& point)
 {
-    m_backend->drawText(text, font, point);
+    m_backend->draw_text(text, font, point);
 }
 
-Window &Window::operator=(Window &&) = default;
+window& window::operator=(window&&) noexcept = default;
 
 } // !malikania
--- a/libclient/malikania/window.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libclient/malikania/window.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -31,61 +31,24 @@
 
 namespace malikania {
 
-class Color;
-class Line;
-class Font;
-class Point;
-class Rectangle;
+class color;
+class line;
+class font;
+class point;
+class rectangle;
 
 /**
  * \brief Main window class and drawing.
  */
-class Window  {
+class window {
 private:
-    class Backend;
+    class backend_impl;
 
-    std::function<void ()> m_onQuit;
-    std::function<void (unsigned)> m_onKeyDown;
-    std::function<void (unsigned)> m_onKeyUp;
+    std::unique_ptr<backend_impl> m_backend;
 
-    std::unique_ptr<Backend> m_backend;
-
-    bool m_isOpen{true};
+    bool m_is_open{true};
 
 public:
-    inline void onQuit()
-    {
-        if (m_onQuit)
-            m_onQuit();
-    }
-
-    inline void onKeyDown(unsigned key)
-    {
-        if (m_onKeyDown)
-            m_onKeyDown(key);
-    }
-
-    inline void onKeyUp(unsigned key)
-    {
-        if (m_onKeyUp)
-            m_onKeyUp(key);
-    }
-
-    inline void setOnQuit(std::function<void ()> fn) noexcept
-    {
-        m_onQuit = std::move(fn);
-    }
-
-    inline void setOnKeyDown(std::function<void (unsigned)> fn) noexcept
-    {
-        m_onKeyDown = std::move(fn);
-    }
-
-    inline void setOnKeyUp(std::function<void (unsigned)> fn) noexcept
-    {
-        m_onKeyUp = std::move(fn);
-    }
-
     /**
      * Create a window.
      *
@@ -94,26 +57,26 @@
      * \param title the optional title
      * \throw std::runtime_error on errors
      */
-    Window(unsigned width = 640, unsigned height = 480, const std::string &title = "Malikania");
+    window(unsigned width = 640, unsigned height = 480, const std::string& title = "Malikania Engine");
 
     /**
      * Move constructor defaulted.
      */
-    Window(Window &&);
+    window(window&&) noexcept;
 
     /**
      * Virtual destructor defaulted.
      */
-    virtual ~Window();
+    virtual ~window() noexcept;
 
     /**
      * Tells if the window is open.
      *
      * \return true if open
      */
-    inline bool isOpen() const noexcept
+    inline bool is_open() const noexcept
     {
-        return m_isOpen;
+        return m_is_open;
     }
 
     /**
@@ -121,7 +84,7 @@
      *
      * \return the backend
      */
-    inline const Backend &backend() const noexcept
+    inline const backend_impl& backend() const noexcept
     {
         return *m_backend;
     }
@@ -131,7 +94,7 @@
      *
      * \return the backend
      */
-    inline Backend &backend() noexcept
+    inline backend_impl& backend() noexcept
     {
         return *m_backend;
     }
@@ -161,42 +124,42 @@
      *
      * \return the color
      */
-    Color drawingColor() const;
+    color drawing_color() const;
 
     /**
      * Set the drawing color.
      *
      * \param color the color
      */
-    void setDrawingColor(const Color &color);
+    void set_drawing_color(const color& color);
 
     /**
      * Draw a line.
      *
      * \param line the line
      */
-    void drawLine(const Line &line);
+    void draw_line(const line& line);
 
     /**
      * Draw a several lines.
      *
      * \param the lines vertices
      */
-    void drawLines(const std::vector<Point> &points);
+    void draw_lines(const std::vector<point>& points);
 
     /**
      * Draw a point.
      *
      * \param point the point
      */
-    void drawPoint(const Point &point);
+    void draw_point(const point& point);
 
     /**
      * Draw a list of points.
      *
      * \param points the points
      */
-    void drawPoints(const std::vector<Point> &points);
+    void draw_points(const std::vector<point>& points);
 
     /**
      * Draw a rectangle (only borders).
@@ -204,7 +167,7 @@
      * \param rect the rectangle
      * \see fillRectangle
      */
-    void drawRectangle(const Rectangle &rect);
+    void draw_rectangle(const rectangle& rect);
 
     /**
      * Draw a list of rectangles.
@@ -212,7 +175,7 @@
      * \param rects the rectangles
      * \see fillRectangles
      */
-    void drawRectangles(const std::vector<Rectangle> &rects);
+    void draw_rectangles(const std::vector<rectangle>& rects);
 
     /**
      * Fill the given rectangle with the current color.
@@ -220,7 +183,7 @@
      * \param rect the rectangle
      * \see drawRectangle
      */
-    void fillRectangle(const Rectangle &rect);
+    void fill_rectangle(const rectangle& rect);
 
     /**
      * Fill the list of rectangles with the current color.
@@ -228,7 +191,7 @@
      * \param rects the list of rectangles
      * \see drawRectangles
      */
-    void fillRectangles(const std::vector<Rectangle> &rects);
+    void fill_rectangles(const std::vector<rectangle>& rects);
 
     /**
      * Draw some text.
@@ -239,7 +202,7 @@
      * \param font the font
      * \param rectangle the rectangle target
      */
-    void drawText(const std::string &text, Font &font, const Rectangle &rectangle);
+    void draw_text(const std::string& text, font& font, const rectangle& rectangle);
 
     /**
      * Overloaded function.
@@ -250,16 +213,16 @@
      * \param font the font
      * \param point the text position
      */
-    void drawText(const std::string &text, Font &font, const Point &point);
+    void draw_text(const std::string& text, font& font, const point& point);
 
     /**
      * Move assigment operator defaulted.
      *
      * \return this
      */
-    Window &operator=(Window &&);
+    window& operator=(window&&) noexcept;
 };
 
 } // !malikania
 
-#endif // !_MALIKANIA_WINDOW_HPP_
+#endif // !MALIKANIA_WINDOW_HPP
--- a/libcommon-js/CMakeLists.txt	Sun Nov 27 20:50:38 2016 +0100
+++ b/libcommon-js/CMakeLists.txt	Tue Nov 29 21:21:36 2016 +0100
@@ -20,14 +20,14 @@
 
 set(
     HEADERS
-    ${libcommon-js_SOURCE_DIR}/malikania/js-elapsed-timer.hpp
-    ${libcommon-js_SOURCE_DIR}/malikania/js-resources-loader.hpp
+    ${libcommon-js_SOURCE_DIR}/malikania/js_elapsed_timer.hpp
+    ${libcommon-js_SOURCE_DIR}/malikania/js_resources_loader.hpp
 )
 
 set(
     SOURCES
-    ${libcommon-js_SOURCE_DIR}/malikania/js-elapsed-timer.cpp
-    ${libcommon-js_SOURCE_DIR}/malikania/js-resources-loader.cpp
+    ${libcommon-js_SOURCE_DIR}/malikania/js_elapsed_timer.cpp
+    ${libcommon-js_SOURCE_DIR}/malikania/js_resources_loader.cpp
 )
 
 malikania_create_library(
--- a/libcommon-js/malikania/js-elapsed-timer.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- * js-elapsed-timer.cpp --
- *
- * Copyright (c) 2013-2016 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 <boost/timer/timer.hpp>
-
-#include <cassert>
-#include <string>
-
-#include "duktape.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff" "\xff" "malikania-elapsed-timer-ptr");
-
-boost::timer::cpu_timer& self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an ElapsedTimer object");
-
-    return *static_cast<boost::timer::cpu_timer*>(ptr);
-}
-
-/*
- * Method: ElapsedTimer.pause
- * ------------------------------------------------------------------
- *
- * Pause the timer, without resetting the current elapsed time stored.
- */
-duk_ret_t pause(duk_context *ctx)
-{
-    self(ctx).stop();
-
-    return 0;
-}
-
-/*
- * Method: ElapsedTimer.reset
- * ------------------------------------------------------------------
- *
- * Reset the elapsed time to 0, the status is not modified.
- */
-duk_ret_t reset(duk_context *ctx)
-{
-    self(ctx).start();
-
-    return 0;
-}
-
-/*
- * Method: ElapsedTimer.restart
- * ------------------------------------------------------------------
- *
- * Restart the timer without resetting the current elapsed time.
- */
-duk_ret_t restart(duk_context *ctx)
-{
-    self(ctx).resume();
-
-    return 0;
-}
-
-/*
- * Method: ElapsedTimer.elapsed
- * ------------------------------------------------------------------
- *
- * Get the number of elapsed milliseconds.
- *
- * Returns:
- *   The time elapsed.
- */
-duk_ret_t elapsed(duk_context *ctx)
-{
-    duk_push_uint(ctx, self(ctx).elapsed().wall / 1000000LL);
-
-    return 1;
-}
-
-/*
- * Function: Malikania.ElapsedTimer() [constructor]
- * ------------------------------------------------------------------
- *
- * Construct a new ElapsedTimer object.
- */
-duk_ret_t constructor(duk_context *ctx)
-{
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, new boost::timer::cpu_timer);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-
-    return 0;
-}
-
-/*
- * Function: Malikania.ElapsedTimer() [destructor]
- * ------------------------------------------------------------------
- *
- * Destroy the timer.
- */
-duk_ret_t destructor(duk_context *ctx)
-{
-    duk_get_prop_string(ctx, 0, Signature.c_str());
-    delete static_cast<boost::timer::cpu_timer*>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-    duk_del_prop_string(ctx, 0, Signature.c_str());
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "elapsed",    elapsed,    0 },
-    { "pause",      pause,      0 },
-    { "reset",      reset,      0 },
-    { "restart",    restart,    0 },
-    { nullptr,      nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_load_elapsedtimer(duk_context *ctx) noexcept
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 0);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_push_c_function(ctx, destructor, 1);
-    duk_set_finalizer(ctx, -2);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "ElapsedTimer");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libcommon-js/malikania/js-elapsed-timer.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * js-elapsed-timer.hpp --
- *
- * Copyright (c) 2013-2016 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 MALIKANIA_JS_ELAPSED_TIMER_HPP
-#define MALIKANIA_JS_ELAPSED_TIMER_HPP
-
-#include "duktape.hpp"
-
-namespace malikania {
-
-void dukx_load_elapsedtimer(duk_context *ctx) noexcept;
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_ELAPSED_TIMER_HPP
-
--- a/libcommon-js/malikania/js-resources-loader.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * js-resources-loader.cpp --resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 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 "js-resources-loader.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Variable("\xff""\xff""malikania-resources-loader");
-
-} // !namespace
-
-void dukx_put_loader(duk_context *ctx, ResourcesLoader *loader)
-{
-    assert(ctx);
-    assert(loader);
-
-    StackAssert sa(ctx);
-
-    duk_push_pointer(ctx, loader);
-    duk_put_global_string(ctx, Variable.c_str());
-}
-
-ResourcesLoader *duk_require_loader(duk_context *ctx)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, Variable.c_str());
-    auto ptr = static_cast<ResourcesLoader *>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-
-    return static_cast<ResourcesLoader *>(ptr);
-}
-
-} // !malikania
--- a/libcommon-js/malikania/js-resources-loader.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * js-resources-loader.hpp --resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 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 MALIKANIA_JS_RESOURCES_LOADER_H
-#define MALIKANIA_JS_RESOURCES_LOADER_H
-
-#include "duktape.hpp"
-#include "resources-loader.hpp"
-
-namespace malikania {
-
-void dukx_put_loader(duk_context *ctx, ResourcesLoader *);
-
-ResourcesLoader *dukx_get_loader(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_RESOURCES_LOADER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon-js/malikania/js_elapsed_timer.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,160 @@
+/*
+ * js_elapsed_timer.cpp -- ElapsedTimer (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 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 <boost/timer/timer.hpp>
+
+#include <cassert>
+#include <string>
+
+#include "duktape.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string signature("\xff" "\xff" "malikania-elapsed-timer-ptr");
+
+boost::timer::cpu_timer& self(duk_context* ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr) {
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an ElapsedTimer object");
+    }
+
+    return *static_cast<boost::timer::cpu_timer*>(ptr);
+}
+
+/*
+ * Method: ElapsedTimer.pause
+ * ------------------------------------------------------------------
+ *
+ * Pause the timer, without resetting the current elapsed time stored.
+ */
+duk_ret_t pause(duk_context* ctx)
+{
+    self(ctx).stop();
+
+    return 0;
+}
+
+/*
+ * Method: ElapsedTimer.reset
+ * ------------------------------------------------------------------
+ *
+ * Reset the elapsed time to 0, the status is not modified.
+ */
+duk_ret_t reset(duk_context* ctx)
+{
+    self(ctx).start();
+
+    return 0;
+}
+
+/*
+ * Method: ElapsedTimer.restart
+ * ------------------------------------------------------------------
+ *
+ * Restart the timer without resetting the current elapsed time.
+ */
+duk_ret_t restart(duk_context* ctx)
+{
+    self(ctx).resume();
+
+    return 0;
+}
+
+/*
+ * Method: ElapsedTimer.elapsed
+ * ------------------------------------------------------------------
+ *
+ * Get the number of elapsed milliseconds.
+ *
+ * Returns:
+ *   The time elapsed.
+ */
+duk_ret_t elapsed(duk_context* ctx)
+{
+    duk_push_uint(ctx, self(ctx).elapsed().wall / 1000000LL);
+
+    return 1;
+}
+
+/*
+ * Function: Malikania.ElapsedTimer() [constructor]
+ * ------------------------------------------------------------------
+ *
+ * Construct a new ElapsedTimer object.
+ */
+duk_ret_t constructor(duk_context* ctx)
+{
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, new boost::timer::cpu_timer);
+    duk_put_prop_string(ctx, -2, signature.c_str());
+    duk_pop(ctx);
+
+    return 0;
+}
+
+/*
+ * Function: Malikania.ElapsedTimer() [destructor]
+ * ------------------------------------------------------------------
+ *
+ * Destroy the timer.
+ */
+duk_ret_t destructor(duk_context* ctx)
+{
+    duk_get_prop_string(ctx, 0, signature.c_str());
+    delete static_cast<boost::timer::cpu_timer*>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+    duk_del_prop_string(ctx, 0, signature.c_str());
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "elapsed",    elapsed,    0 },
+    { "pause",      pause,      0 },
+    { "reset",      reset,      0 },
+    { "restart",    restart,    0 },
+    { nullptr,      nullptr,    0 }
+};
+
+} // !namespace
+
+void dukx_load_elapsedtimer(duk_context* ctx) noexcept
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 0);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_push_c_function(ctx, destructor, 1);
+    duk_set_finalizer(ctx, -2);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "ElapsedTimer");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon-js/malikania/js_elapsed_timer.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,30 @@
+/*
+ * js_elapsed_timer.hpp -- ElapsedTimer (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 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 MALIKANIA_JS_ELAPSED_TIMER_HPP
+#define MALIKANIA_JS_ELAPSED_TIMER_HPP
+
+#include "duktape.hpp"
+
+namespace malikania {
+
+void dukx_load_elapsedtimer(duk_context* ctx) noexcept;
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_ELAPSED_TIMER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon-js/malikania/js_resources_loader.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,54 @@
+/*
+ * js_resources_loader.cpp -- resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 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 "js_resources_loader.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string variable("\xff""\xff""malikania-resources-loader");
+
+} // !namespace
+
+void dukx_put_loader(duk_context *ctx, resources_loader& loader)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_push_pointer(ctx, &loader);
+    duk_put_global_string(ctx, variable.c_str());
+}
+
+resources_loader& duk_require_loader(duk_context* ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, variable.c_str());
+    auto ptr = static_cast<resources_loader*>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+
+    return *static_cast<resources_loader*>(ptr);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon-js/malikania/js_resources_loader.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,33 @@
+/*
+ * js_resources_loader.hpp -- resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 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 MALIKANIA_JS_RESOURCES_LOADER_H
+#define MALIKANIA_JS_RESOURCES_LOADER_H
+
+#include "duktape.hpp"
+#include "resources_loader.hpp"
+
+namespace malikania {
+
+void dukx_put_loader(duk_context* ctx, resources_loader&);
+
+resources_loader& dukx_get_loader(duk_context* ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_RESOURCES_LOADER_H
--- a/libcommon/CMakeLists.txt	Sun Nov 27 20:50:38 2016 +0100
+++ b/libcommon/CMakeLists.txt	Tue Nov 29 21:21:36 2016 +0100
@@ -18,28 +18,26 @@
 
 set(
     HEADERS
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/application.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/duktape.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/game.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/id.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-loader.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-locator.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources_loader.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources_locator.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/util.hpp
 )
 
 set(
     SOURCES
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/application.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-loader.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-locator.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources_loader.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources_locator.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/util.cpp
 )
 
 if (WITH_BACKEND_SDL)
     find_package(SDL2 REQUIRED)
 
-    list(APPEND HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/malikania/backend/sdl/common-sdl.hpp)
-    list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/malikania/backend/sdl/common-sdl.cpp)
+    list(APPEND HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/malikania/backend/sdl/sdl_util.hpp)
+    list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/malikania/backend/sdl/sdl_util.cpp)
     list(APPEND INCLUDES ${SDL2_INCLUDE_DIRS})
     list(APPEND LIBRARIES ${SDL2_LIBRARIES})
 endif ()
--- a/libcommon/malikania/application.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * application.cpp -- main application class
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "application.hpp"
-
-namespace malikania {
-
-Application::Application(int, char **)
-{
-    // TODO: find the executable path
-}
-
-} // !malikania
--- a/libcommon/malikania/application.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * application.hpp -- main application class
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_APPLICATION_HPP
-#define MALIKANIA_APPLICATION_HPP
-
-/**
- * \file application.hpp
- * \brief Main class for the client or server
- */
-
-namespace malikania {
-
-/**
- * \class Application
- * \brief Main class for argument parsing and executable path retrievement
- */
-class Application {
-public:
-    /**
-     * Construct the application.
-     *
-     * \param argc the argument count
-     * \param argv the arguments
-     */
-    Application(int argc, char **argv);
-
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~Application() = default;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_APPLICATION_HPP
--- a/libcommon/malikania/backend/sdl/common-sdl.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * CommonSdl.cpp -- common SDL2 related code
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 <cstdint>
-#include <cstring>
-#include <new>
-
-#include "common-sdl.hpp"
-
-namespace malikania {
-
-namespace {
-
-/*
- * RWFromBinary implementation
- * ------------------------------------------------------------------
- *
- * A little bit inspired by official SDL_RWFromMem implementation, largely modified to match our conventions and the
- * C++ code.
- */
-
-class Buffer {
-public:
-    std::string m_data;
-    std::uint64_t m_position;
-    std::uint64_t m_length;
-
-    inline Buffer(std::string data) noexcept
-        : m_data(std::move(data))
-        , m_position(0U)
-        , m_length(m_data.length())
-    {
-    }
-};
-
-Sint64 size(SDL_RWops *ops) noexcept
-{
-    return reinterpret_cast<Buffer *>(ops->hidden.unknown.data1)->m_length;
-}
-
-Sint64 seek(SDL_RWops *ops, Sint64 offset, int whence) noexcept
-{
-    Buffer *data = reinterpret_cast<Buffer *>(ops->hidden.unknown.data1);
-    Sint64 position = data->m_position;
-
-    switch (whence) {
-    case RW_SEEK_SET:
-        position = offset;
-        break;
-    case RW_SEEK_CUR:
-        position = data->m_position + offset;
-        break;
-    case RW_SEEK_END:
-        position = data->m_length + offset;
-        break;
-    default:
-        break;
-    }
-
-    if (position < 0)
-        position = 0;
-    else if ((std::uint64_t)position > data->m_length)
-        position = data->m_length;
-
-    return (data->m_position = position);
-}
-
-size_t read(SDL_RWops *ops, void *dst, std::size_t size, std::size_t number) noexcept
-{
-    Buffer *data = reinterpret_cast<Buffer *>(ops->hidden.unknown.data1);
-    size_t total = number * size;
-    size_t avail = data->m_length - data->m_position;
-
-    if (number <= 0 || size <= 0 || ((total / number) != static_cast<std::size_t>(size)))
-        return 0;
-    if (total > avail)
-        total = avail;
-
-    SDL_memcpy(dst, &data->m_data[data->m_position], total);
-
-    data->m_position += total;
-
-    return (total / size);
-}
-
-size_t write(SDL_RWops *, const void *, size_t, size_t) noexcept
-{
-    SDL_SetError("write not supported");
-
-    return -1;
-}
-
-int close(SDL_RWops *ops) noexcept
-{
-    if (ops != nullptr) {
-        delete reinterpret_cast<Buffer *>(ops->hidden.unknown.data1);
-        SDL_FreeRW(ops);
-    }
-
-    return 0;
-}
-
-} // !namespace
-
-SDL_RWops *SDLx_RWFromBinary(std::string data) noexcept
-{
-    SDL_RWops *ops = SDL_AllocRW();
-
-    if (ops == nullptr)
-        return nullptr;
-
-    ops->hidden.unknown.data1 = new (std::nothrow) Buffer(std::move(data));
-
-    if (ops->hidden.unknown.data1 == nullptr) {
-        SDL_SetError("%s", std::strerror(errno));
-        SDL_FreeRW(ops);
-        return nullptr;
-    }
-
-    ops->type = SDL_RWOPS_UNKNOWN;
-    ops->seek = seek;
-    ops->size = size;
-    ops->read = read;
-    ops->write = write;
-    ops->close = close;
-
-    return ops;
-}
-
-} // !malikania
--- a/libcommon/malikania/backend/sdl/common-sdl.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * CommonSdl.hpp -- common SDL2 related code
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_COMMON_SDL_HPP
-#define MALIKANIA_COMMON_SDL_HPP
-
-#include <SDL.h>
-
-#include <string>
-
-namespace malikania {
-
-/**
- * Create a SDL_RWops that owns the binary data.
- *
- * This is a safe alternative to SDL_RWFromMem because it owns the memory pointed by data until it is closed. The
- * data is moved so there are no copies.
- *
- * The stream has read-only support and can not write.
- *
- * Seeking past-the-end or past-the-begin readjust the position to the end or begin respectively.
- *
- * \param data the data
- * \return the object or nullptr on errors
- */
-SDL_RWops *SDLx_RWFromBinary(std::string data) noexcept;
-
-} // !malikania
-
-#endif // !MALIKANIA_COMMON_SDL_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/backend/sdl/sdl_util.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,148 @@
+/*
+ * sdl_util.cpp -- common SDL2 related code
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 <cstdint>
+#include <cstring>
+#include <new>
+
+#include "sdl_util.hpp"
+
+namespace malikania {
+
+namespace {
+
+/*
+ * RWFromBinary implementation
+ * ------------------------------------------------------------------
+ *
+ * A little bit inspired by official SDL_RWFromMem implementation, largely
+ * modified to match our conventions and the C++ code.
+ */
+
+class buffer {
+public:
+    std::string m_data;
+    std::uint64_t m_position;
+    std::uint64_t m_length;
+
+    inline buffer(std::string data) noexcept
+        : m_data(std::move(data))
+        , m_position(0ULL)
+        , m_length(m_data.length())
+    {
+    }
+};
+
+Sint64 size(SDL_RWops* ops) noexcept
+{
+    return reinterpret_cast<buffer*>(ops->hidden.unknown.data1)->m_length;
+}
+
+Sint64 seek(SDL_RWops* ops, Sint64 offset, int whence) noexcept
+{
+    buffer *data = reinterpret_cast<buffer*>(ops->hidden.unknown.data1);
+    Sint64 position = data->m_position;
+
+    switch (whence) {
+    case RW_SEEK_SET:
+        position = offset;
+        break;
+    case RW_SEEK_CUR:
+        position = data->m_position + offset;
+        break;
+    case RW_SEEK_END:
+        position = data->m_length + offset;
+        break;
+    default:
+        break;
+    }
+
+    if (position < 0LL) {
+        position = 0LL;
+    } else if (static_cast<std::uint64_t>(position) > data->m_length) {
+        position = data->m_length;
+    }
+
+    return (data->m_position = position);
+}
+
+std::size_t read(SDL_RWops* ops, void* dst, std::size_t size, std::size_t number) noexcept
+{
+    buffer* data = reinterpret_cast<buffer*>(ops->hidden.unknown.data1);
+    std::size_t total = number * size;
+    std::size_t avail = data->m_length - data->m_position;
+
+    if (number <= 0U || size <= 0U || ((total / number) != static_cast<std::size_t>(size))) {
+        return 0;
+    }
+    if (total > avail) {
+        total = avail;
+    }
+
+    SDL_memcpy(dst, &data->m_data[data->m_position], total);
+    data->m_position += total;
+
+    return total / size;
+}
+
+std::size_t write(SDL_RWops*, const void*, std::size_t, std::size_t) noexcept
+{
+    SDL_SetError("write not supported");
+    return -1;
+}
+
+int close(SDL_RWops* ops) noexcept
+{
+    if (ops != nullptr) {
+        delete reinterpret_cast<buffer*>(ops->hidden.unknown.data1);
+        SDL_FreeRW(ops);
+    }
+
+    return 0;
+}
+
+} // !namespace
+
+SDL_RWops* SDLx_RWFromBinary(std::string data) noexcept
+{
+    SDL_RWops* ops = SDL_AllocRW();
+
+    if (ops == nullptr) {
+        return nullptr;
+    }
+
+    ops->hidden.unknown.data1 = new (std::nothrow) buffer(std::move(data));
+
+    if (ops->hidden.unknown.data1 == nullptr) {
+        SDL_SetError("%s", std::strerror(errno));
+        SDL_FreeRW(ops);
+        return nullptr;
+    }
+
+    ops->type = SDL_RWOPS_UNKNOWN;
+    ops->seek = seek;
+    ops->size = size;
+    ops->read = read;
+    ops->write = write;
+    ops->close = close;
+
+    return ops;
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/backend/sdl/sdl_util.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,51 @@
+/*
+ * sdl_util.hpp -- common SDL2 related code
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_COMMON_SDL_UTIL_HPP
+#define MALIKANIA_COMMON_SDL_UTIL_HPP
+
+/**
+ * \file sdl_util.hpp
+ * \brief Utilities for SDL backend.
+ */
+
+#include <SDL.h>
+
+#include <string>
+
+namespace malikania {
+
+/**
+ * Create a SDL_RWops that owns the binary data.
+ *
+ * This is a safe alternative to SDL_RWFromMem because it owns the memory
+ * pointed by data until it is closed. The data is moved so there are no copies.
+ *
+ * The stream has read-only support and can not write.
+ *
+ * Seeking past-the-end or past-the-begin readjust the position to the end or
+ * begin respectively.
+ *
+ * \param data the data
+ * \return the object or nullptr on errors
+ */
+SDL_RWops* SDLx_RWFromBinary(std::string data) noexcept;
+
+} // !malikania
+
+#endif // !MALIKANIA_COMMON_SDL_UTIL_HPP
--- a/libcommon/malikania/game.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libcommon/malikania/game.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -19,6 +19,11 @@
 #ifndef MALIKANIA_GAME_HPP
 #define MALIKANIA_GAME_HPP
 
+/**
+ * \file game.hpp
+ * \brief Game description.
+ */
+
 #include <cassert>
 #include <string>
 #include <vector>
@@ -26,91 +31,15 @@
 namespace malikania {
 
 /**
- * \class Game
- * \brief Basic game class.
+ * \brief Basic game description.
  */
-class Game {
-private:
-    std::string m_name;
-    std::string m_version;
-    std::string m_requires;
-    std::string m_license;
-    std::string m_author;
-
+class game {
 public:
-    /**
-     * Construct a game.
-     *
-     * \pre name must not be empty
-     * \pre version must not be empty
-     * \pre requires must not be empty
-     * \param name the game name
-     * \param version the version
-     * \param requires the engine version required
-     * \param license the license (Optional)
-     * \param authors the authors (Optional)
-     */
-    inline Game(std::string name, std::string version, std::string requires, std::string license, std::string author)
-        : m_name(std::move(name))
-        , m_version(std::move(version))
-        , m_requires(std::move(requires))
-        , m_license(std::move(license))
-        , m_author(std::move(author))
-    {
-        assert(!m_name.empty());
-        assert(!m_version.empty());
-        assert(!m_requires.empty());
-    }
-
-    /**
-     * Get the game name.
-     *
-     * \return the name
-     */
-    inline const std::string &name() const noexcept
-    {
-        return m_name;
-    }
-
-    /**
-     * Get the author.
-     *
-     * \return the author
-     */
-    inline const std::string &author() const noexcept
-    {
-        return m_author;
-    }
-
-    /**
-     * Get the license.
-     *
-     * \return the license
-     */
-    inline const std::string &license() const noexcept
-    {
-        return m_license;
-    }
-
-    /**
-     * Get the license.
-     *
-     * \return the license
-     */
-    inline const std::string &version() const noexcept
-    {
-        return m_version;
-    }
-
-    /**
-     * Get the engine version required to run the game.
-     *
-     * \return the version required
-     */
-    inline const std::string &requires() const noexcept
-    {
-        return m_requires;
-    }
+    std::string name;
+    std::string version;
+    std::string requires;
+    std::string license;
+    std::string author;
 };
 
 } // !malikania
--- a/libcommon/malikania/id.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libcommon/malikania/id.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -25,26 +25,32 @@
  */
 
 #include <limits>
+#include <memory>
 #include <queue>
 #include <stdexcept>
 
 namespace malikania {
 
+template <typename T>
+class id;
+
 /**
- * \class IdGen
  * \brief Integer id generator
  *
- * This class helps generating and release unique integer id that can be used anywhere. The ids are generated in a
- * sequence and when an id is released it is reused instead of incrementing the next number.
+ * This class helps generating and release unique integer id that can be used
+ * anywhere. The ids are generated in a sequence and when an id is released it
+ * is reused instead of incrementing the next number.
  *
  * The template can use any integral integer but unsigned are preferred.
  *
  * The maximum number of id is equal to std::numeric_limits<T>::max - 1.
  */
 template <typename T>
-class IdGen {
+class id_generator {
 private:
-    static_assert(std::numeric_limits<T>::is_integer, "IdGen requires integral types");
+    static_assert(std::numeric_limits<T>::is_integer, "id_generator requires integral types");
+
+    friend class id<T>;
 
     T m_current{0};
     std::priority_queue<T> m_reusable;
@@ -56,98 +62,46 @@
      * \return the id
      * \throw std::out_of_range if no number is available
      */
-    T next();
-
-    /**
-     * Release the player id.
-     *
-     * \param id the id not needed anymore
-     */
-    inline void release(T id) noexcept
-    {
-        m_reusable.push(id);
-    }
-
-    /**
-     * Reset the ids to 0 and remove the queue.
-     */
-    void reset() noexcept;
+    std::unique_ptr<id<T>> next();
 };
 
-template <typename T>
-T IdGen<T>::next()
-{
-    T id;
-
-    if (m_reusable.size() > 0) {
-        id = m_reusable.top();
-        m_reusable.pop();
-    } else {
-        if (m_current == std::numeric_limits<T>::max())
-            throw std::out_of_range("no id available");
-
-        id = m_current++;
-    }
-
-    return id;
-}
-
-template <typename T>
-void IdGen<T>::reset() noexcept
-{
-    m_current = 0;
-
-    while (!m_reusable.empty())
-        m_reusable.pop();
-}
-
 /**
- * \class Id
  * \brief RAII based id owner
  *
- * This class is similar to a std::lock_guard or std::unique_lock in a way that the id is acquired
- * when the object is instanciated and released when destroyed.
+ * This class is similar to a std::lock_guard or std::unique_lock in a way that
+ * the id is acquired when the object is instanciated and released when
+ * destroyed.
  *
- * This class does not take ownership of the IdGen so it must still exists when the Id is destroyed.
+ * This class does not take ownership of the id_generator so it must still
+ * exists when the id is destroyed.
  */
 template <typename T>
-class Id {
+class id {
 private:
-    IdGen<T> &m_gen;
+    friend class id_generator<T>;
+
+    id_generator<T>& m_gen;
     T m_id;
 
-public:
     /**
-     * Construct a new Id and take the next number.
+     * Construct a new id and take the next number.
      *
      * \param gen the generator
      * \throw any exception if IdGen fails to give an id.
      */
-    inline Id(IdGen<T> &gen)
-        : m_gen(gen)
-        , m_id(m_gen.next())
-    {
-    }
-
-    /**
-     * Construct an Id with an already taken number.
-     *
-     * \param gen the generator
-     * \param id the id
-     * \warning be sure that the id was taken from this generator
-     */
-    Id(IdGen<T> &gen, T id)
+    inline id(id_generator<T>& gen, T id) noexcept
         : m_gen(gen)
         , m_id(id)
     {
     }
 
+public:
     /**
      * Destroy the id and release the number.
      */
-    ~Id() noexcept
+    ~id() noexcept
     {
-        m_gen.release(m_id);
+        m_gen.m_reusable.push(m_id);
     }
 
     /**
@@ -159,15 +113,46 @@
     {
         return m_id;
     }
+};
 
-    /**
-     * Convert the id to the number.
-     */
-    inline operator T() const noexcept
-    {
-        return m_id;
+template <typename T>
+std::unique_ptr<id<T>> id_generator<T>::next()
+{
+    T i;
+
+    if (m_reusable.size() > 0) {
+        i = m_reusable.top();
+        m_reusable.pop();
+    } else {
+        if (m_current == std::numeric_limits<T>::max()) {
+            throw std::out_of_range("no id available");
+        }
+
+        i = m_current++;
     }
-};
+
+    return std::unique_ptr<id<T>>(new id<T>(*this, i));
+}
+
+/**
+ * Typedef for std::uint8_t.
+ */
+using id8 = id<std::uint8_t>;
+
+/**
+ * Typedef for std::uint16_t.
+ */
+using id16 = id<std::uint16_t>;
+
+/**
+ * Typedef for std::uint32_t.
+ */
+using id32 = id<std::uint32_t>;
+
+/**
+ * Typedef for std::uint64_t.
+ */
+using id64 = id<std::uint64_t>;
 
 } // !malikania
 
--- a/libcommon/malikania/resources-loader.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * resources-loader.cpp -- load shared resources files
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "game.hpp"
-#include "resources-loader.hpp"
-#include "resources-locator.hpp"
-
-using json = nlohmann::json;
-
-namespace malikania {
-
-void ResourcesLoader::requires(const std::string &id,
-                               const json &object,
-                               const std::unordered_map<std::string, json::value_t> props) const
-{
-    assert(object.is_object());
-
-    for (const auto &pair : props) {
-        auto it = object.find(pair.first);
-
-        if (it == object.end() || it->type() != pair.second) {
-            std::string msg = id + ": missing '" + pair.first + "' property (";
-
-            switch (pair.second) {
-            case json::value_t::array:
-                msg += "array";
-                break;
-            case json::value_t::boolean:
-                msg += "boolean";
-                break;
-            case json::value_t::number_float:
-            case json::value_t::number_integer:
-            case json::value_t::number_unsigned:
-                msg += "number";
-                break;
-            case json::value_t::object:
-                msg += "object";
-                break;
-            case json::value_t::string:
-                msg += "string";
-                break;
-            default:
-                break;
-            }
-
-            msg += " expected)";
-
-            throw std::runtime_error(std::move(msg));
-        }
-    }
-}
-
-std::string ResourcesLoader::requireString(const std::string &id,
-                                           const nlohmann::json &object,
-                                           const std::string &property) const
-{
-    assert(object.is_object());
-
-    auto it = object.find(property);
-
-    if (it == object.end() || !it->is_string())
-        throw std::runtime_error(id + ": missing '" + property + "' property (string expected)");
-
-    return *it;
-}
-
-ResourcesLoader::ResourcesLoader(ResourcesLocator &locator)
-    : m_locator(locator)
-{
-}
-
-Game ResourcesLoader::loadGame() const
-{
-    auto value = json::parse(m_locator.read("game.json"));
-
-    if (!value.is_object())
-        throw std::runtime_error("game.json: not a JSON object");
-
-    requires("game.json", value, {
-        { "name",       json::value_t::string },
-        { "version",    json::value_t::string },
-        { "requires",   json::value_t::string }
-    });
-
-    return Game(value["name"],
-                value["version"],
-                value["requires"],
-                value.count("license") > 0 ? value["license"] : "",
-                value.count("author") > 0 ? value["author"] : "");
-}
-
-} // !malikania
--- a/libcommon/malikania/resources-loader.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * resources-loader.hpp -- load shared resources files
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_RESOURCES_LOADER_HPP
-#define MALIKANIA_RESOURCES_LOADER_HPP
-
-#include <string>
-#include <unordered_map>
-
-#include <json.hpp>
-
-#include "resources-locator.hpp"
-
-namespace malikania {
-
-class Game;
-
-/**
- * \class ResourcesLoader
- * \brief Open resources files using a ResourcesLocator.
- *
- * This class is used to load resources files that are common to the server and the client.
- *
- * \see ResourcesLoaderClient
- * \see ResourcesLoaderServer
- */
-class ResourcesLoader {
-private:
-    ResourcesLocator &m_locator;
-
-protected:
-    /**
-     * Check that an object has the specified properties of the given type.
-     *
-     * Throws an error when any of the property is missing or not the correct type.
-     *
-     * You can use this function when you have lot of properties to extract, otherwise, you can use one of the
-     * require* or get* functions to avoid performances overhead.
-     *
-     * \pre object.isObject()
-     * \param id the resource id
-     * \param object the object
-     * \param props the properties
-     * \throw std::runtime_error when a property is missing / invalid
-     */
-    void requires(const std::string &id,
-                  const nlohmann::json &object,
-                  const std::unordered_map<std::string, nlohmann::json::value_t> props) const;
-
-    /**
-     * Require a string.
-     *
-     * \pre object.isObject()
-     * \param id the resource id
-     * \param object the object
-     * \param property the property
-     * \return the string
-     * \throw std::runtime_error if the property is not a string or missing
-     */
-    std::string requireString(const std::string &id, const nlohmann::json &object, const std::string &property) const;
-
-public:
-    /**
-     * Construct the ResourcesLoader.
-     *
-     * \param locator the locator
-     */
-    ResourcesLoader(ResourcesLocator &locator);
-
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~ResourcesLoader() = default;
-
-    /**
-     * Get the underlying locator.
-     *
-     * \return the locator
-     */
-    inline ResourcesLocator &locator() noexcept
-    {
-        return m_locator;
-    }
-
-    /**
-     * Load a game.
-     *
-     * \return the game
-     * \throw std::runtime_error on errors
-     */
-    virtual Game loadGame() const;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_RESOURCES_LOADER_HPP
--- a/libcommon/malikania/resources-locator.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * resources-locator.cpp -- file and stream loader
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 <fstream>
-#include <iterator>
-#include <stdexcept>
-
-#include "resources-locator.hpp"
-
-namespace malikania {
-
-ResourcesLocatorDirectory::ResourcesLocatorDirectory(std::string path) noexcept
-    : m_path(std::move(path))
-{
-}
-
-std::string ResourcesLocatorDirectory::read(const std::string &id)
-{
-    std::ifstream in(m_path + "/" + id, std::ifstream::in | std::ifstream::binary);
-
-    if (!in)
-        throw std::runtime_error(std::strerror(errno));
-
-    return std::string(std::istreambuf_iterator<char>(in.rdbuf()), std::istreambuf_iterator<char>());
-}
-
-std::unique_ptr<std::istream> ResourcesLocatorDirectory::open(const std::string &id)
-{
-    std::unique_ptr<std::istream> ptr = std::make_unique<std::ifstream>(m_path + "/" + id);
-
-    if (!(*ptr))
-        throw std::runtime_error(std::strerror(errno));
-
-    return ptr;
-}
-
-} // !malikania
--- a/libcommon/malikania/resources-locator.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * resources-locator.hpp -- file and stream loader
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 MALIKANIA_RESOURCES_LOCATOR_HPP
-#define MALIKANIA_RESOURCES_LOCATOR_HPP
-
-#include <string>
-#include <memory>
-#include <istream>
-
-namespace malikania {
-
-/**
- * \class ResourcesLocator
- * \brief Load files from directories and zip.
- */
-class ResourcesLocator {
-public:
-    /**
-     * Read a whole resource as a string.
-     *
-     * \param id the resource id
-     * \return the string
-     * \throw std::runtime_error on any errors
-     */
-    virtual std::string read(const std::string &id) = 0;
-
-    /**
-     * Open a resource as a stream.
-     *
-     * \param id the resource id
-     * \return the stream
-     * \throw std::runtime_error on any errors
-     */
-    virtual std::unique_ptr<std::istream> open(const std::string &id) = 0;
-};
-
-/**
- * \class ResourcesLocatorDirectory
- * \brief Load a game from a directory.
- */
-class ResourcesLocatorDirectory : public ResourcesLocator {
-private:
-    std::string m_path;
-
-public:
-    /**
-     * Load the game from the directory.
-     *
-     * \param path the base directory
-     */
-    ResourcesLocatorDirectory(std::string path) noexcept;
-
-    /**
-     * @copydoc ResourcesLocator::read
-     */
-    std::string read(const std::string &id) override;
-
-    /**
-     * @copydoc ResourcesLocator::open
-     */
-    std::unique_ptr<std::istream> open(const std::string &id) override;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_RESOURCES_LOCATOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/resources_loader.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,108 @@
+/*
+ * resources_loader.cpp -- load shared resources files
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 <boost/format.hpp>
+
+#include <cassert>
+
+#include "game.hpp"
+#include "resources_loader.hpp"
+#include "resources_locator.hpp"
+
+namespace malikania {
+
+void resources_loader::requires(const std::string& id,
+                                const nlohmann::json& object,
+                                const std::unordered_map<std::string, nlohmann::json::value_t>& props) const
+{
+    assert(object.is_object());
+
+    for (const auto& pair : props) {
+        auto it = object.find(pair.first);
+
+        if (it == object.end() || it->type() != pair.second) {
+            std::string type;
+
+            switch (pair.second) {
+            case nlohmann::json::value_t::array:
+                type = "array";
+                break;
+            case nlohmann::json::value_t::boolean:
+                type = "boolean";
+                break;
+            case nlohmann::json::value_t::number_unsigned:
+                type = "number";
+                break;
+            case nlohmann::json::value_t::object:
+                type = "object";
+                break;
+            case nlohmann::json::value_t::string:
+                type = "string";
+                break;
+            default:
+                break;
+            }
+
+            throw std::runtime_error(boost::str(
+                boost::format("%s: missing '%s' property (%s expected)") % id % pair.first % type));
+        }
+    }
+}
+
+std::string resources_loader::require_string(const std::string& id,
+                                            const nlohmann::json& object,
+                                            const std::string& property) const
+{
+    assert(object.is_object());
+
+    auto it = object.find(property);
+
+    if (it == object.end() || !it->is_string()) {
+        throw std::runtime_error(id + ": missing '" + property + "' property (string expected)");
+    }
+
+    return *it;
+}
+
+resources_loader::resources_loader(resources_locator& locator)
+    : m_locator(locator)
+{
+}
+
+game resources_loader::load_game() const
+{
+    auto value = nlohmann::json::parse(m_locator.read("game.json"));
+
+    if (!value.is_object()) {
+        throw std::runtime_error("game.json: not a JSON object");
+    }
+
+    requires("game.json", value, {
+        { "name",       nlohmann::json::value_t::string },
+        { "version",    nlohmann::json::value_t::string },
+        { "requires",   nlohmann::json::value_t::string }
+    });
+
+    return game{value["name"],
+                value["version"],
+                value["requires"],
+                value.count("license") > 0 ? value["license"] : "",
+                value.count("author") > 0 ? value["author"] : ""};
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/resources_loader.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,114 @@
+/*
+ * resources_loader.hpp -- load shared resources files
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_RESOURCES_LOADER_HPP
+#define MALIKANIA_RESOURCES_LOADER_HPP
+
+#include <string>
+#include <unordered_map>
+
+#include <json.hpp>
+
+#include "resources_locator.hpp"
+
+namespace malikania {
+
+class game;
+
+/**
+ * \brief Open resources files using a resources_locator.
+ *
+ * This class is used to load resources files that are common to the server and
+ * the client.
+ *
+ * \see client_resources_loader
+ */
+class resources_loader {
+private:
+    resources_locator& m_locator;
+
+protected:
+    /**
+     * Check that an object has the specified properties of the given type.
+     *
+     * Throws an error when any of the property is missing or not the correct
+     * type.
+     *
+     * You can use this function when you have lot of properties to extract,
+     * otherwise, you can use one of the require* or get* functions to avoid
+     * performances overhead.
+     *
+     * \pre object.is_object()
+     * \param id the resource id
+     * \param object the object
+     * \param props the properties
+     * \throw std::runtime_error when a property is missing / invalid
+     */
+    void requires(const std::string& id,
+                  const nlohmann::json& object,
+                  const std::unordered_map<std::string, nlohmann::json::value_t>& props) const;
+
+    /**
+     * Require a string.
+     *
+     * \pre object.isObject()
+     * \param id the resource id
+     * \param object the object
+     * \param property the property
+     * \return the string
+     * \throw std::runtime_error if the property is not a string or missing
+     */
+    std::string require_string(const std::string& id,
+                               const nlohmann::json& object,
+                               const std::string& property) const;
+
+public:
+    /**
+     * Construct the resources loader.
+     *
+     * \param locator the locator
+     */
+    resources_loader(resources_locator& locator);
+
+    /**
+     * Virtual destructor defaulted.
+     */
+    virtual ~resources_loader() noexcept = default;
+
+    /**
+     * Get the underlying locator.
+     *
+     * \return the locator
+     */
+    inline resources_locator& locator() noexcept
+    {
+        return m_locator;
+    }
+
+    /**
+     * Load a game.
+     *
+     * \return the game
+     * \throw std::runtime_error on errors
+     */
+    virtual game load_game() const;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_RESOURCES_LOADER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/resources_locator.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,56 @@
+/*
+ * resources_locator.cpp -- file and stream loader
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 <fstream>
+#include <iterator>
+#include <stdexcept>
+
+#include "resources_locator.hpp"
+
+namespace malikania {
+
+directory_resources_locator::directory_resources_locator(std::string path) noexcept
+    : m_path(std::move(path))
+{
+}
+
+std::string directory_resources_locator::read(const std::string &id)
+{
+    std::ifstream in(m_path + "/" + id, std::ifstream::in | std::ifstream::binary);
+
+    if (!in) {
+        throw std::runtime_error(std::strerror(errno));
+    }
+
+    return std::string(std::istreambuf_iterator<char>(in.rdbuf()), std::istreambuf_iterator<char>());
+}
+
+std::unique_ptr<std::istream> directory_resources_locator::open(const std::string &id)
+{
+    auto ptr = std::make_unique<std::ifstream>(m_path + "/" + id);
+
+    if (!(*ptr)) {
+        throw std::runtime_error(std::strerror(errno));
+    }
+
+    return ptr;
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/resources_locator.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,85 @@
+/*
+ * resources_locator.hpp -- file and stream loader
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 MALIKANIA_RESOURCES_LOCATOR_HPP
+#define MALIKANIA_RESOURCES_LOCATOR_HPP
+
+#include <string>
+#include <memory>
+#include <istream>
+
+namespace malikania {
+
+/**
+ * \brief Abstract assets locator.
+ */
+class resources_locator {
+public:
+    /**
+     * Default destructor.
+     */
+    virtual ~resources_locator() = default;
+
+    /**
+     * Read a whole resource as a string.
+     *
+     * \param id the resource id
+     * \return the string
+     * \throw std::runtime_error on any errors
+     */
+    virtual std::string read(const std::string& id) = 0;
+
+    /**
+     * Open a resource as a stream.
+     *
+     * \param id the resource id
+     * \return the stream
+     * \throw std::runtime_error on any errors
+     */
+    virtual std::unique_ptr<std::istream> open(const std::string& id) = 0;
+};
+
+/**
+ * \brief Load a game from a directory.
+ */
+class directory_resources_locator : public resources_locator {
+private:
+    std::string m_path;
+
+public:
+    /**
+     * Load the game from the directory.
+     *
+     * \param path the base directory
+     */
+    directory_resources_locator(std::string path) noexcept;
+
+    /**
+     * \copydoc resources_locator::read
+     */
+    std::string read(const std::string& id) override;
+
+    /**
+     * \copydoc resources_locator::open
+     */
+    std::unique_ptr<std::istream> open(const std::string& id) override;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_RESOURCES_LOCATOR_HPP
--- a/libcommon/malikania/signals.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*
- * signals.h -- synchronous observer mechanism
- *
- * Copyright (c) 2016 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 MALIKANIA_SIGNALS_HPP
-#define MALIKANIA_SIGNALS_HPP
-
-/**
- * \file signals.hpp
- * \brief Synchronous callbacks.
- */
-
-#include <algorithm>
-#include <cstdint>
-#include <functional>
-#include <stack>
-#include <unordered_map>
-#include <vector>
-
-namespace malikania {
-
-/**
- * \brief Stores and call registered functions.
- *
- * This class is intended to be use as a public field in the desired object.
- *
- * The user just have to call one of connect(), disconnect() or the call
- * operator to use this class.
- *
- * It stores the callable as std::function so type-erasure is complete.
- *
- * The user is responsible of taking care that the object is still alive
- * in case that the function takes a reference to the object.
- *
- * It is forbidden to connect, disconnect, clearing the signal from a callback,
- * instead you should postpone this operation for example, in an event loop
- * event.
- *
- * It is also forbidden to throw in user callbacks, to make such guarantee, the
- * call operator is noexcept.
- */
-template <typename... Args>
-class Signal {
-public:
-    /**
-     * \brief Opaque connection identifier.
-     * \see disconnect
-     */
-    using Index = std::intmax_t;
-
-private:
-    using Function = std::function<void (Args...)>;
-    using List = std::vector<Function>;
-    using Stack = std::stack<Index>;
-
-    List m_functions;
-    Stack m_reuseable;
-
-#if !defined(NDEBUG)
-    mutable bool m_locked{false};
-#endif
-
-    template <typename Func>
-    inline Index add(Func &&function)
-    {
-        assert(!m_locked);
-
-        std::size_t id;
-
-        if (!m_reuseable.empty()) {
-            id = m_reuseable.top();
-            m_functions[id] = std::forward<Func>(function);
-            m_reuseable.pop();
-        } else {
-            m_functions.push_back(std::forward<Func>(function));
-            id = m_functions.size() - 1;
-        }
-
-        return id;
-    }
-
-public:
-    /**
-     * Register a new function to the signal.
-     *
-     * \pre must not be called from an handler
-     * \param function the function to copy
-     * \return the index for removing
-     * \throw exceptions on bad allocation
-     */
-    inline Index connect(const Function &function)
-    {
-        return add(function);
-    }
-
-    /**
-     * Overloaded function for move semantics.
-     *
-     * \pre must not be called from an handler
-     * \param function the function to move
-     * \return the connection index
-     * \throw exceptions on bad allocation
-     */
-    inline Index connect(Function &&function)
-    {
-        return add(function);
-    }
-
-    /**
-     * Disconnect an handler.
-     *
-     * \pre must not be called from an handler
-     * \param id the id to disconnect (will be set to 0)
-     */
-    inline void disconnect(Index &id)
-    {
-        assert(!m_locked);
-
-        if (id < 0 || static_cast<std::size_t>(id) >= m_functions.size())
-            return;
-
-        m_functions[id] = nullptr;
-        m_reuseable.push(id);
-        id = -1;
-    }
-
-    /**
-     * Remove all registered functions.
-     *
-     * \pre must not be called from an handler
-     */
-    inline void clear() noexcept
-    {
-        assert(!m_locked);
-
-        m_functions.clear();
-
-        while (!m_reuseable.empty())
-            m_reuseable.pop();
-    }
-
-    /**
-     * Get the number of signals connected.
-     *
-     * \return the number
-     */
-    inline std::size_t size() const noexcept
-    {
-        return std::count_if(m_functions.begin(), m_functions.end(), [&] (auto fn) {
-            return fn != nullptr;
-        });
-    }
-
-    /**
-     * Call every functions.
-     *
-     * \pre must not be called from an handler
-     * \param args the arguments to pass to the signal
-     */
-    void operator()(Args... args) const noexcept
-    {
-        assert(!m_locked);
-
-        m_locked = true;
-
-        for (auto &f : m_functions)
-            if (f)
-                f(args...);
-
-        m_locked = false;
-    }
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_SIGNALS_HPP
--- a/libcommon/malikania/util.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libcommon/malikania/util.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -22,7 +22,7 @@
 
 namespace util {
 
-std::vector<std::string> netsplit(std::string &input)
+std::vector<std::string> netsplit(std::string& input)
 {
     std::vector<std::string> ret;
     std::string::size_type pos;
--- a/libcommon/malikania/util.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libcommon/malikania/util.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -39,7 +39,7 @@
  * \param input the buffer to split and update
  * \return the list of received message or empty if not ready
  */
-std::vector<std::string> netsplit(std::string &input);
+std::vector<std::string> netsplit(std::string& input);
 
 /**
  * Clamp the value between low and high.
--- a/libserver/CMakeLists.txt	Sun Nov 27 20:50:38 2016 +0100
+++ b/libserver/CMakeLists.txt	Tue Nov 29 21:21:36 2016 +0100
@@ -21,13 +21,13 @@
 set(
     HEADERS
     ${libmlk-server_SOURCE_DIR}/malikania/account.hpp
-    ${libmlk-server_SOURCE_DIR}/malikania/dao-account.hpp
+    ${libmlk-server_SOURCE_DIR}/malikania/account_dao.hpp
     ${libmlk-server_SOURCE_DIR}/malikania/database.hpp
 )
 
 set(
     SOURCES
-    ${libmlk-server_SOURCE_DIR}/malikania/dao-account.cpp
+    ${libmlk-server_SOURCE_DIR}/malikania/account_dao.cpp
     ${libmlk-server_SOURCE_DIR}/malikania/database.cpp
 )
 
--- a/libserver/malikania/account.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libserver/malikania/account.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -32,145 +32,22 @@
 /**
  * \brief Account model
  */
-class Account {
-private:
-    std::uint64_t m_id{0};
-    std::string m_name;
-    std::string m_email;
-    std::string m_firstName;
-    std::string m_lastName;
-    std::string m_password;
-
+class account {
 public:
-    /**
-     * Get the id.
-     *
-     * \return the id
-     */
-    inline std::uint64_t id() const noexcept
-    {
-        return m_id;
-    }
-
-    /**
-     * Set the id.
-     *
-     * \param id the id
-     */
-    inline void setId(std::uint64_t id) noexcept
-    {
-        m_id = id;
-    }
-
-    /**
-     * Get the account name.
-     *
-     * \return the name
-     */
-    inline const std::string &name() const noexcept
-    {
-        return m_name;
-    }
-
-    /**
-     * Set the account name.
-     *
-     * \param name the name
-     */
-    inline void setName(std::string name) noexcept
-    {
-        m_name = std::move(name);
-    }
-
-    /**
-     * Get the email.
-     *
-     * \return the email address
-     */
-    inline const std::string &email() const noexcept
-    {
-        return m_email;
-    }
-
-    /**
-     * Set the email.
-     *
-     * \param email the email address
-     */
-    inline void setEmail(std::string email) noexcept
-    {
-        m_email = std::move(email);
-    }
-
-    /**
-     * Get the first name.
-     *
-     * \return the first name
-     */
-    inline const std::string &firstName() const noexcept
-    {
-        return m_firstName;
-    }
-
-    /**
-     * Set the first name.
-     *
-     * \param firstName the first name
-     */
-    inline void setFirstName(std::string firstName) noexcept
-    {
-        m_firstName = std::move(firstName);
-    }
-
-    /**
-     * Get the last name.
-     *
-     * \return the last name
-     */
-    inline const std::string &lastName() const noexcept
-    {
-        return m_lastName;
-    }
-
-    /**
-     * Set the last name.
-     *
-     * \param lastName the last name
-     */
-    inline void setLastName(std::string lastName) noexcept
-    {
-        m_lastName = std::move(lastName);
-    }
-
-    /**
-     * Get the password.
-     *
-     * \return the password
-     */
-    inline const std::string &password() const noexcept
-    {
-        return m_password;
-    }
-
-    /**
-     * Set the password.
-     *
-     * \param password the password
-     */
-    inline void setPassword(std::string password) noexcept
-    {
-        m_password = std::move(password);
-    }
+    std::uint64_t id;
+    std::string name;
+    std::string email;
+    std::string first_name;
+    std::string last_name;
+    std::string password;
 };
 
-inline bool operator==(const Account &ac1, const Account &ac2) noexcept
+inline bool operator==(const account &ac1, const account &ac2) noexcept
 {
-    return ac1.id() == ac2.id() && ac1.name() == ac2.name() && ac1.email() == ac2.email() &&
-           ac1.firstName() == ac2.firstName() && ac1.lastName() == ac2.lastName() &&
-           ac1.password() == ac2.password();
+    return ac1.id == ac2.id;
 }
 
-inline bool operator!=(const Account &ac1, const Account &ac2) noexcept
+inline bool operator!=(const account &ac1, const account &ac2) noexcept
 {
     return !(ac1 == ac2);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/account_dao.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,68 @@
+/*
+ * dao-account.cpp -- database account management
+ *
+ * Copyright (c) 2013-2016 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 "account.hpp"
+#include "account_dao.hpp"
+#include "database.hpp"
+
+namespace malikania {
+
+using create_func = void (account&);
+using remove_func = void (const account&);
+using update_func = void (account&);
+using get_func = account (std::uint64_t);
+using list_func = std::vector<account> ();
+using count_func = std::uint64_t ();
+using clear_func = void ();
+
+void account_dao::create(account& account)
+{
+    m_database.handle().get<create_func>("malikania_account_create")(account);
+}
+
+void account_dao::remove(const account& account)
+{
+    m_database.handle().get<remove_func>("malikania_account_remove")(account);
+}
+
+void account_dao::update(account& account)
+{
+    m_database.handle().get<update_func>("malikania_account_update")(account);
+}
+
+account account_dao::get(uint64_t id)
+{
+    return m_database.handle().get<get_func>("malikania_account_get")(id);
+}
+
+std::vector<account> account_dao::list()
+{
+    return m_database.handle().get<list_func>("malikania_account_list")();
+}
+
+std::uint64_t account_dao::count()
+{
+    return m_database.handle().get<count_func>("malikania_account_count")();
+}
+
+void account_dao::clear()
+{
+    m_database.handle().get<clear_func>("malikania_account_clear")();
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/account_dao.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,115 @@
+/*
+ * account_dao.hpp -- database account management
+ *
+ * Copyright (c) 2013-2016 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 MALIKANIA_SERVER_ACCOUNT_DAO_HPP
+#define MALIKANIA_SERVER_ACCOUNT_DAO_HPP
+
+/**
+ * \file account_dao.hpp
+ * \brief Database account management.
+ */
+
+#include <cstdint>
+#include <vector>
+
+namespace malikania {
+
+class database;
+class account;
+
+/**
+ * \brief Account DAO.
+ */
+class account_dao {
+private:
+    database& m_database;
+
+public:
+    /**
+     * Constructor.
+     *
+     * \param database the database
+     */
+    inline account_dao(database& database) noexcept
+        : m_database(database)
+    {
+    }
+
+    /**
+     * Create the given account.
+     *
+     * The object will be modified in place.
+     *
+     * \param account the account to add
+     * \throw std::exception on errors
+     */
+    void create(account& account);
+
+    /**
+     * Remove the given account, all data that references this account is
+     * deleted too.
+     *
+     * \param account the account
+     * \throw std::exception on errors
+     */
+    void remove(const account& account);
+
+    /**
+     * Update account only, does not recurse into objects that references the
+     * account.
+     *
+     * \param account the account
+     * \throw std::exception on errors
+     */
+    void update(account& account);
+
+    /**
+     * Get an account.
+     *
+     * \param id the account id
+     * \return the account
+     * \throw std::exception if not found
+     */
+    account get(std::uint64_t id);
+
+    /**
+     * Get the list of account.
+     *
+     * \throw std::exception on errors
+     */
+    std::vector<account> list();
+
+    /**
+     * Get the number of accounts.
+     *
+     * \return the number of account.
+     */
+    std::uint64_t count();
+
+    /**
+     * Remove all accounts recursively.
+     *
+     * \throw std::exception on errors
+     * \warning use with care
+     */
+    void clear();
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_SERVER_ACCOUNT_DAO_HPP
--- a/libserver/malikania/connection-service.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * connection-service.cpp -- manage clients server side
- *
- * Copyright (c) 2016 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 <iostream>
-
-#include "dao-account.hpp"
-#include "connection-state-ready.hpp"
-#include "connection-service.hpp"
-#include "server.hpp"
-
-namespace malikania {
-
-void ConnectionService::slotAuthentication(Server &server,
-                                           Connection &connection,
-                                           const std::string &login,
-                                           const std::string &password)
-{
-    AccountDao dao(server.database());
-
-    try {
-        if (dao.authenticate(login, password)) {
-            std::cout << "client successfully authenticated" << std::endl;
-            server.post([&connection] (auto &) {
-                connection.setState(std::make_unique<Connection::ReadyState>());
-            });
-        } else {
-            std::cout << "client failed to authenticate" << std::endl;
-            connection.error("authentication failed");
-        }
-    } catch (const std::exception &ex) {
-        // FATAL ERROR??
-    }
-}
-
-void ConnectionService::slotDisconnect(Server &, Connection &)
-{
-    std::cout << "client disconnected" << std::endl;
-}
-
-void ConnectionService::syncMaster(Server &server)
-{
-    try {
-        auto socket = net::TlsSocket(m_master.accept());
-
-        socket.setCertificate(m_settings.certificate);
-        socket.setPrivateKey(m_settings.key);
-
-        auto conn = std::make_unique<Connection>(std::move(socket));
-        auto &ref = *conn;
-
-        conn->onAuthentication.connect([this, &server, &ref] (auto login, auto password) {
-            this->slotAuthentication(server, ref, login, password);
-        });
-        conn->onDisconnect.connect([this, &server, &ref] () {
-            this->slotDisconnect(server, ref);
-        });
-
-        m_clients.push_back(std::move(conn));
-
-        std::cout << "new client connected" << std::endl;
-    } catch (const std::exception &ex) {
-        // LOG ERROR SOMEWHERE
-    }
-}
-
-void ConnectionService::syncClients(net::Listener<> &listener, const net::ListenerStatus &status)
-{
-    for (auto it = m_clients.begin(); it != m_clients.end(); ) {
-        auto &cnt = *it;
-
-        if (cnt->handle() == status.socket)
-            cnt->sync(listener, status.flags);
-
-        if (cnt->state().id() == "disconnected")
-            it = m_clients.erase(it);
-        else
-            ++ it;
-    }
-}
-
-ConnectionService::ConnectionService(ConnectionSettings settings)
-    : m_settings(std::move(settings))
-    , m_master(any(m_settings.type & ConnectionSettings::Ipv6) ? AF_INET6 : AF_INET, 0)
-{
-    if (any(m_settings.type & ConnectionSettings::Ipv6)) {
-        m_master.set(net::option::Ipv6Only(m_settings.type == ConnectionSettings::Ipv6));
-        m_master.set(net::option::SockBlockMode(false));
-
-        if (m_settings.address == "*")
-            m_master.bind(net::ipv6::any(m_settings.port));
-        else
-            m_master.bind(net::ipv6::pton(m_settings.address, m_settings.port));
-    } else {
-        if (m_settings.address == "*")
-            m_master.bind(net::ipv4::any(m_settings.port));
-        else
-            m_master.bind(net::ipv4::pton(m_settings.address, m_settings.port));
-    }
-
-    m_master.listen(256);
-}
-
-void ConnectionService::prepare(Server &, net::Listener<> &listener)
-{
-    listener.reset(m_master.handle(), net::Condition::Readable);
-
-    for (auto &cnt : m_clients)
-        cnt->prepare(listener);
-}
-
-void ConnectionService::sync(Server &server,
-                             net::Listener<> &listener,
-                             const net::ListenerStatus &status)
-{
-    if (status.socket == m_master.handle())
-        syncMaster(server);
-    else
-        syncClients(listener, status);
-}
-
-} // !malikania
--- a/libserver/malikania/connection-service.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * connection-service.hpp -- manage clients server side
- *
- * Copyright (c) 2016 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 MALIKANIA_CONNECTION_SERVICE_HPP
-#define MALIKANIA_CONNECTION_SERVICE_HPP
-
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-#include "connection.hpp"
-
-namespace malikania {
-
-class Server;
-
-/**
- * \brief Connections parameters
- */
-class ConnectionSettings {
-public:
-    enum Type {
-        Ipv4        = (1 << 0),         //!< Add IPv4
-        Ipv6        = (1 << 1),         //!< Add IPv6
-        All         = (Ipv4 | Ipv6)     //!< Use both IPv4 and IPv6 on same port
-    } type{All};
-
-    std::string certificate;            //!< Certificate file
-    std::string key;                    //!< Private key file
-    std::string address{"*"};           //!< Address to bind
-    std::uint16_t port{3320};           //!< Port to use
-};
-
-/**
- * \brief Manage connections on the server
- */
-class ConnectionService {
-private:
-    ConnectionSettings m_settings;
-    net::TcpSocket m_master;
-    std::vector<std::unique_ptr<Connection>> m_clients;
-
-    void slotAuthentication(Server &, Connection &, const std::string &, const std::string &);
-    void slotDisconnect(Server &, Connection &);
-
-    void syncMaster(Server &server);
-    void syncClients(net::Listener<> &listener, const net::ListenerStatus &status);
-
-public:
-    ConnectionService(ConnectionSettings settings);
-
-    inline const std::vector<std::unique_ptr<Connection>> &clients() const noexcept
-    {
-        return m_clients;
-    }
-
-    inline std::vector<std::unique_ptr<Connection>> &clients() noexcept
-    {
-        return m_clients;
-    }
-
-    void prepare(Server &server, net::Listener<> &listener);
-
-    void sync(Server &server, net::Listener<> &listener, const net::ListenerStatus &status);
-};
-
-/**
- * \cond ENUM_HIDDEN_SYMBOLS
- */
-
-inline ConnectionSettings::Type operator^(ConnectionSettings::Type v1, ConnectionSettings::Type v2) noexcept
-{
-    return static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
-}
-
-inline ConnectionSettings::Type operator&(ConnectionSettings::Type v1, ConnectionSettings::Type v2) noexcept
-{
-    return static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) & static_cast<unsigned>(v2));
-}
-
-inline ConnectionSettings::Type operator|(ConnectionSettings::Type v1, ConnectionSettings::Type v2) noexcept
-{
-    return static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
-}
-
-inline ConnectionSettings::Type operator~(ConnectionSettings::Type v) noexcept
-{
-    return static_cast<ConnectionSettings::Type>(~static_cast<unsigned>(v));
-}
-
-inline ConnectionSettings::Type &operator|=(ConnectionSettings::Type &v1, ConnectionSettings::Type v2) noexcept
-{
-    v1 = static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
-
-    return v1;
-}
-
-inline ConnectionSettings::Type &operator&=(ConnectionSettings::Type &v1, ConnectionSettings::Type v2) noexcept
-{
-    v1 = static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) & static_cast<unsigned>(v2));
-
-    return v1;
-}
-
-inline ConnectionSettings::Type &operator^=(ConnectionSettings::Type &v1, ConnectionSettings::Type v2) noexcept
-{
-    v1 = static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
-
-    return v1;
-}
-
-/**
- * \endcond
- */
-
-} // !malikania
-
-#endif // !MALIKANIA_CONNECTION_SERVICE_HPP
--- a/libserver/malikania/connection-state-authenticating.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * connection-state-authenticating.cpp -- user is authenticating
- *
- * Copyright (c) 2016 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 "connection-state-authenticating.hpp"
-
-namespace malikania {
-
-void Connection::AuthenticatingState::prepare(Connection &conn, net::Listener<> &listener)
-{
-    listener.reset(conn.m_socket.handle(), net::Condition::Readable);
-}
-
-void Connection::AuthenticatingState::sync(Connection &conn, net::Listener<> &, net::Condition)
-{
-    recv(conn, m_input);
-
-    auto value = next(conn, m_input);
-
-    if (!value.is_object())
-        return;
-
-    auto login = value.find("login");
-    auto password = value.find("password");
-
-    if (login != value.end() && login->is_string() &&
-        password != value.end() && password->is_string())
-        conn.onAuthentication(*login, *password);
-}
-
-std::string Connection::AuthenticatingState::id() const noexcept
-{
-    return "authenticating";
-}
-
-} // !malikania
--- a/libserver/malikania/connection-state-authenticating.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * connection-state-authenticating.hpp -- user is authenticating
- *
- * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_AUTHENTICATING_HPP
-#define MALIKANIA_CONNECTION_STATE_AUTHENTICATING_HPP
-
-/**
- * \file connection-state-authenticating.hpp
- * \brief User is authenticating.
- */
-
-#include "connection-state.hpp"
-
-namespace malikania {
-
-/**
- * \brief User is authenticating.
- */
-class Connection::AuthenticatingState : public Connection::State {
-private:
-    std::string m_input;
-
-public:
-    void prepare(Connection &conn, net::Listener<> &listener) override;
-
-    void sync(Connection &conn, net::Listener<> &, net::Condition) override;
-
-    std::string id() const noexcept override;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_CONNECTION_STATE_AUTHENTICATING_HPP
--- a/libserver/malikania/connection-state-closing.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * connection-state-closing.hpp -- closing connection to the user
- *
- * Copyright (c) 2016 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 "connection-state-disconnected.hpp"
-#include "connection-state-closing.hpp"
-
-namespace malikania {
-
-void Connection::ClosingState::prepare(Connection &conn, net::Listener<> &listener)
-{
-    if (conn.m_output.empty())
-        listener.remove(conn.handle());
-    else
-        listener.reset(conn.handle(), net::Condition::Writable);
-}
-
-void Connection::ClosingState::sync(Connection &conn, net::Listener<> &, net::Condition)
-{
-    send(conn, conn.m_output);
-
-    if (conn.m_output.empty())
-        conn.m_stateNext = std::make_unique<DisconnectedState>();
-}
-
-std::string Connection::ClosingState::id() const noexcept
-{
-    return "closing";
-}
-
-} // !malikania
--- a/libserver/malikania/connection-state-closing.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * connection-state-closing.hpp -- closing connection to the user
- *
- * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_CLOSING_HPP
-#define MALIKANIA_CONNECTION_STATE_CLOSING_HPP
-
-/**
- * \file connection-state-closing.hpp
- * \brief Closing connection to the user.
- */
-
-#include "connection-state.hpp"
-
-namespace malikania {
-
-/**
- * \brief Closing connection to the user.
- */
-class Connection::ClosingState : public Connection::State {
-public:
-    void prepare(Connection &conn, net::Listener<> &listener) override;
-
-    void sync(Connection &conn, net::Listener<> &, net::Condition) override;
-
-    std::string id() const noexcept override;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_CONNECTION_STATE_CLOSING_HPP
--- a/libserver/malikania/connection-state-disconnected.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * connection-state-disconnected.cpp -- client is down and will be removed
- *
- * Copyright (c) 2016 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 "connection-state-disconnected.hpp"
-
-namespace malikania {
-
-void Connection::DisconnectedState::prepare(Connection &, net::Listener<> &)
-{
-}
-
-void Connection::DisconnectedState::sync(Connection &, net::Listener<> &, net::Condition)
-{
-}
-
-std::string Connection::DisconnectedState::id() const noexcept
-{
-    return "disconnected";
-}
-
-} // !malikania
--- a/libserver/malikania/connection-state-disconnected.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * connection-state-disconnected.hpp -- client is down and will be removed
- *
- * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_DISCONNECTED_HPP
-#define MALIKANIA_CONNECTION_STATE_DISCONNECTED_HPP
-
-/**
- * \file connection-state-disconected.hpp
- * \brief Client is down and will be removed.
- */
-
-#include "connection-state.hpp"
-
-namespace malikania {
-
-/**
- * \brief Client is down and will be removed.
- */
-class Connection::DisconnectedState : public Connection::State {
-public:
-    void prepare(Connection &conn, net::Listener<> &listener) override;
-
-    void sync(Connection &conn, net::Listener<> &, net::Condition) override;
-
-    std::string id() const noexcept override;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_CONNECTION_STATE_DISCONNECTED_HPP
--- a/libserver/malikania/connection-state-greeting.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * connection-state-greeting.cpp -- greeting the user
- *
- * Copyright (c) 2016 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 <json.hpp>
-
-#include "connection-state-authenticating.hpp"
-#include "connection-state-greeting.hpp"
-
-namespace malikania {
-
-Connection::GreetingState::GreetingState()
-{
-    // TODO: this is just an example.
-    m_output += nlohmann::json::object({
-        { "malikania", "0.1.0" }
-    }).dump();
-    m_output += "\r\n\r\n";
-}
-
-void Connection::GreetingState::prepare(Connection &conn, net::Listener<> &listener)
-{
-    listener.reset(conn.m_socket.handle(), net::Condition::Writable);
-}
-
-void Connection::GreetingState::sync(Connection &conn, net::Listener<> &listener, net::Condition condition)
-{
-    assert(condition == net::Condition::Writable);
-
-    if (m_output.length() > 0)
-        send(conn, m_output);
-    else {
-        listener.unset(conn.handle(), net::Condition::Writable);
-        conn.m_stateNext = std::make_unique<AuthenticatingState>();
-    }
-}
-
-std::string Connection::GreetingState::id() const noexcept
-{
-    return "greeting";
-}
-
-} // !malikania
--- a/libserver/malikania/connection-state-greeting.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * connection-state-greeting.hpp -- greeting the user
- *
- * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_GREETING_HPP
-#define MALIKANIA_CONNECTION_STATE_GREETING_HPP
-
-/**
- * \file connection-state-greeting.hpp
- * \brief Greeting the user.
- */
-
-#include "connection-state.hpp"
-
-namespace malikania {
-
-/**
- * \brief Greeting the user.
- */
-class Connection::GreetingState : public Connection::State {
-private:
-    std::string m_output;
-
-public:
-    GreetingState();
-
-    void prepare(Connection &conn, net::Listener<> &listener) override;
-
-    void sync(Connection &conn, net::Listener<> &listener, net::Condition condition) override;
-
-    std::string id() const noexcept override;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_CONNECTION_STATE_GREETING_HPP
--- a/libserver/malikania/connection-state-ready.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * connection-state-ready.cpp -- client is ready
- *
- * Copyright (c) 2016 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 "connection-state-ready.hpp"
-
-namespace malikania {
-
-void Connection::ReadyState::prepare(Connection &conn, net::Listener<> &listener)
-{
-    if (!conn.m_output.empty())
-        listener.reset(conn.handle(), net::Condition::Writable);
-
-    listener.reset(conn.handle(), net::Condition::Readable);
-}
-
-void Connection::ReadyState::sync(Connection &conn, net::Listener<> &lst, net::Condition cond)
-{
-    if (bool(cond & net::Condition::Readable))
-        recv(conn, conn.m_input);
-
-    if (bool(cond & net::Condition::Writable)) {
-        send(conn, conn.m_output);
-
-        if (conn.m_output.empty())
-            lst.unset(conn.handle(), net::Condition::Writable);
-    }
-}
-
-std::string Connection::ReadyState::id() const noexcept
-{
-    return "ready";
-}
-
-} // !malikania
--- a/libserver/malikania/connection-state-ready.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * connection-state-ready.hpp -- client is ready
- *
- * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_READY_HPP
-#define MALIKANIA_CONNECTION_STATE_READY_HPP
-
-/**
- * \file connection-state-ready.hpp
- * \brief Client is ready.
- */
-
-#include "connection-state.hpp"
-
-namespace malikania {
-
-/**
- * \brief Client is ready.
- */
-class Connection::ReadyState : public Connection::State {
-public:
-    void prepare(Connection &conn, net::Listener<> &listener) override;
-
-    void sync(Connection &conn, net::Listener<> &listener, net::Condition condition) override;
-
-    std::string id() const noexcept override;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_CONNECTION_STATE_READY_HPP
--- a/libserver/malikania/connection-state.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * connection-state.cpp -- base class for connection state
- *
- * Copyright (c) 2016 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 <iostream>
-
-#include "connection-state-disconnected.hpp"
-#include "connection-state.hpp"
-#include "util.hpp"
-
-namespace malikania {
-
-void Connection::State::close(Connection &conn) noexcept
-{
-    conn.onDisconnect();
-    conn.m_state = std::make_unique<DisconnectedState>();
-}
-
-void Connection::State::recv(Connection &conn, std::string &input) noexcept
-{
-    try {
-        std::string buffer;
-        std::size_t size = 512;
-
-        buffer.resize(size);
-        buffer.resize(conn.m_socket.recv(&buffer[0], size));
-
-        if (buffer.size() == 0)
-            close(conn);
-
-        input += buffer;
-    } catch (const net::WantReadError &) {
-        conn.m_handshake = Handshake::Reading;
-    } catch (const net::WantWriteError &) {
-        conn.m_handshake = Handshake::Writing;
-    } catch (const std::exception &) {
-        close(conn);
-    }
-}
-
-void Connection::State::send(Connection &conn, std::string &output) noexcept
-{
-    assert(output.length() != 0);
-
-    try {
-        auto nsent = conn.m_socket.send(&output[0], output.length());
-
-        if (nsent == 0)
-            close(conn);
-
-        output.erase(0, nsent);
-    } catch (const net::WantReadError &) {
-        conn.m_handshake = Handshake::Reading;
-    } catch (const net::WantWriteError &) {
-        conn.m_handshake = Handshake::Writing;
-    } catch (const std::exception &) {
-        close(conn);
-    }
-}
-
-nlohmann::json Connection::State::next(Connection &conn, std::string &input) noexcept
-{
-    nlohmann::json object;
-
-    try {
-        object = util::json::next(input);
-    } catch (const std::exception &) {
-        close(conn);
-    }
-
-    return object;
-}
-
-} // !malikania
--- a/libserver/malikania/connection-state.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * connection-state.hpp -- base class for connection state
- *
- * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_HPP
-#define MALIKANIA_CONNECTION_STATE_HPP
-
-/**
- * \file connection-state.hpp
- * \brief Base class for connection state.
- */
-
-#include <json.hpp>
-
-#include "connection.hpp"
-
-namespace malikania {
-
-/**
- * \brief Base class for connection state.
- */
-class Connection::State {
-protected:
-    void close(Connection &conn) noexcept;
-
-    void recv(Connection &conn, std::string &input) noexcept;
-
-    void send(Connection &conn, std::string &output) noexcept;
-
-    nlohmann::json next(Connection &conn, std::string &input) noexcept;
-
-public:
-    /**
-     * Default constructor.
-     */
-    State() = default;
-
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~State() = default;
-
-    /**
-     * Prepare the listener about that connection.
-     *
-     * This function should not care about handshake status because the
-     * connection object will never call this function if a handshake is
-     * taking place.
-     *
-     * \param connection the connection
-     * \param listener the listener
-     */
-    virtual void prepare(Connection &connection, net::Listener<> &listener) = 0;
-
-    virtual void sync(Connection &, net::Listener<> &, net::Condition) = 0;
-
-    virtual std::string id() const noexcept = 0;
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_CONNECTION_STATE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_service.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,136 @@
+/*
+ * connection-service.cpp -- manage clients server side
+ *
+ * Copyright (c) 2016 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 <iostream>
+
+#include "dao-account.hpp"
+#include "connection-state-ready.hpp"
+#include "connection-service.hpp"
+#include "server.hpp"
+
+namespace malikania {
+
+void ConnectionService::slotAuthentication(Server &server,
+                                           Connection &connection,
+                                           const std::string &login,
+                                           const std::string &password)
+{
+    AccountDao dao(server.database());
+
+    try {
+        if (dao.authenticate(login, password)) {
+            std::cout << "client successfully authenticated" << std::endl;
+            server.post([&connection] (auto &) {
+                connection.setState(std::make_unique<Connection::ReadyState>());
+            });
+        } else {
+            std::cout << "client failed to authenticate" << std::endl;
+            connection.error("authentication failed");
+        }
+    } catch (const std::exception &ex) {
+        // FATAL ERROR??
+    }
+}
+
+void ConnectionService::slotDisconnect(Server &, Connection &)
+{
+    std::cout << "client disconnected" << std::endl;
+}
+
+void ConnectionService::syncMaster(Server &server)
+{
+    try {
+        auto socket = net::TlsSocket(m_master.accept());
+
+        socket.setCertificate(m_settings.certificate);
+        socket.setPrivateKey(m_settings.key);
+
+        auto conn = std::make_unique<Connection>(std::move(socket));
+        auto &ref = *conn;
+
+        conn->onAuthentication.connect([this, &server, &ref] (auto login, auto password) {
+            this->slotAuthentication(server, ref, login, password);
+        });
+        conn->onDisconnect.connect([this, &server, &ref] () {
+            this->slotDisconnect(server, ref);
+        });
+
+        m_clients.push_back(std::move(conn));
+
+        std::cout << "new client connected" << std::endl;
+    } catch (const std::exception &ex) {
+        // LOG ERROR SOMEWHERE
+    }
+}
+
+void ConnectionService::syncClients(net::Listener<> &listener, const net::ListenerStatus &status)
+{
+    for (auto it = m_clients.begin(); it != m_clients.end(); ) {
+        auto &cnt = *it;
+
+        if (cnt->handle() == status.socket)
+            cnt->sync(listener, status.flags);
+
+        if (cnt->state().id() == "disconnected")
+            it = m_clients.erase(it);
+        else
+            ++ it;
+    }
+}
+
+ConnectionService::ConnectionService(ConnectionSettings settings)
+    : m_settings(std::move(settings))
+    , m_master(any(m_settings.type & ConnectionSettings::Ipv6) ? AF_INET6 : AF_INET, 0)
+{
+    if (any(m_settings.type & ConnectionSettings::Ipv6)) {
+        m_master.set(net::option::Ipv6Only(m_settings.type == ConnectionSettings::Ipv6));
+        m_master.set(net::option::SockBlockMode(false));
+
+        if (m_settings.address == "*")
+            m_master.bind(net::ipv6::any(m_settings.port));
+        else
+            m_master.bind(net::ipv6::pton(m_settings.address, m_settings.port));
+    } else {
+        if (m_settings.address == "*")
+            m_master.bind(net::ipv4::any(m_settings.port));
+        else
+            m_master.bind(net::ipv4::pton(m_settings.address, m_settings.port));
+    }
+
+    m_master.listen(256);
+}
+
+void ConnectionService::prepare(Server &, net::Listener<> &listener)
+{
+    listener.reset(m_master.handle(), net::Condition::Readable);
+
+    for (auto &cnt : m_clients)
+        cnt->prepare(listener);
+}
+
+void ConnectionService::sync(Server &server,
+                             net::Listener<> &listener,
+                             const net::ListenerStatus &status)
+{
+    if (status.socket == m_master.handle())
+        syncMaster(server);
+    else
+        syncClients(listener, status);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_service.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,133 @@
+/*
+ * connection-service.hpp -- manage clients server side
+ *
+ * Copyright (c) 2016 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 MALIKANIA_CONNECTION_SERVICE_HPP
+#define MALIKANIA_CONNECTION_SERVICE_HPP
+
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "connection.hpp"
+
+namespace malikania {
+
+class Server;
+
+/**
+ * \brief Connections parameters
+ */
+class ConnectionSettings {
+public:
+    enum Type {
+        Ipv4        = (1 << 0),         //!< Add IPv4
+        Ipv6        = (1 << 1),         //!< Add IPv6
+        All         = (Ipv4 | Ipv6)     //!< Use both IPv4 and IPv6 on same port
+    } type{All};
+
+    std::string certificate;            //!< Certificate file
+    std::string key;                    //!< Private key file
+    std::string address{"*"};           //!< Address to bind
+    std::uint16_t port{3320};           //!< Port to use
+};
+
+/**
+ * \brief Manage connections on the server
+ */
+class ConnectionService {
+private:
+    ConnectionSettings m_settings;
+    net::TcpSocket m_master;
+    std::vector<std::unique_ptr<Connection>> m_clients;
+
+    void slotAuthentication(Server &, Connection &, const std::string &, const std::string &);
+    void slotDisconnect(Server &, Connection &);
+
+    void syncMaster(Server &server);
+    void syncClients(net::Listener<> &listener, const net::ListenerStatus &status);
+
+public:
+    ConnectionService(ConnectionSettings settings);
+
+    inline const std::vector<std::unique_ptr<Connection>> &clients() const noexcept
+    {
+        return m_clients;
+    }
+
+    inline std::vector<std::unique_ptr<Connection>> &clients() noexcept
+    {
+        return m_clients;
+    }
+
+    void prepare(Server &server, net::Listener<> &listener);
+
+    void sync(Server &server, net::Listener<> &listener, const net::ListenerStatus &status);
+};
+
+/**
+ * \cond ENUM_HIDDEN_SYMBOLS
+ */
+
+inline ConnectionSettings::Type operator^(ConnectionSettings::Type v1, ConnectionSettings::Type v2) noexcept
+{
+    return static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
+}
+
+inline ConnectionSettings::Type operator&(ConnectionSettings::Type v1, ConnectionSettings::Type v2) noexcept
+{
+    return static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) & static_cast<unsigned>(v2));
+}
+
+inline ConnectionSettings::Type operator|(ConnectionSettings::Type v1, ConnectionSettings::Type v2) noexcept
+{
+    return static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
+}
+
+inline ConnectionSettings::Type operator~(ConnectionSettings::Type v) noexcept
+{
+    return static_cast<ConnectionSettings::Type>(~static_cast<unsigned>(v));
+}
+
+inline ConnectionSettings::Type &operator|=(ConnectionSettings::Type &v1, ConnectionSettings::Type v2) noexcept
+{
+    v1 = static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
+
+    return v1;
+}
+
+inline ConnectionSettings::Type &operator&=(ConnectionSettings::Type &v1, ConnectionSettings::Type v2) noexcept
+{
+    v1 = static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) & static_cast<unsigned>(v2));
+
+    return v1;
+}
+
+inline ConnectionSettings::Type &operator^=(ConnectionSettings::Type &v1, ConnectionSettings::Type v2) noexcept
+{
+    v1 = static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
+
+    return v1;
+}
+
+/**
+ * \endcond
+ */
+
+} // !malikania
+
+#endif // !MALIKANIA_CONNECTION_SERVICE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,88 @@
+/*
+ * connection-state.cpp -- base class for connection state
+ *
+ * Copyright (c) 2016 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 <iostream>
+
+#include "connection-state-disconnected.hpp"
+#include "connection-state.hpp"
+#include "util.hpp"
+
+namespace malikania {
+
+void Connection::State::close(Connection &conn) noexcept
+{
+    conn.onDisconnect();
+    conn.m_state = std::make_unique<DisconnectedState>();
+}
+
+void Connection::State::recv(Connection &conn, std::string &input) noexcept
+{
+    try {
+        std::string buffer;
+        std::size_t size = 512;
+
+        buffer.resize(size);
+        buffer.resize(conn.m_socket.recv(&buffer[0], size));
+
+        if (buffer.size() == 0)
+            close(conn);
+
+        input += buffer;
+    } catch (const net::WantReadError &) {
+        conn.m_handshake = Handshake::Reading;
+    } catch (const net::WantWriteError &) {
+        conn.m_handshake = Handshake::Writing;
+    } catch (const std::exception &) {
+        close(conn);
+    }
+}
+
+void Connection::State::send(Connection &conn, std::string &output) noexcept
+{
+    assert(output.length() != 0);
+
+    try {
+        auto nsent = conn.m_socket.send(&output[0], output.length());
+
+        if (nsent == 0)
+            close(conn);
+
+        output.erase(0, nsent);
+    } catch (const net::WantReadError &) {
+        conn.m_handshake = Handshake::Reading;
+    } catch (const net::WantWriteError &) {
+        conn.m_handshake = Handshake::Writing;
+    } catch (const std::exception &) {
+        close(conn);
+    }
+}
+
+nlohmann::json Connection::State::next(Connection &conn, std::string &input) noexcept
+{
+    nlohmann::json object;
+
+    try {
+        object = util::json::next(input);
+    } catch (const std::exception &) {
+        close(conn);
+    }
+
+    return object;
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,76 @@
+/*
+ * connection-state.hpp -- base class for connection state
+ *
+ * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_HPP
+#define MALIKANIA_CONNECTION_STATE_HPP
+
+/**
+ * \file connection-state.hpp
+ * \brief Base class for connection state.
+ */
+
+#include <json.hpp>
+
+#include "connection.hpp"
+
+namespace malikania {
+
+/**
+ * \brief Base class for connection state.
+ */
+class Connection::State {
+protected:
+    void close(Connection &conn) noexcept;
+
+    void recv(Connection &conn, std::string &input) noexcept;
+
+    void send(Connection &conn, std::string &output) noexcept;
+
+    nlohmann::json next(Connection &conn, std::string &input) noexcept;
+
+public:
+    /**
+     * Default constructor.
+     */
+    State() = default;
+
+    /**
+     * Virtual destructor defaulted.
+     */
+    virtual ~State() = default;
+
+    /**
+     * Prepare the listener about that connection.
+     *
+     * This function should not care about handshake status because the
+     * connection object will never call this function if a handshake is
+     * taking place.
+     *
+     * \param connection the connection
+     * \param listener the listener
+     */
+    virtual void prepare(Connection &connection, net::Listener<> &listener) = 0;
+
+    virtual void sync(Connection &, net::Listener<> &, net::Condition) = 0;
+
+    virtual std::string id() const noexcept = 0;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_CONNECTION_STATE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_authenticating.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,50 @@
+/*
+ * connection-state-authenticating.cpp -- user is authenticating
+ *
+ * Copyright (c) 2016 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 "connection-state-authenticating.hpp"
+
+namespace malikania {
+
+void Connection::AuthenticatingState::prepare(Connection &conn, net::Listener<> &listener)
+{
+    listener.reset(conn.m_socket.handle(), net::Condition::Readable);
+}
+
+void Connection::AuthenticatingState::sync(Connection &conn, net::Listener<> &, net::Condition)
+{
+    recv(conn, m_input);
+
+    auto value = next(conn, m_input);
+
+    if (!value.is_object())
+        return;
+
+    auto login = value.find("login");
+    auto password = value.find("password");
+
+    if (login != value.end() && login->is_string() &&
+        password != value.end() && password->is_string())
+        conn.onAuthentication(*login, *password);
+}
+
+std::string Connection::AuthenticatingState::id() const noexcept
+{
+    return "authenticating";
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_authenticating.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,48 @@
+/*
+ * connection-state-authenticating.hpp -- user is authenticating
+ *
+ * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_AUTHENTICATING_HPP
+#define MALIKANIA_CONNECTION_STATE_AUTHENTICATING_HPP
+
+/**
+ * \file connection-state-authenticating.hpp
+ * \brief User is authenticating.
+ */
+
+#include "connection-state.hpp"
+
+namespace malikania {
+
+/**
+ * \brief User is authenticating.
+ */
+class Connection::AuthenticatingState : public Connection::State {
+private:
+    std::string m_input;
+
+public:
+    void prepare(Connection &conn, net::Listener<> &listener) override;
+
+    void sync(Connection &conn, net::Listener<> &, net::Condition) override;
+
+    std::string id() const noexcept override;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_CONNECTION_STATE_AUTHENTICATING_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_closing.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * connection-state-closing.hpp -- closing connection to the user
+ *
+ * Copyright (c) 2016 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 "connection-state-disconnected.hpp"
+#include "connection-state-closing.hpp"
+
+namespace malikania {
+
+void Connection::ClosingState::prepare(Connection &conn, net::Listener<> &listener)
+{
+    if (conn.m_output.empty())
+        listener.remove(conn.handle());
+    else
+        listener.reset(conn.handle(), net::Condition::Writable);
+}
+
+void Connection::ClosingState::sync(Connection &conn, net::Listener<> &, net::Condition)
+{
+    send(conn, conn.m_output);
+
+    if (conn.m_output.empty())
+        conn.m_stateNext = std::make_unique<DisconnectedState>();
+}
+
+std::string Connection::ClosingState::id() const noexcept
+{
+    return "closing";
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_closing.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * connection-state-closing.hpp -- closing connection to the user
+ *
+ * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_CLOSING_HPP
+#define MALIKANIA_CONNECTION_STATE_CLOSING_HPP
+
+/**
+ * \file connection-state-closing.hpp
+ * \brief Closing connection to the user.
+ */
+
+#include "connection-state.hpp"
+
+namespace malikania {
+
+/**
+ * \brief Closing connection to the user.
+ */
+class Connection::ClosingState : public Connection::State {
+public:
+    void prepare(Connection &conn, net::Listener<> &listener) override;
+
+    void sync(Connection &conn, net::Listener<> &, net::Condition) override;
+
+    std::string id() const noexcept override;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_CONNECTION_STATE_CLOSING_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_disconnected.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,36 @@
+/*
+ * connection-state-disconnected.cpp -- client is down and will be removed
+ *
+ * Copyright (c) 2016 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 "connection-state-disconnected.hpp"
+
+namespace malikania {
+
+void Connection::DisconnectedState::prepare(Connection &, net::Listener<> &)
+{
+}
+
+void Connection::DisconnectedState::sync(Connection &, net::Listener<> &, net::Condition)
+{
+}
+
+std::string Connection::DisconnectedState::id() const noexcept
+{
+    return "disconnected";
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_disconnected.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * connection-state-disconnected.hpp -- client is down and will be removed
+ *
+ * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_DISCONNECTED_HPP
+#define MALIKANIA_CONNECTION_STATE_DISCONNECTED_HPP
+
+/**
+ * \file connection-state-disconected.hpp
+ * \brief Client is down and will be removed.
+ */
+
+#include "connection-state.hpp"
+
+namespace malikania {
+
+/**
+ * \brief Client is down and will be removed.
+ */
+class Connection::DisconnectedState : public Connection::State {
+public:
+    void prepare(Connection &conn, net::Listener<> &listener) override;
+
+    void sync(Connection &conn, net::Listener<> &, net::Condition) override;
+
+    std::string id() const noexcept override;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_CONNECTION_STATE_DISCONNECTED_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_greeting.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,57 @@
+/*
+ * connection-state-greeting.cpp -- greeting the user
+ *
+ * Copyright (c) 2016 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 <json.hpp>
+
+#include "connection-state-authenticating.hpp"
+#include "connection-state-greeting.hpp"
+
+namespace malikania {
+
+Connection::GreetingState::GreetingState()
+{
+    // TODO: this is just an example.
+    m_output += nlohmann::json::object({
+        { "malikania", "0.1.0" }
+    }).dump();
+    m_output += "\r\n\r\n";
+}
+
+void Connection::GreetingState::prepare(Connection &conn, net::Listener<> &listener)
+{
+    listener.reset(conn.m_socket.handle(), net::Condition::Writable);
+}
+
+void Connection::GreetingState::sync(Connection &conn, net::Listener<> &listener, net::Condition condition)
+{
+    assert(condition == net::Condition::Writable);
+
+    if (m_output.length() > 0)
+        send(conn, m_output);
+    else {
+        listener.unset(conn.handle(), net::Condition::Writable);
+        conn.m_stateNext = std::make_unique<AuthenticatingState>();
+    }
+}
+
+std::string Connection::GreetingState::id() const noexcept
+{
+    return "greeting";
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_greeting.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,50 @@
+/*
+ * connection-state-greeting.hpp -- greeting the user
+ *
+ * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_GREETING_HPP
+#define MALIKANIA_CONNECTION_STATE_GREETING_HPP
+
+/**
+ * \file connection-state-greeting.hpp
+ * \brief Greeting the user.
+ */
+
+#include "connection-state.hpp"
+
+namespace malikania {
+
+/**
+ * \brief Greeting the user.
+ */
+class Connection::GreetingState : public Connection::State {
+private:
+    std::string m_output;
+
+public:
+    GreetingState();
+
+    void prepare(Connection &conn, net::Listener<> &listener) override;
+
+    void sync(Connection &conn, net::Listener<> &listener, net::Condition condition) override;
+
+    std::string id() const noexcept override;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_CONNECTION_STATE_GREETING_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_ready.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,49 @@
+/*
+ * connection-state-ready.cpp -- client is ready
+ *
+ * Copyright (c) 2016 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 "connection-state-ready.hpp"
+
+namespace malikania {
+
+void Connection::ReadyState::prepare(Connection &conn, net::Listener<> &listener)
+{
+    if (!conn.m_output.empty())
+        listener.reset(conn.handle(), net::Condition::Writable);
+
+    listener.reset(conn.handle(), net::Condition::Readable);
+}
+
+void Connection::ReadyState::sync(Connection &conn, net::Listener<> &lst, net::Condition cond)
+{
+    if (bool(cond & net::Condition::Readable))
+        recv(conn, conn.m_input);
+
+    if (bool(cond & net::Condition::Writable)) {
+        send(conn, conn.m_output);
+
+        if (conn.m_output.empty())
+            lst.unset(conn.handle(), net::Condition::Writable);
+    }
+}
+
+std::string Connection::ReadyState::id() const noexcept
+{
+    return "ready";
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver/malikania/connection_state_ready.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * connection-state-ready.hpp -- client is ready
+ *
+ * Copyright (c) 2016 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 MALIKANIA_CONNECTION_STATE_READY_HPP
+#define MALIKANIA_CONNECTION_STATE_READY_HPP
+
+/**
+ * \file connection-state-ready.hpp
+ * \brief Client is ready.
+ */
+
+#include "connection-state.hpp"
+
+namespace malikania {
+
+/**
+ * \brief Client is ready.
+ */
+class Connection::ReadyState : public Connection::State {
+public:
+    void prepare(Connection &conn, net::Listener<> &listener) override;
+
+    void sync(Connection &conn, net::Listener<> &listener, net::Condition condition) override;
+
+    std::string id() const noexcept override;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_CONNECTION_STATE_READY_HPP
--- a/libserver/malikania/dao-account.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * dao-account.cpp -- database account management
- *
- * Copyright (c) 2013-2016 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 "account.hpp"
-#include "dao-account.hpp"
-#include "database.hpp"
-
-namespace malikania {
-
-using Create = void (Account&);
-using Remove = void (const Account&);
-using Update = void (Account&);
-using Get = Account (std::uint64_t);
-using List = std::vector<Account> ();
-using Count = std::uint64_t ();
-using Clear = void ();
-
-void AccountDao::create(Account &account)
-{
-    m_database.handle().get<Create>("malikania_account_create")(account);
-}
-
-void AccountDao::remove(const Account &account)
-{
-    m_database.handle().get<Remove>("malikania_account_remove")(account);
-}
-
-void AccountDao::update(Account &account)
-{
-    m_database.handle().get<Update>("malikania_account_update")(account);
-}
-
-Account AccountDao::get(uint64_t id)
-{
-    return m_database.handle().get<Get>("malikania_account_get")(id);
-}
-
-std::vector<Account> AccountDao::list()
-{
-    return m_database.handle().get<List>("malikania_account_list")();
-}
-
-std::uint64_t AccountDao::count()
-{
-    return m_database.handle().get<Count>("malikania_account_count")();
-}
-
-void AccountDao::clear()
-{
-    m_database.handle().get<Clear>("malikania_account_clear")();
-}
-
-} // !malikania
--- a/libserver/malikania/dao-account.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * dao-account.hpp -- database account management
- *
- * Copyright (c) 2013-2016 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 MALIKANIA_DAO_ACCOUNT_HPP
-#define MALIKANIA_DAO_ACCOUNT_HPP
-
-/**
- * \file dao-account.hpp
- * \brief Database account management.
- */
-
-#include <cstdint>
-#include <vector>
-
-namespace malikania {
-
-class Database;
-class Account;
-
-/**
- * \brief Account DAO.
- */
-class AccountDao {
-private:
-    Database &m_database;
-
-public:
-    /**
-     * Constructor.
-     *
-     * \param database the database
-     */
-    inline AccountDao(Database &database) noexcept
-        : m_database(database)
-    {
-    }
-
-    /**
-     * Create the given account.
-     *
-     * The object will be modified in place.
-     *
-     * \param account the account to add
-     * \throw std::exception on errors
-     */
-    void create(Account &account);
-
-    /**
-     * Remove the given account, all data that references this account is deleted too.
-     *
-     * \param account the account
-     * \throw std::exception on errors
-     */
-    void remove(const Account &account);
-
-    /**
-     * Update account only, does not recurse into objects that references the account.
-     *
-     * \param account the account
-     * \throw std::exception on errors
-     */
-    void update(Account &account);
-
-    /**
-     * Get an account.
-     *
-     * \param id the account id
-     * \return the account
-     * \throw std::exception if not found
-     */
-    Account get(std::uint64_t id);
-
-    /**
-     * Get the list of account.
-     *
-     * \throw std::exception on errors
-     */
-    std::vector<Account> list();
-
-    /**
-     * Get the number of accounts.
-     *
-     * \return the number of account.
-     */
-    std::uint64_t count();
-
-    /**
-     * Remove all accounts recursively.
-     *
-     * \throw std::exception on errors
-     * \warning use with care
-     */
-    void clear();
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_DAO_ACCOUNT_HPP
--- a/libserver/malikania/database.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libserver/malikania/database.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -20,18 +20,18 @@
 
 namespace malikania {
 
-using Load = void (const std::unordered_map<std::string, std::string>&);
-using Unload = void ();
+using load_func = void (const std::unordered_map<std::string, std::string>&);
+using unload_func = void ();
 
-Database::Database(const std::string &path, const std::unordered_map<std::string, std::string> &params)
+database::database(const std::string& path, const std::unordered_map<std::string, std::string>& params)
     : m_dso(path)
 {
-    m_dso.get<Load>("malikania_driver_load")(params);
+    m_dso.get<load_func>("malikania_driver_load")(params);
 }
 
-Database::~Database()
+database::~database()
 {
-    m_dso.get<Unload>("malikania_driver_unload")();
+    m_dso.get<unload_func>("malikania_driver_unload")();
 }
 
 } // !malikania
--- a/libserver/malikania/database.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/libserver/malikania/database.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -34,7 +34,7 @@
 /**
  * \brief Generic database.
  */
-class Database {
+class database {
 private:
     boost::dll::shared_library m_dso;
 
@@ -48,12 +48,12 @@
      * \param params the parameters to pass to the driver
      * \throw std::exception on errors
      */
-    Database(const std::string &type, const std::unordered_map<std::string, std::string> &params);
+    database(const std::string& type, const std::unordered_map<std::string, std::string>& params);
 
     /**
      * Close the database.
      */
-    ~Database();
+    ~database();
 
     /**
      * Get the associated dso handle.
--- a/server/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/server/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -16,40 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <iostream>
-
-#include "malikania/account.hpp"
-#include "malikania/dao-account.hpp"
-#include "malikania/database.hpp"
-
-using namespace malikania;
-
-int main(int, char **)
+int main()
 {
-    try {
-        Database database("./pgsql", {
-            { "user",       "kingdom"   },
-            { "host",       "localhost" },
-            { "database",   "kingdomdb" }
-        });
-
-        AccountDao act(database);
-        Account account;
-
-        account.setId(2);
-
-        act.remove(account);
-
-        for (const Account &ac : act.list()) {
-            std::cout << "id          : " << ac.id() << std::endl;
-            std::cout << "name        : " << ac.name() << std::endl;
-            std::cout << "email       : " << ac.email() << std::endl;
-            std::cout << "firstname   : " << ac.firstName() << std::endl;
-            std::cout << "lastname    : " << ac.lastName() << std::endl;
-        }
-    } catch (const std::exception &ex) {
-        std::cerr << ex.what() << std::endl;
-    }
-
-    return 0;
 }
--- a/tests/libclient/animation/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/animation/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test Animation
+ * main.cpp -- test animation
  *
  * Copyright (c) 2013-2016 Malikania Authors
  *
@@ -24,24 +24,22 @@
 
 #include <malikania/animation.hpp>
 #include <malikania/animator.hpp>
-#include <malikania/client-resources-loader.hpp>
-#include <malikania/resources-locator.hpp>
+#include <malikania/client_resources_loader.hpp>
+#include <malikania/resources_locator.hpp>
 #include <malikania/window.hpp>
 
-using namespace malikania;
-
 using namespace std::chrono_literals;
 
 namespace {
 
-Window window(400, 400);
+malikania::window window(400, 400);
 
 } // !namespace
 
 class TestAnimation : public testing::Test {
 protected:
-    ResourcesLocatorDirectory m_locator;
-    ClientResourcesLoader m_loader;
+    malikania::directory_resources_locator m_locator;
+    malikania::client_resources_loader m_loader;
 
 public:
     TestAnimation()
@@ -54,7 +52,7 @@
 TEST_F(TestAnimation, standard)
 {
     try {
-        Animation animation = m_loader.loadAnimation("animations/margins.json");
+        auto animation = m_loader.load_animation("animations/margins.json");
 
         ASSERT_EQ(12U, animation.frames().size());
         ASSERT_EQ(500U, animation[0].delay());
@@ -79,15 +77,15 @@
     boost::timer::cpu_timer timer;
 
     try {
-        Animation animation = m_loader.loadAnimation("animations/margins.json");
-        Animator animator(animation);
+        malikania::animation animation = m_loader.load_animation("animations/margins.json");
+        malikania::animator animator(animation);
 
         auto x = (400 / 2) - (animation.sprite().cell().width() / 2);
         auto y = (400 / 2) - (animation.sprite().cell().height() / 2);
 
         while (timer.elapsed().wall / 1000000LL < 8000) {
             window.clear();
-            animator.draw(window, Point(x, y));
+            animator.draw(window, malikania::point(x, y));
             animator.update();
             window.present();
         }
--- a/tests/libclient/color/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/color/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test Color
+ * main.cpp -- test color
  *
  * Copyright (c) 2013-2016 Malikania Authors
  *
@@ -29,7 +29,7 @@
 
 TEST(Basic, black)
 {
-    Color c;
+    color c;
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -39,7 +39,7 @@
 
 TEST(Basic, white)
 {
-    Color c{255, 255, 255, 255};
+    color c{255, 255, 255, 255};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(255, c.green());
@@ -49,7 +49,7 @@
 
 TEST(Basic, red)
 {
-    Color c{255, 0, 0, 255};
+    color c{255, 0, 0, 255};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(0, c.green());
@@ -59,7 +59,7 @@
 
 TEST(Basic, green)
 {
-    Color c{0, 255, 0, 255};
+    color c{0, 255, 0, 255};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(255, c.green());
@@ -69,7 +69,7 @@
 
 TEST(Basic, blue)
 {
-    Color c{0, 0, 255, 255};
+    color c{0, 0, 255, 255};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -84,7 +84,7 @@
 
 TEST(Hex, black)
 {
-    Color c{0xff000000};
+    color c{0xff000000};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -94,7 +94,7 @@
 
 TEST(Hex, white)
 {
-    Color c{0xffffffff};
+    color c{0xffffffff};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(255, c.green());
@@ -104,7 +104,7 @@
 
 TEST(Hex, red)
 {
-    Color c{0xffff0000};
+    color c{0xffff0000};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(0, c.green());
@@ -114,7 +114,7 @@
 
 TEST(Hex, green)
 {
-    Color c{0xff00ff00};
+    color c{0xff00ff00};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(255, c.green());
@@ -124,7 +124,7 @@
 
 TEST(Hex, blue)
 {
-    Color c{0xff0000ff};
+    color c{0xff0000ff};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -141,7 +141,7 @@
 
 TEST(Named, black)
 {
-    Color c{"black"};
+    color c{"black"};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -151,7 +151,7 @@
 
 TEST(Named, white)
 {
-    Color c{"white"};
+    color c{"white"};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(255, c.green());
@@ -161,7 +161,7 @@
 
 TEST(Named, red)
 {
-    Color c{"red"};
+    color c{"red"};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(0, c.green());
@@ -171,7 +171,7 @@
 
 TEST(Named, green)
 {
-    Color c{"green"};
+    color c{"green"};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(128, c.green());
@@ -181,7 +181,7 @@
 
 TEST(Named, blue)
 {
-    Color c{"blue"};
+    color c{"blue"};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -192,7 +192,7 @@
 TEST(Named, wrong)
 {
     try {
-        Color c{"does not exist"};
+        color c{"does not exist"};
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -208,7 +208,7 @@
 
 TEST(FullRgb, black)
 {
-    Color c{"#000000"};
+    color c{"#000000"};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -218,7 +218,7 @@
 
 TEST(FullRgb, white)
 {
-    Color c{"#ffffff"};
+    color c{"#ffffff"};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(255, c.green());
@@ -228,7 +228,7 @@
 
 TEST(FullRgb, red)
 {
-    Color c{"#ff0000"};
+    color c{"#ff0000"};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(0, c.green());
@@ -238,7 +238,7 @@
 
 TEST(FullRgb, green)
 {
-    Color c{"#00ff00"};
+    color c{"#00ff00"};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(255, c.green());
@@ -248,7 +248,7 @@
 
 TEST(FullRgb, blue)
 {
-    Color c{"#0000ff"};
+    color c{"#0000ff"};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -259,7 +259,7 @@
 TEST(FullRgb, wrong)
 {
     try {
-        Color c{"#ghijkl"};
+        color c{"#ghijkl"};
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -275,7 +275,7 @@
 
 TEST(ShortRgb, black)
 {
-    Color c{"#000"};
+    color c{"#000"};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -285,7 +285,7 @@
 
 TEST(ShortRgb, white)
 {
-    Color c{"#fff"};
+    color c{"#fff"};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(255, c.green());
@@ -295,7 +295,7 @@
 
 TEST(ShortRgb, red)
 {
-    Color c{"#f00"};
+    color c{"#f00"};
 
     ASSERT_EQ(255, c.red());
     ASSERT_EQ(0, c.green());
@@ -305,7 +305,7 @@
 
 TEST(ShortRgb, green)
 {
-    Color c{"#0f0"};
+    color c{"#0f0"};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(255, c.green());
@@ -315,7 +315,7 @@
 
 TEST(ShortRgb, blue)
 {
-    Color c{"#00f"};
+    color c{"#00f"};
 
     ASSERT_EQ(0, c.red());
     ASSERT_EQ(0, c.green());
@@ -325,7 +325,7 @@
 
 TEST(ShortRgb, combination)
 {
-    Color c{"#123"};
+    color c{"#123"};
 
     ASSERT_EQ(17, c.red());
     ASSERT_EQ(34, c.green());
@@ -336,7 +336,7 @@
 TEST(ShortRgb, wrong)
 {
     try {
-        Color c{"#ghi"};
+        color c{"#ghi"};
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
--- a/tests/libclient/font/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/font/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,44 +21,44 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/client-resources-loader.hpp>
+#include <malikania/client_resources_loader.hpp>
 #include <malikania/color.hpp>
 #include <malikania/font.hpp>
 #include <malikania/point.hpp>
-#include <malikania/resources-locator.hpp>
+#include <malikania/resources_locator.hpp>
 #include <malikania/window.hpp>
 
-using namespace malikania;
-
 using namespace std::chrono_literals;
 
+namespace mlk = malikania;
+
 namespace {
 
-Window window(400, 400);
+mlk::window window(400, 400);
 
 } // !namespace
 
 class TestFont : public testing::Test {
 protected:
-    ResourcesLocatorDirectory m_locator;
-    ClientResourcesLoader m_loader;
-    Font m_font;
+    mlk::directory_resources_locator m_locator;
+    mlk::client_resources_loader m_loader;
+    mlk::font m_font;
 
 public:
     TestFont()
         : m_locator(SOURCE_DIRECTORY "/resources")
         , m_loader(m_locator)
-        , m_font(m_loader.loadFont("DejaVuSans.ttf", 10))
+        , m_font(m_loader.load_font("DejaVuSans.ttf", 10))
     {
-        window.setDrawingColor(Color("black"));
+        window.set_drawing_color(mlk::color("black"));
         window.clear();
     }
 };
 
 TEST_F(TestFont, topleft)
 {
-    window.setDrawingColor(Color("white"));
-    window.drawText("top left", m_font, Point(10, 10));
+    window.set_drawing_color(mlk::color("white"));
+    window.draw_text("top left", m_font, mlk::point(10, 10));
     window.present();
 
     std::this_thread::sleep_for(1s);
@@ -66,10 +66,10 @@
 
 TEST_F(TestFont, topright)
 {
-    Size dim = m_font.clip("top right");
+    auto dim = m_font.clip("top right");
 
-    window.setDrawingColor(Color("white"));
-    window.drawText("top right", m_font, Point(400 - dim.width() - 10, 10));
+    window.set_drawing_color(mlk::color("white"));
+    window.draw_text("top right", m_font, mlk::point(400 - dim.width() - 10, 10));
     window.present();
 
     std::this_thread::sleep_for(1s);
@@ -78,10 +78,10 @@
 
 TEST_F(TestFont, bottomleft)
 {
-    Size dim = m_font.clip("bottom left");
+    auto dim = m_font.clip("bottom left");
 
-    window.setDrawingColor(Color("white"));
-    window.drawText("bottom left", m_font, Point(10, 400 - dim.height() - 10));
+    window.set_drawing_color(mlk::color("white"));
+    window.draw_text("bottom left", m_font, mlk::point(10, 400 - dim.height() - 10));
     window.present();
 
     std::this_thread::sleep_for(1s);
@@ -89,10 +89,10 @@
 
 TEST_F(TestFont, bottomright)
 {
-    Size dim = m_font.clip("bottom right");
+    auto dim = m_font.clip("bottom right");
 
-    window.setDrawingColor(Color("white"));
-    window.drawText("bottom right", m_font, Point(400 - dim.width() - 10, 400 - dim.height() - 10));
+    window.set_drawing_color(mlk::color("white"));
+    window.draw_text("bottom right", m_font, mlk::point(400 - dim.width() - 10, 400 - dim.height() - 10));
     window.present();
 
     std::this_thread::sleep_for(1s);
@@ -100,10 +100,10 @@
 
 TEST_F(TestFont, center)
 {
-    Size dim = m_font.clip("center");
+    auto dim = m_font.clip("center");
 
-    window.setDrawingColor(Color("white"));
-    window.drawText("center", m_font, Point(200 - (dim.width() / 2), 200 - (dim.height() -2)));
+    window.set_drawing_color(mlk::color("white"));
+    window.draw_text("center", m_font, mlk::point(200 - (dim.width() / 2), 200 - (dim.height() -2)));
     window.present();
 
     std::this_thread::sleep_for(1s);
@@ -111,10 +111,10 @@
 
 TEST_F(TestFont, center2)
 {
-    Size dim = m_font.clip("The world is Malikania.");
+    auto dim = m_font.clip("The world is Malikania.");
 
-    window.setDrawingColor(Color("white"));
-    window.drawText("The world is Malikania.", m_font, Point(200 - (dim.width() / 2), 200 - (dim.height() -2)));
+    window.set_drawing_color(mlk::color("white"));
+    window.draw_text("The world is Malikania.", m_font, mlk::point(200 - (dim.width() / 2), 200 - (dim.height() -2)));
     window.present();
 
     std::this_thread::sleep_for(3s);
--- a/tests/libclient/image/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/image/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,25 +21,25 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/client-resources-loader.hpp>
+#include <malikania/client_resources_loader.hpp>
 #include <malikania/image.hpp>
-#include <malikania/resources-locator.hpp>
+#include <malikania/resources_locator.hpp>
 #include <malikania/window.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 using namespace std::chrono_literals;
 
 namespace {
 
-Window window(400, 400);
+mlk::window window(400, 400);
 
 } // !namespace
 
 class TestImage : public testing::Test {
 protected:
-    ResourcesLocatorDirectory m_locator;
-    ClientResourcesLoader m_loader;
+    mlk::directory_resources_locator m_locator;
+    mlk::client_resources_loader m_loader;
 
 public:
     TestImage()
@@ -52,7 +52,7 @@
 TEST_F(TestImage, image100x10)
 {
     try {
-        Image image = m_loader.loadImage("images/100x10.png");
+        auto image = m_loader.load_image("images/100x10.png");
 
         ASSERT_EQ(100U, image.size().width());
         ASSERT_EQ(10U, image.size().height());
@@ -64,7 +64,7 @@
 TEST_F(TestImage, image16x16)
 {
     try {
-        Image image = m_loader.loadImage("images/16x16.png");
+        auto image = m_loader.load_image("images/16x16.png");
 
         ASSERT_EQ(16U, image.size().width());
         ASSERT_EQ(16U, image.size().height());
@@ -76,7 +76,7 @@
 TEST_F(TestImage, image10x100)
 {
     try {
-        Image image = m_loader.loadImage("images/10x100.png");
+        auto image = m_loader.load_image("images/10x100.png");
 
         ASSERT_EQ(10U, image.size().width());
         ASSERT_EQ(100U, image.size().height());
@@ -88,7 +88,7 @@
 TEST_F(TestImage, notfound)
 {
     try {
-        m_loader.loadImage("image-not-found");
+        m_loader.load_image("image-not-found");
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -103,12 +103,12 @@
 TEST_F(TestImage, draw)
 {
     try {
-        auto image = m_loader.loadImage("images/smiley.png");
+        auto image = m_loader.load_image("images/smiley.png");
         auto x = (400 / 2) - (image.size().width() / 2);
         auto y = (400 / 2) - (image.size().height() / 2);
 
         window.clear();
-        image.draw(window, Point(x, y));
+        image.draw(window, mlk::point(x, y));
         window.present();
 
         std::this_thread::sleep_for(3s);
--- a/tests/libclient/js-animation/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-animation/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,20 +21,20 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-client-resources-loader.hpp>
-#include <malikania/js-animation.hpp>
-#include <malikania/js-animator.hpp>
-#include <malikania/js-window.hpp>
-#include <malikania/resources-locator.hpp>
+#include <malikania/js_client_resources_loader.hpp>
+#include <malikania/js_animation.hpp>
+#include <malikania/js_animator.hpp>
+#include <malikania/js_window.hpp>
+#include <malikania/resources_locator.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 using namespace std::chrono_literals;
 
 class TestAnimation : public testing::Test {
 protected:
-    ResourcesLocatorDirectory m_locator;
-    ClientResourcesLoader m_loader;
+    mlk::directory_resources_locator m_locator;
+    mlk::client_resources_loader m_loader;
     UniqueContext m_ctx;
 
 public:
@@ -44,10 +44,10 @@
     {
         duk_push_object(m_ctx);
         duk_put_global_string(m_ctx, "Malikania");
-        dukx_load_animation(m_ctx);
-        dukx_load_animator(m_ctx);
-        dukx_load_window(m_ctx);
-        dukx_put_client_loader(m_ctx, &m_loader);
+        mlk::dukx_load_animation(m_ctx);
+        mlk::dukx_load_animator(m_ctx);
+        mlk::dukx_load_window(m_ctx);
+        dukx_put_client_loader(m_ctx, m_loader);
     }
 };
 
--- a/tests/libclient/js-color/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-color/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-color.hpp>
+#include <malikania/js_color.hpp>
 
 using namespace malikania;
 
@@ -487,7 +487,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Color color = dukx_require_color(ctx, 0);
+            auto color = dukx_require_color(ctx, 0);
 
             duk_push_uint(ctx, color.red());
             duk_put_global_string(ctx, "r");
@@ -601,7 +601,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Color color = dukx_get_color(ctx, 0);
+            auto color = dukx_get_color(ctx, 0);
 
             duk_push_uint(ctx, color.red());
             duk_put_global_string(ctx, "r");
@@ -642,7 +642,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Color color = dukx_get_color(ctx, 0);
+            auto color = dukx_get_color(ctx, 0);
 
             duk_push_uint(ctx, color.red());
             duk_put_global_string(ctx, "r");
@@ -683,7 +683,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Color color = dukx_get_color(ctx, 0);
+            auto color = dukx_get_color(ctx, 0);
 
             duk_push_uint(ctx, color.red());
             duk_put_global_string(ctx, "r");
@@ -724,7 +724,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Color color = dukx_get_color(ctx, 0);
+            auto color = dukx_get_color(ctx, 0);
 
             duk_push_uint(ctx, color.red());
             duk_put_global_string(ctx, "r");
--- a/tests/libclient/js-font/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-font/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,19 +21,19 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-client-resources-loader.hpp>
-#include <malikania/js-font.hpp>
-#include <malikania/js-window.hpp>
-#include <malikania/resources-locator.hpp>
+#include <malikania/js_client_resources_loader.hpp>
+#include <malikania/js_font.hpp>
+#include <malikania/js_window.hpp>
+#include <malikania/resources_locator.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 using namespace std::chrono_literals;
 
 class TestFont : public testing::Test {
 protected:
-    ResourcesLocatorDirectory m_locator;
-    ClientResourcesLoader m_loader;
+    mlk::directory_resources_locator m_locator;
+    mlk::client_resources_loader m_loader;
     UniqueContext m_ctx;
 
 public:
@@ -43,9 +43,9 @@
     {
         duk_push_object(m_ctx);
         duk_put_global_string(m_ctx, "Malikania");
-        dukx_put_client_loader(m_ctx, &m_loader);
-        dukx_load_font(m_ctx);
-        dukx_load_window(m_ctx);
+        dukx_put_client_loader(m_ctx, m_loader);
+        mlk::dukx_load_font(m_ctx);
+        mlk::dukx_load_window(m_ctx);
     }
 };
 
@@ -64,8 +64,9 @@
             "w.present();"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         std::this_thread::sleep_for(3s);
     } catch (const std::exception &ex) {
--- a/tests/libclient/js-image/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-image/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,19 +21,19 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-client-resources-loader.hpp>
-#include <malikania/js-image.hpp>
-#include <malikania/js-window.hpp>
-#include <malikania/resources-locator.hpp>
+#include <malikania/js_client_resources_loader.hpp>
+#include <malikania/js_image.hpp>
+#include <malikania/js_window.hpp>
+#include <malikania/resources_locator.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 using namespace std::chrono_literals;
 
 class TestImage : public testing::Test {
 protected:
-    ResourcesLocatorDirectory m_locator;
-    ClientResourcesLoader m_loader;
+    mlk::directory_resources_locator m_locator;
+    mlk::client_resources_loader m_loader;
     UniqueContext m_ctx;
 
 public:
@@ -43,9 +43,9 @@
     {
         duk_push_object(m_ctx);
         duk_put_global_string(m_ctx, "Malikania");
-        dukx_load_image(m_ctx);
-        dukx_load_window(m_ctx);
-        dukx_put_client_loader(m_ctx, &m_loader);
+        mlk::dukx_load_image(m_ctx);
+        mlk::dukx_load_window(m_ctx);
+        dukx_put_client_loader(m_ctx, m_loader);
     }
 };
 
--- a/tests/libclient/js-line/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-line/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-line.hpp>
+#include <malikania/js_line.hpp>
 
 using namespace malikania;
 
@@ -51,8 +51,9 @@
             "y2 = r.y2;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x1");
         ASSERT_EQ(0, duk_to_int(m_ctx, -1));
@@ -82,8 +83,9 @@
             "y2 = r.y2;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x1");
         ASSERT_EQ(10, duk_to_int(m_ctx, -1));
@@ -113,8 +115,9 @@
             "y2 = r.y2;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x1");
         ASSERT_EQ(10, duk_to_int(m_ctx, -1));
@@ -144,8 +147,9 @@
             "y2 = r.y2;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x1");
         ASSERT_EQ(10, duk_to_int(m_ctx, -1));
@@ -181,8 +185,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
@@ -204,7 +209,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Line line = dukx_require_line(ctx, 0);
+            auto line = dukx_require_line(ctx, 0);
 
             duk_push_int(ctx, line.x1());
             duk_put_global_string(ctx, "x1");
@@ -221,8 +226,9 @@
 
         auto ret = duk_peval_string(m_ctx, "build({ x1: 50, y1: 80, x2: 100, y2: 200 });");
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x1");
         ASSERT_EQ(50, duk_to_int(m_ctx, -1));
@@ -260,8 +266,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
@@ -283,7 +290,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Line line = dukx_get_line(ctx, 0);
+            auto line = dukx_get_line(ctx, 0);
 
             duk_push_int(ctx, line.x1());
             duk_put_global_string(ctx, "x1");
@@ -300,8 +307,9 @@
 
         auto ret = duk_peval_string(m_ctx, "build({});");
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x1");
         ASSERT_EQ(0, duk_to_int(m_ctx, -1));
--- a/tests/libclient/js-point/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-point/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-point.hpp>
+#include <malikania/js_point.hpp>
 
 using namespace malikania;
 
@@ -49,8 +49,9 @@
             "y = p.y;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(0, duk_to_int(m_ctx, -1));
@@ -72,8 +73,9 @@
             "y = p.y;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(-10, duk_to_int(m_ctx, -1));
@@ -95,8 +97,9 @@
             "y = p.y;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(100, duk_to_int(m_ctx, -1));
@@ -118,8 +121,9 @@
             "y = p.y;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(100, duk_to_int(m_ctx, -1));
@@ -149,8 +153,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
@@ -172,7 +177,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Point point = dukx_require_point(ctx, 0);
+            auto point = dukx_require_point(ctx, 0);
 
             duk_push_int(ctx, point.x());
             duk_put_global_string(ctx, "x");
@@ -185,8 +190,9 @@
 
         auto ret = duk_peval_string(m_ctx, "build({ x: 100, y: 200 });");
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(100, duk_to_int(m_ctx, -1));
@@ -218,8 +224,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
@@ -241,7 +248,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Point point = dukx_get_point(ctx, 0);
+            auto point = dukx_get_point(ctx, 0);
 
             duk_push_int(ctx, point.x());
             duk_put_global_string(ctx, "x");
@@ -254,8 +261,9 @@
 
         auto ret = duk_peval_string(m_ctx, "build({});");
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(0, duk_to_int(m_ctx, -1));
--- a/tests/libclient/js-rectangle/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-rectangle/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-rectangle.hpp>
+#include <malikania/js_rectangle.hpp>
 
 using namespace malikania;
 
@@ -51,8 +51,9 @@
             "h = r.height;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(0, duk_to_int(m_ctx, -1));
@@ -82,8 +83,9 @@
             "h = r.height;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(10, duk_to_int(m_ctx, -1));
@@ -113,8 +115,9 @@
             "h = r.height;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(10, duk_to_int(m_ctx, -1));
@@ -144,8 +147,9 @@
             "h = r.height;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(10, duk_to_int(m_ctx, -1));
@@ -181,8 +185,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
@@ -207,8 +212,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
@@ -230,7 +236,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Rectangle rect = dukx_require_rect(ctx, 0);
+            auto rect = dukx_require_rect(ctx, 0);
 
             duk_push_int(ctx, rect.x());
             duk_put_global_string(ctx, "x");
@@ -247,8 +253,9 @@
 
         auto ret = duk_peval_string(m_ctx, "build({ x: 50, y: 80, width: 100, height: 200 });");
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(50, duk_to_int(m_ctx, -1));
@@ -286,8 +293,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
@@ -309,7 +317,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Rectangle rect = dukx_get_rect(ctx, 0);
+            auto rect = dukx_get_rect(ctx, 0);
 
             duk_push_int(ctx, rect.x());
             duk_put_global_string(ctx, "x");
@@ -325,8 +333,9 @@
 
         auto ret = duk_peval_string(m_ctx, "build({});");
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "x");
         ASSERT_EQ(0, duk_to_int(m_ctx, -1));
--- a/tests/libclient/js-size/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-size/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-size.hpp>
+#include <malikania/js_size.hpp>
 
 using namespace malikania;
 
@@ -49,8 +49,9 @@
             "h = s.height;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "w");
         ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
@@ -72,8 +73,9 @@
             "h = s.height;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "w");
         ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
@@ -95,8 +97,9 @@
             "h = s.height;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "w");
         ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
@@ -118,8 +121,9 @@
             "h = s.height;"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "w");
         ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
@@ -149,8 +153,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
@@ -175,8 +180,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
@@ -201,8 +207,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
@@ -227,8 +234,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
@@ -253,8 +261,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
@@ -276,7 +285,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Size size = dukx_require_size(ctx, 0);
+            auto size = dukx_require_size(ctx, 0);
 
             duk_push_uint(ctx, size.width());
             duk_put_global_string(ctx, "w");
@@ -289,8 +298,9 @@
 
         auto ret = duk_peval_string(m_ctx, "build({ width: 100, height: 200 });");
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "w");
         ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
@@ -322,8 +332,9 @@
             "}"
         );
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "name");
         ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
@@ -345,7 +356,7 @@
 {
     try {
         duk_push_c_function(m_ctx, [] (auto ctx) {
-            Size size = dukx_get_size(ctx, 0);
+            auto size = dukx_get_size(ctx, 0);
 
             duk_push_uint(ctx, size.width());
             duk_put_global_string(ctx, "w");
@@ -358,8 +369,9 @@
 
         auto ret = duk_peval_string(m_ctx, "build({});");
 
-        if (ret != 0)
+        if (ret != 0) {
             throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "w");
         ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
--- a/tests/libclient/js-sprite/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-sprite/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,172 +21,178 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-client-resources-loader.hpp>
-#include <malikania/js-image.hpp>
-#include <malikania/js-sprite.hpp>
-#include <malikania/js-window.hpp>
-#include <malikania/resources-locator.hpp>
+#include <malikania/js_client_resources_loader.hpp>
+#include <malikania/js_image.hpp>
+#include <malikania/js_sprite.hpp>
+#include <malikania/js_window.hpp>
+#include <malikania/resources_locator.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 using namespace std::chrono_literals;
 
 class TestSprite : public testing::Test {
 protected:
-	ResourcesLocatorDirectory m_locator;
-	ClientResourcesLoader m_loader;
-	UniqueContext m_ctx;
+    mlk::directory_resources_locator m_locator;
+    mlk::client_resources_loader m_loader;
+    UniqueContext m_ctx;
 
 public:
-	TestSprite()
-		: m_locator(SOURCE_DIRECTORY "/resources")
-		, m_loader(m_locator)
-	{
+    TestSprite()
+        : m_locator(SOURCE_DIRECTORY "/resources")
+        , m_loader(m_locator)
+    {
         duk_push_object(m_ctx);
         duk_put_global_string(m_ctx, "Malikania");
-        dukx_load_image(m_ctx);
-        dukx_load_sprite(m_ctx);
-        dukx_load_window(m_ctx);
-        dukx_put_client_loader(m_ctx, &m_loader);
-	}
+        mlk::dukx_load_image(m_ctx);
+        mlk::dukx_load_sprite(m_ctx);
+        mlk::dukx_load_window(m_ctx);
+        dukx_put_client_loader(m_ctx, m_loader);
+    }
 };
 
 TEST_F(TestSprite, cell)
 {
-	try {
-		auto ret = duk_peval_string(m_ctx,
-			"s = new Malikania.Sprite('sprites/margins.json');"
-			"w = s.cell.width;"
-			"h = s.cell.height;"
-		);
+    try {
+        auto ret = duk_peval_string(m_ctx,
+            "s = new Malikania.Sprite('sprites/margins.json');"
+            "w = s.cell.width;"
+            "h = s.cell.height;"
+        );
 
-		if (ret != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (ret != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "w");
-		ASSERT_EQ(32U, duk_to_uint(m_ctx, -1));
+        ASSERT_EQ(32U, duk_to_uint(m_ctx, -1));
         duk_pop(m_ctx);
         duk_get_global_string(m_ctx, "h");
-		ASSERT_EQ(32U, duk_to_uint(m_ctx, -1));
+        ASSERT_EQ(32U, duk_to_uint(m_ctx, -1));
         duk_pop(m_ctx);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 TEST_F(TestSprite, columns)
 {
-	try {
-		auto ret = duk_peval_string(m_ctx,
-			"s = new Malikania.Sprite('sprites/margins.json');"
-			"n = s.columns;"
-		);
+    try {
+        auto ret = duk_peval_string(m_ctx,
+            "s = new Malikania.Sprite('sprites/margins.json');"
+            "n = s.columns;"
+        );
 
-		if (ret != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (ret != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "n");
-		ASSERT_EQ(4U, duk_to_uint(m_ctx, -1));
+        ASSERT_EQ(4U, duk_to_uint(m_ctx, -1));
         duk_pop(m_ctx);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 TEST_F(TestSprite, margins)
 {
-	try {
-		auto ret = duk_peval_string(m_ctx,
-			"s = new Malikania.Sprite('sprites/margins.json');"
-			"w = s.margins.width;"
-			"h = s.margins.height;"
-		);
+    try {
+        auto ret = duk_peval_string(m_ctx,
+            "s = new Malikania.Sprite('sprites/margins.json');"
+            "w = s.margins.width;"
+            "h = s.margins.height;"
+        );
 
-		if (ret != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (ret != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "w");
-		ASSERT_EQ(4U, duk_to_uint(m_ctx, -1));
+        ASSERT_EQ(4U, duk_to_uint(m_ctx, -1));
         duk_pop(m_ctx);
         duk_get_global_string(m_ctx, "h");
-		ASSERT_EQ(6U, duk_to_uint(m_ctx, -1));
+        ASSERT_EQ(6U, duk_to_uint(m_ctx, -1));
         duk_pop(m_ctx);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 TEST_F(TestSprite, rows)
 {
-	try {
-		auto ret = duk_peval_string(m_ctx,
-			"s = new Malikania.Sprite('sprites/margins.json');"
-			"n = s.rows;"
-		);
+    try {
+        auto ret = duk_peval_string(m_ctx,
+            "s = new Malikania.Sprite('sprites/margins.json');"
+            "n = s.rows;"
+        );
 
-		if (ret != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (ret != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "n");
-		ASSERT_EQ(3U, duk_to_uint(m_ctx, -1));
+        ASSERT_EQ(3U, duk_to_uint(m_ctx, -1));
         duk_pop(m_ctx);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 TEST_F(TestSprite, space)
 {
-	try {
-		auto ret = duk_peval_string(m_ctx,
-			"s = new Malikania.Sprite('sprites/margins.json');"
-			"w = s.space.width;"
-			"h = s.space.height;"
-		);
+    try {
+        auto ret = duk_peval_string(m_ctx,
+            "s = new Malikania.Sprite('sprites/margins.json');"
+            "w = s.space.width;"
+            "h = s.space.height;"
+        );
 
-		if (ret != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (ret != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "w");
-		ASSERT_EQ(2U, duk_to_uint(m_ctx, -1));
+        ASSERT_EQ(2U, duk_to_uint(m_ctx, -1));
         duk_pop(m_ctx);
         duk_get_global_string(m_ctx, "h");
-		ASSERT_EQ(3U, duk_to_uint(m_ctx, -1));
+        ASSERT_EQ(3U, duk_to_uint(m_ctx, -1));
         duk_pop(m_ctx);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 TEST_F(TestSprite, basic)
 {
-	try {
-		auto ret = duk_peval_string(m_ctx,
-			"w = new Malikania.Window();"
-			"s = new Malikania.Sprite('sprites/margins.json');"
-			"c = 0;"
-		);
+    try {
+        auto ret = duk_peval_string(m_ctx,
+            "w = new Malikania.Window();"
+            "s = new Malikania.Sprite('sprites/margins.json');"
+            "c = 0;"
+        );
 
-		if (ret != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (ret != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
-		for (unsigned c = 0; c < 12; ++c) {
-			auto ret = duk_peval_string(m_ctx,
-				"w.setDrawingColor('lightskyblue');"
-				"w.clear();"
-				"s.draw(w, c++, { x: 320 - 16, y: 240 - 16 });"
-				"w.present();"
-			);
+        for (unsigned c = 0; c < 12; ++c) {
+            auto ret = duk_peval_string(m_ctx,
+                "w.setDrawingColor('lightskyblue');"
+                "w.clear();"
+                "s.draw(w, c++, { x: 320 - 16, y: 240 - 16 });"
+                "w.present();"
+            );
 
-			if (ret != 0) {
-				throw dukx_exception(m_ctx, -1);
-			}
+            if (ret != 0) {
+                throw dukx_exception(m_ctx, -1);
+            }
 
-			std::this_thread::sleep_for(1s);
-		}
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+            std::this_thread::sleep_for(1s);
+        }
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 int main(int argc, char **argv)
--- a/tests/libclient/js-window/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/js-window/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -21,63 +21,65 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/js-window.hpp>
+#include <malikania/js_window.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 using namespace std::chrono_literals;
 
 class TestWindow : public testing::Test {
 protected:
-	UniqueContext m_ctx;
+    UniqueContext m_ctx;
 
 public:
-	TestWindow()
-	{
+    TestWindow()
+    {
         duk_push_object(m_ctx);
-		duk_put_global_string(m_ctx, "Malikania");
-        dukx_load_window(m_ctx);
-	}
+        duk_put_global_string(m_ctx, "Malikania");
+        mlk::dukx_load_window(m_ctx);
+    }
 };
 
 TEST_F(TestWindow, basic)
 {
-	try {
-		auto ret = duk_peval_string(m_ctx,
-			"w = new Malikania.Window();"
-			"w.setDrawingColor('lightskyblue');"
-			"w.clear();"
-			"w.present();"
-		);
+    try {
+        auto ret = duk_peval_string(m_ctx,
+            "w = new Malikania.Window();"
+            "w.setDrawingColor('lightskyblue');"
+            "w.clear();"
+            "w.present();"
+        );
 
-		if (ret != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (ret != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
-		std::this_thread::sleep_for(3s);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+        std::this_thread::sleep_for(3s);
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 TEST_F(TestWindow, rect)
 {
-	try {
-		auto ret = duk_peval_string(m_ctx,
-			"w = new Malikania.Window();"
-			"w.setDrawingColor('lightskyblue');"
-			"w.clear();"
-			"w.setDrawingColor('white');"
-			"w.drawRectangle({ x: 10, y: 10, width: 10, height: 10 });"
-			"w.present();"
-		);
+    try {
+        auto ret = duk_peval_string(m_ctx,
+            "w = new Malikania.Window();"
+            "w.setDrawingColor('lightskyblue');"
+            "w.clear();"
+            "w.setDrawingColor('white');"
+            "w.drawRectangle({ x: 10, y: 10, width: 10, height: 10 });"
+            "w.present();"
+        );
 
-		if (ret != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (ret != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
-		std::this_thread::sleep_for(3s);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+        std::this_thread::sleep_for(3s);
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 int main(int argc, char **argv)
--- a/tests/libclient/line/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/line/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test Line
+ * main.cpp -- test mlk::line
  *
  * Copyright (c) 2013-2016 Malikania Authors
  *
@@ -20,11 +20,11 @@
 
 #include <malikania/line.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 TEST(Basics, none)
 {
-    Line line;
+    mlk::line line;
 
     ASSERT_EQ(0, line.x1());
     ASSERT_EQ(0, line.y1());
@@ -34,7 +34,7 @@
 
 TEST(Basics, standard)
 {
-    Line line(10, 20, 30, 40);
+    mlk::line line(10, 20, 30, 40);
 
     ASSERT_EQ(10, line.x1());
     ASSERT_EQ(20, line.y1());
@@ -44,25 +44,25 @@
 
 TEST(Basics, operatorEq)
 {
-    Line line1, line2;
+    mlk::line line1, line2;
 
     ASSERT_EQ(line1, line2);
 }
 
 TEST(Basics, operatorEq1)
 {
-    Line line1(10, 20, 30, 40);
-    Line line2(10, 20, 30, 40);
+    mlk::line line1(10, 20, 30, 40);
+    mlk::line line2(10, 20, 30, 40);
 
     ASSERT_EQ(line1, line2);
 }
 
 TEST(Basics, operatorNeq)
 {
-    ASSERT_NE(Line(10), Line(20));
-    ASSERT_NE(Line(10, 10), Line(10, 20));
-    ASSERT_NE(Line(10, 10, 10), Line(10, 10, 20));
-    ASSERT_NE(Line(10, 10, 10, 10), Line(10, 10, 10, 20));
+    ASSERT_NE(mlk::line(10), mlk::line(20));
+    ASSERT_NE(mlk::line(10, 10), mlk::line(10, 20));
+    ASSERT_NE(mlk::line(10, 10, 10), mlk::line(10, 10, 20));
+    ASSERT_NE(mlk::line(10, 10, 10, 10), mlk::line(10, 10, 10, 20));
 }
 
 int main(int argc, char **argv)
--- a/tests/libclient/point/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/point/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test Point
+ * main.cpp -- test mlk::point
  *
  * Copyright (c) 2013-2016 Malikania Authors
  *
@@ -20,11 +20,11 @@
 
 #include <malikania/point.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 TEST(Basics, none)
 {
-    Point point;
+    mlk::point point;
 
     ASSERT_EQ(0, point.x());
     ASSERT_EQ(0, point.y());
@@ -32,7 +32,7 @@
 
 TEST(Basics, standard)
 {
-    Point point(10, 20);
+    mlk::point point(10, 20);
 
     ASSERT_EQ(10, point.x());
     ASSERT_EQ(20, point.y());
@@ -40,23 +40,23 @@
 
 TEST(Basics, operatorEq)
 {
-    Point point1, point2;
+    mlk::point point1, point2;
 
     ASSERT_EQ(point1, point2);
 }
 
 TEST(Basics, operatorEq1)
 {
-    Point point1(10, 20);
-    Point point2(10, 20);
+    mlk::point point1(10, 20);
+    mlk::point point2(10, 20);
 
     ASSERT_EQ(point1, point2);
 }
 
 TEST(Basics, operatorNeq)
 {
-    ASSERT_NE(Point(10), Point(20));
-    ASSERT_NE(Point(10, 10), Point(10, 20));
+    ASSERT_NE(mlk::point(10), mlk::point(20));
+    ASSERT_NE(mlk::point(10, 10), mlk::point(10, 20));
 }
 
 int main(int argc, char **argv)
--- a/tests/libclient/rectangle/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/rectangle/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test Rectangle
+ * main.cpp -- test mlk::rectangle
  *
  * Copyright (c) 2013-2016 Malikania Authors
  *
@@ -20,11 +20,11 @@
 
 #include <malikania/rectangle.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 TEST(Basics, none)
 {
-    Rectangle rectangle;
+    mlk::rectangle rectangle;
 
     ASSERT_EQ(0, rectangle.x());
     ASSERT_EQ(0, rectangle.y());
@@ -34,15 +34,15 @@
 
 TEST(Basics, null)
 {
-    ASSERT_TRUE(Rectangle().isNull());
-    ASSERT_FALSE(Rectangle(0, 0, 10, 0).isNull());
-    ASSERT_FALSE(Rectangle(0, 0, 0, 10).isNull());
-    ASSERT_FALSE(Rectangle(0, 0, 10, 10).isNull());
+    ASSERT_TRUE(mlk::rectangle().is_null());
+    ASSERT_FALSE(mlk::rectangle(0, 0, 10, 0).is_null());
+    ASSERT_FALSE(mlk::rectangle(0, 0, 0, 10).is_null());
+    ASSERT_FALSE(mlk::rectangle(0, 0, 10, 10).is_null());
 }
 
 TEST(Basics, standard)
 {
-    Rectangle rectangle(10, 20, 30, 40);
+    mlk::rectangle rectangle(10, 20, 30, 40);
 
     ASSERT_EQ(10, rectangle.x());
     ASSERT_EQ(20, rectangle.y());
@@ -52,25 +52,25 @@
 
 TEST(Basics, operatorEq)
 {
-    Rectangle rectangle1, rectangle2;
+    mlk::rectangle rectangle1, rectangle2;
 
     ASSERT_EQ(rectangle1, rectangle2);
 }
 
 TEST(Basics, operatorEq1)
 {
-    Rectangle rectangle1(10, 20, 30, 40);
-    Rectangle rectangle2(10, 20, 30, 40);
+    mlk::rectangle rectangle1(10, 20, 30, 40);
+    mlk::rectangle rectangle2(10, 20, 30, 40);
 
     ASSERT_EQ(rectangle1, rectangle2);
 }
 
 TEST(Basics, operatorNeq)
 {
-    ASSERT_NE(Rectangle(10), Rectangle(20));
-    ASSERT_NE(Rectangle(10, 10), Rectangle(10, 20));
-    ASSERT_NE(Rectangle(10, 10, 10), Rectangle(10, 10, 20));
-    ASSERT_NE(Rectangle(10, 10, 10, 10), Rectangle(10, 10, 10, 20));
+    ASSERT_NE(mlk::rectangle(10), mlk::rectangle(20));
+    ASSERT_NE(mlk::rectangle(10, 10), mlk::rectangle(10, 20));
+    ASSERT_NE(mlk::rectangle(10, 10, 10), mlk::rectangle(10, 10, 20));
+    ASSERT_NE(mlk::rectangle(10, 10, 10, 10), mlk::rectangle(10, 10, 10, 20));
 }
 
 int main(int argc, char **argv)
--- a/tests/libclient/size/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/size/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test Size
+ * main.cpp -- test mlk::size
  *
  * Copyright (c) 2013-2016 Malikania Authors
  *
@@ -20,11 +20,11 @@
 
 #include <malikania/size.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 TEST(Basics, none)
 {
-    Size size;
+    mlk::size size;
 
     ASSERT_EQ(0U, size.width());
     ASSERT_EQ(0U, size.height());
@@ -32,14 +32,14 @@
 
 TEST(Basics, null)
 {
-    ASSERT_TRUE(Size().isNull());
-    ASSERT_FALSE(Size(0, 10).isNull());
-    ASSERT_FALSE(Size(10, 0).isNull());
+    ASSERT_TRUE(mlk::size().is_null());
+    ASSERT_FALSE(mlk::size(0, 10).is_null());
+    ASSERT_FALSE(mlk::size(10, 0).is_null());
 }
 
 TEST(Basics, standard)
 {
-    Size size(10, 20);
+    mlk::size size(10, 20);
 
     ASSERT_EQ(10U, size.width());
     ASSERT_EQ(20U, size.height());
@@ -47,23 +47,23 @@
 
 TEST(Basics, operatorEq)
 {
-    Size size1, size2;
+    mlk::size size1, size2;
 
     ASSERT_EQ(size1, size2);
 }
 
 TEST(Basics, operatorEq1)
 {
-    Size size1(10, 20);
-    Size size2(10, 20);
+    mlk::size size1(10, 20);
+    mlk::size size2(10, 20);
 
     ASSERT_EQ(size1, size2);
 }
 
 TEST(Basics, operatorNeq)
 {
-    ASSERT_NE(Size(10), Size(20));
-    ASSERT_NE(Size(10, 10), Size(10, 20));
+    ASSERT_NE(mlk::size(10), mlk::size(20));
+    ASSERT_NE(mlk::size(10, 10), mlk::size(10, 20));
 }
 
 int main(int argc, char **argv)
--- a/tests/libclient/sprite/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libclient/sprite/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -22,25 +22,25 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/client-resources-loader.hpp>
-#include <malikania/resources-locator.hpp>
+#include <malikania/client_resources_loader.hpp>
+#include <malikania/resources_locator.hpp>
 #include <malikania/sprite.hpp>
 #include <malikania/window.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 using namespace std::chrono_literals;
 
 namespace {
 
-Window window(400, 400);
+mlk::window window(400, 400);
 
 } // !namespace
 
 class TestSprite : public testing::Test {
 protected:
-    ResourcesLocatorDirectory m_locator;
-    ClientResourcesLoader m_loader;
+    mlk::directory_resources_locator m_locator;
+    mlk::client_resources_loader m_loader;
 
 public:
     TestSprite()
@@ -58,7 +58,7 @@
 TEST_F(TestSprite, missingPropertyImage)
 {
     try {
-        m_loader.loadSprite("sprites/no-property-image.json");
+        m_loader.load_sprite("sprites/no-property-image.json");
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -68,7 +68,7 @@
 TEST_F(TestSprite, missingPropertyCell)
 {
     try {
-        m_loader.loadSprite("sprites/no-property-cell.json");
+        m_loader.load_sprite("sprites/no-property-cell.json");
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -83,7 +83,7 @@
 TEST_F(TestSprite, imageNotString)
 {
     try {
-        m_loader.loadSprite("sprites/property-image-not-string.json");
+        m_loader.load_sprite("sprites/property-image-not-string.json");
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -93,7 +93,7 @@
 TEST_F(TestSprite, cellNotArray)
 {
     try {
-        m_loader.loadSprite("sprites/property-cell-not-array.json");
+        m_loader.load_sprite("sprites/property-cell-not-array.json");
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -103,7 +103,7 @@
 TEST_F(TestSprite, cellNotArray2)
 {
     try {
-        m_loader.loadSprite("sprites/property-cell-not-array2.json");
+        m_loader.load_sprite("sprites/property-cell-not-array2.json");
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -118,7 +118,7 @@
 TEST_F(TestSprite, imageNotFound)
 {
     try {
-        m_loader.loadSprite("sprites/image-not-found.json");
+        m_loader.load_sprite("sprites/image-not-found.json");
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -128,7 +128,7 @@
 TEST_F(TestSprite, notObject)
 {
     try {
-        m_loader.loadSprite("sprites/not-object.json");
+        m_loader.load_sprite("sprites/not-object.json");
 
         FAIL() << "exception expected";
     } catch (const std::exception &) {
@@ -143,7 +143,7 @@
 TEST_F(TestSprite, standard)
 {
     try {
-        Sprite sprite = m_loader.loadSprite("sprites/simple.json");
+        auto sprite = m_loader.load_sprite("sprites/simple.json");
 
         ASSERT_EQ(300U, sprite.cell().width());
         ASSERT_EQ(300U, sprite.cell().height());
@@ -155,7 +155,7 @@
 TEST_F(TestSprite, margins)
 {
     try {
-        Sprite sprite = m_loader.loadSprite("sprites/margins.json");
+        auto sprite = m_loader.load_sprite("sprites/margins.json");
 
         ASSERT_EQ(3U, sprite.rows());
         ASSERT_EQ(4U, sprite.columns());
@@ -167,16 +167,15 @@
 TEST_F(TestSprite, draw)
 {
     try {
-        Sprite sprite = m_loader.loadSprite("sprites/margins.json");
+        auto sprite = m_loader.load_sprite("sprites/margins.json");
 
-        unsigned total = sprite.rows() * sprite.columns();
-
+        auto total = sprite.rows() * sprite.columns();
         auto x = (400 / 2) - (sprite.cell().width() / 2);
         auto y = (400 / 2) - (sprite.cell().height() / 2);
 
         for (unsigned c = 0; c < total; ++c) {
             window.clear();
-            sprite.draw(window, c, Point(x, y));
+            sprite.draw(window, c, mlk::point(x, y));
             window.present();
 
             std::this_thread::sleep_for(1s);
--- a/tests/libcommon/js-elapsed-timer/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libcommon/js-elapsed-timer/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -20,9 +20,9 @@
 
 #include <thread>
 
-#include <malikania/js-elapsed-timer.hpp>
+#include <malikania/js_elapsed_timer.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 using namespace std::chrono_literals;
 
@@ -33,119 +33,131 @@
 
 class TestElapsedTimer : public testing::Test {
 protected:
-	UniqueContext m_ctx;
+    UniqueContext m_ctx;
 
-	TestElapsedTimer()
-	{
+    TestElapsedTimer()
+    {
         duk_push_object(m_ctx);
         duk_put_global_string(m_ctx, "Malikania");
-        dukx_load_elapsedtimer(m_ctx);
-	}
+        mlk::dukx_load_elapsedtimer(m_ctx);
+    }
 
-	inline void assertRange(int value, int expected) const noexcept
-	{
-		if (value < (expected - margin) || value > (expected + margin))
-			FAIL() << value << " is bigger than [" << (expected - margin) << ", " << (expected + margin) << "]";
-	}
+    inline void assertRange(int value, int expected) const noexcept
+    {
+        if (value < (expected - margin) || value > (expected + margin)) {
+            FAIL() << value << " is bigger than [" << (expected - margin) << ", " << (expected + margin) << "]";
+        }
+    }
 };
 
 TEST_F(TestElapsedTimer, standard)
 {
-	try {
-		if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-			throw dukx_exception(m_ctx, -1);
+    try {
+        if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
-		std::this_thread::sleep_for(300ms);
+        std::this_thread::sleep_for(300ms);
 
-		if (duk_peval_string(m_ctx, "result = timer.elapsed();") != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (duk_peval_string(m_ctx, "result = timer.elapsed();") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "result");
-		assertRange(duk_to_int(m_ctx, -1), 300);
+        assertRange(duk_to_int(m_ctx, -1), 300);
         duk_pop(m_ctx);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 TEST_F(TestElapsedTimer, reset)
 {
-	try {
-		if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-			throw dukx_exception(m_ctx, -1);
+    try {
+        if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
-		std::this_thread::sleep_for(300ms);
+        std::this_thread::sleep_for(300ms);
 
-		if (duk_peval_string(m_ctx, "timer.reset(); result = timer.elapsed();") != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (duk_peval_string(m_ctx, "timer.reset(); result = timer.elapsed();") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "result");
-		assertRange(duk_to_int(m_ctx, -1), 0);
+        assertRange(duk_to_int(m_ctx, -1), 0);
         duk_pop(m_ctx);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 TEST_F(TestElapsedTimer, pause)
 {
-	try {
-		if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-			throw dukx_exception(m_ctx, -1);
+    try {
+        if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
+
+        /*
+         * Simulate a pause in the game like this:
+         *
+         * start     pause restart elapsed
+         * |   10ms   |.5ms.| 6ms  |
+         *
+         * Since the game was paused, the 5ms must not be totalized.
+         */
+        std::this_thread::sleep_for(10ms);
 
-		/*
-		 * Simulate a pause in the game like this:
-		 *
-		 * start     pause restart elapsed
-		 * |   10ms   |.5ms.| 6ms  |
-		 *
-		 * Since the game was paused, the 5ms must not be totalized.
-		 */
-		std::this_thread::sleep_for(10ms);
+        if (duk_peval_string(m_ctx, "timer.pause();") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
+
+        std::this_thread::sleep_for(5ms);
 
-		if (duk_peval_string(m_ctx, "timer.pause();") != 0)
-			throw dukx_exception(m_ctx, -1);
-
-		std::this_thread::sleep_for(5ms);
+        if (duk_peval_string(m_ctx, "timer.restart();") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
-		if (duk_peval_string(m_ctx, "timer.restart();") != 0)
-			throw dukx_exception(m_ctx, -1);
+        std::this_thread::sleep_for(6ms);
 
-		std::this_thread::sleep_for(6ms);
-
-		if (duk_peval_string(m_ctx, "result = timer.elapsed()") != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (duk_peval_string(m_ctx, "result = timer.elapsed()") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "result");
-		assertRange(duk_to_int(m_ctx, -1), 16);
+        assertRange(duk_to_int(m_ctx, -1), 16);
         duk_pop(m_ctx);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 TEST_F(TestElapsedTimer, doublecheck)
 {
-	try {
-		if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-			throw dukx_exception(m_ctx, -1);
+    try {
+        if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
-		std::this_thread::sleep_for(50ms);
+        std::this_thread::sleep_for(50ms);
 
-		if (duk_peval_string(m_ctx, "result = timer.elapsed()") != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (duk_peval_string(m_ctx, "result = timer.elapsed()") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
-		std::this_thread::sleep_for(50ms);
+        std::this_thread::sleep_for(50ms);
 
-		if (duk_peval_string(m_ctx, "result = timer.elapsed()") != 0)
-			throw dukx_exception(m_ctx, -1);
+        if (duk_peval_string(m_ctx, "result = timer.elapsed()") != 0) {
+            throw dukx_exception(m_ctx, -1);
+        }
 
         duk_get_global_string(m_ctx, "result");
-		assertRange(duk_to_int(m_ctx, -1), 100);
+        assertRange(duk_to_int(m_ctx, -1), 100);
         duk_pop(m_ctx);
-	} catch (const std::exception &ex) {
-		FAIL() << ex.what();
-	}
+    } catch (const std::exception &ex) {
+        FAIL() << ex.what();
+    }
 }
 
 int main(int argc, char **argv)
--- a/tests/libserver/dao-account/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libserver/dao-account/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -23,10 +23,10 @@
 #include <sysconfig-tests.h>
 
 #include <malikania/account.hpp>
-#include <malikania/dao-account.hpp>
+#include <malikania/account_dao.hpp>
 #include <malikania/database.hpp>
 
-using namespace malikania;
+namespace mlk = malikania;
 
 #include "test-sqlite.hpp"
 
--- a/tests/libserver/dao-account/test.hpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libserver/dao-account/test.hpp	Tue Nov 29 21:21:36 2016 +0100
@@ -1,7 +1,7 @@
 class @TEST_CLASS_NAME@ : public testing::Test {
 protected:
-    Database m_database;
-    AccountDao m_dao;
+    mlk::database m_database;
+    mlk::account_dao m_dao;
 
     std::string kind()
     {
@@ -46,13 +46,13 @@
 TEST_F(@TEST_CLASS_NAME@, create)
 {
     try {
-        Account ac;
+        mlk::account ac;
 
-        ac.setName("jean");
-        ac.setEmail("jean@christophe.fr");
-        ac.setFirstName("Jean");
-        ac.setLastName("Christophe");
-        ac.setPassword("raw");
+        ac.name = "jean";
+        ac.email = "jean@christophe.fr";
+        ac.first_name = "Jean";
+        ac.last_name = "Christophe";
+        ac.password = "raw";
 
         m_dao.create(ac);
 
@@ -66,26 +66,26 @@
 TEST_F(@TEST_CLASS_NAME@, update)
 {
     try {
-        Account ac;
+        mlk::account ac;
 
-        ac.setName("jean");
-        ac.setEmail("jean@christophe.fr");
-        ac.setFirstName("Jean");
-        ac.setLastName("Christophe");
-        ac.setPassword("raw");
+        ac.name = "jean";
+        ac.email = "jean@christophe.fr";
+        ac.first_name = "Jean";
+        ac.last_name = "Christophe";
+        ac.password = "raw";
 
         m_dao.create(ac);
 
-        ac.setEmail("benoit@christophe.fr");
-        ac.setFirstName("Benoit");
+        ac.email = "benoit@christophe.fr";
+        ac.first_name = "Benoit";
 
         m_dao.update(ac);
 
-        Account ac2 = m_dao.get(ac.id());
+        mlk::account ac2 = m_dao.get(ac.id);
 
-        ASSERT_EQ("jean", ac2.name());
-        ASSERT_EQ("benoit@christophe.fr", ac2.email());
-        ASSERT_EQ("Benoit", ac2.firstName());
+        ASSERT_EQ("jean", ac2.name);
+        ASSERT_EQ("benoit@christophe.fr", ac2.email);
+        ASSERT_EQ("Benoit", ac2.first_name);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
--- a/tests/libserver/id/main.cpp	Sun Nov 27 20:50:38 2016 +0100
+++ b/tests/libserver/id/main.cpp	Tue Nov 29 21:21:36 2016 +0100
@@ -25,64 +25,55 @@
 
 using namespace malikania;
 
-/* --------------------------------------------------------
- * Basic use case
- * -------------------------------------------------------- */
+/*
+ * Basic use case.
+ * ------------------------------------------------------------------
+ */
 
-class TestId : public testing::Test {
+class test_id : public testing::Test {
 protected:
-    IdGen<unsigned> m_idgen;
-
-public:
-    ~TestId()
-    {
-        m_idgen.reset();
-    }
+    id_generator<unsigned> m_idgen;
 };
 
-TEST_F(TestId, simple)
+TEST_F(test_id, simple)
 {
-    ASSERT_EQ(0U, m_idgen.next());
-    ASSERT_EQ(1U, m_idgen.next());
-    ASSERT_EQ(2U, m_idgen.next());
-    ASSERT_EQ(3U, m_idgen.next());
-    ASSERT_EQ(4U, m_idgen.next());
+    auto i0 = m_idgen.next();
+    auto i1 = m_idgen.next();
+    auto i2 = m_idgen.next();
+
+    ASSERT_EQ(0U, i0->value());
+    ASSERT_EQ(1U, i1->value());
+    ASSERT_EQ(2U, i2->value());
 }
 
-TEST_F(TestId, reset)
+TEST_F(test_id, release1)
 {
-    m_idgen.next();
-    m_idgen.next();
-    m_idgen.next();
-
-    m_idgen.reset();
+    auto i0 = m_idgen.next();   // 0
+    auto i1 = m_idgen.next();   // 1
+    auto i2 = m_idgen.next();   // 2
 
-    ASSERT_EQ(0U, m_idgen.next());
-}
+    i1 = nullptr;
 
-TEST_F(TestId, release1)
-{
-    m_idgen.next();    // 0
-    m_idgen.next();    // 1
-    m_idgen.next();    // 2
-    m_idgen.release(1);
+    auto n1 = m_idgen.next();
+    auto n2 = m_idgen.next();
 
     /*
      * 0 and 2 are currently in use.
      *
      * The next id must be 1 and then 3.
      */
-    ASSERT_EQ(1U, m_idgen.next());
-    ASSERT_EQ(3U, m_idgen.next());
+    ASSERT_EQ(1U, n1->value());
+    ASSERT_EQ(3U, n2->value());
 }
 
-TEST_F(TestId, release2)
+TEST_F(test_id, release2)
 {
-    m_idgen.next();    // 0
-    m_idgen.next();    // 1
-    m_idgen.next();    // 2
-    m_idgen.release(1);
-    m_idgen.release(0);
+    auto i0 = m_idgen.next();    // 0
+    auto i1 = m_idgen.next();    // 1
+    auto i2 = m_idgen.next();    // 2
+
+    i1 = nullptr;
+    i0 = nullptr;
 
     /*
      * Only 2 is in use, next id must be:
@@ -91,76 +82,50 @@
      * - 0
      * - 3
      */
-    ASSERT_EQ(1U, m_idgen.next());
-    ASSERT_EQ(0U, m_idgen.next());
-    ASSERT_EQ(3U, m_idgen.next());
-}
+    auto n1 = m_idgen.next();
+    auto n2 = m_idgen.next();
+    auto n3 = m_idgen.next();
 
-/* --------------------------------------------------------
- * Id RAII class
- * -------------------------------------------------------- */
-
-TEST(IdLocker, basic)
-{
-    IdGen<int8_t> gen;
-    Id<int8_t> id(gen);
-
-    ASSERT_EQ(0, id);
+    ASSERT_EQ(1U, n1->value());
+    ASSERT_EQ(0U, n2->value());
+    ASSERT_EQ(3U, n3->value());
 }
 
-TEST(IdLocker, two)
-{
-    IdGen<int8_t> gen;
-    Id<int8_t> id(gen);
-    Id<int8_t> id2(gen);
-
-    ASSERT_EQ(0, id);
-    ASSERT_EQ(1, id2);
-}
-
-TEST(IdLocker, already)
-{
-    IdGen<int8_t> gen;
-    Id<int8_t> id(gen, gen.next());
-
-    ASSERT_EQ(0, id);
-}
-
-/* --------------------------------------------------------
- * Limit test
- * -------------------------------------------------------- */
+/*
+ * Limit test.
+ * ------------------------------------------------------------------
+ */
 
 TEST(Limits, max)
 {
-    IdGen<int8_t> idgen;
-    int8_t last;
+    id_generator<std::int8_t> idgen;
+    std::vector<std::unique_ptr<id<std::int8_t>>> ids;
 
     try {
         for (int i = 0; i < 127; ++i) {
-            last = idgen.next();
+            ids.push_back(idgen.next());
         }
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
 
-    ASSERT_EQ(126, last);
+    ASSERT_EQ(127U, ids.size());
+    ASSERT_EQ(126, ids[126]->value());
 }
 
 TEST(Limits, fail)
 {
-    IdGen<int8_t> idgen;
-    int8_t last;
+    id_generator<std::int8_t> idgen;
+    std::vector<std::unique_ptr<id<std::int8_t>>> ids;
 
-    try {
+    ASSERT_ANY_THROW(
         for (int i = 0; i < 200; ++i) {
-            last = idgen.next();
+            ids.push_back(idgen.next());
         }
+    );
 
-        FAIL() << "Exception expected";
-    } catch (const std::exception &ex) {
-    }
-
-    ASSERT_EQ(126, last);
+    ASSERT_EQ(127U, ids.size());
+    ASSERT_EQ(126, ids[126]->value());
 }
 
 int main(int argc, char **argv)