Mercurial > malikania
changeset 98:f4d23ad4aa27
Common: refactoring class mlk::size
1. Make uniform size representation in JSON format:
{
"width": 100,
"height": 200
}
The Javascript API was using this form while an array was used in loaders.
2. Create brand new functions in util::json to parse mlk::size objects,
Updated util::json::require_(u)int as well.
3. Add new tests for mlk::size object,
4. Get rid of utilities in loader as they are in util::json instead.
line wrap: on
line diff
--- a/docs/CMakeLists.txt Fri Jun 16 12:38:04 2017 +0200 +++ b/docs/CMakeLists.txt Tue Jul 04 13:23:15 2017 +0200 @@ -28,6 +28,7 @@ ALL COMMENT "Generating documentation" SOURCES + ${docs_SOURCE_DIR}/specs/size.md ${docs_SOURCE_DIR}/specs/sprite.md )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/specs/size.md Tue Jul 04 13:23:15 2017 +0200 @@ -0,0 +1,19 @@ +# Size + +A size describe an object which has width and height dimensions. + +## JSON Specification + +### Synopsis + +````json +{ + "width": 800, + "height: 600 +} +```` + +### Properties + + - **width**: width as positive int, + - **height**: height as positive int.
--- a/examples/animation/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/animation/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -17,6 +17,7 @@ */ #include <chrono> +#include <iostream> #include <thread> #include <exception>
--- a/examples/animation/resources/sprites/margins.json Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/animation/resources/sprites/margins.json Tue Jul 04 13:23:15 2017 +0200 @@ -1,6 +1,15 @@ { - "image": "images/margins.png", - "cell": [ 32, 32 ], - "margin": [ 4, 6 ], - "space": [ 2, 3 ] + "image": "images/margins.png", + "cell": { + "width": 32, + "height": 32 + }, + "margin": { + "width": 4, + "height": 6 + }, + "space": { + "width": 2, + "height": 3 + } }
--- a/examples/font/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/font/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -17,6 +17,7 @@ */ #include <chrono> +#include <iostream> #include <thread> #include <malikania/client/loader.hpp>
--- a/examples/image/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/image/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -17,6 +17,7 @@ */ #include <chrono> +#include <iostream> #include <thread> #include <malikania/client/loader.hpp>
--- a/examples/js-animation/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/js-animation/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -17,6 +17,7 @@ */ #include <chrono> +#include <iostream> #include <thread> #include <malikania/js_client_resources_loader.hpp>
--- a/examples/js-animation/resources/sprites/margins.json Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/js-animation/resources/sprites/margins.json Tue Jul 04 13:23:15 2017 +0200 @@ -1,6 +1,15 @@ { - "image": "images/margins.png", - "cell": [ 32, 32 ], - "margin": [ 4, 6 ], - "space": [ 2, 3 ] + "image": "images/margins.png", + "cell": { + "width": 32, + "height": 32 + }, + "margin": { + "width": 4, + "height": 6 + }, + "space": { + "width": 2, + "height": 3 + } }
--- a/examples/js-font/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/js-font/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -17,6 +17,7 @@ */ #include <chrono> +#include <iostream> #include <thread> #include <malikania/js_client_resources_loader.hpp>
--- a/examples/js-image/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/js-image/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -17,6 +17,7 @@ */ #include <chrono> +#include <iostream> #include <thread> #include <malikania/js_client_resources_loader.hpp>
--- a/examples/js-sprite/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/js-sprite/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -17,6 +17,7 @@ */ #include <chrono> +#include <iostream> #include <thread> #include <malikania/js_client_resources_loader.hpp>
--- a/examples/js-sprite/resources/sprites/margins.json Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/js-sprite/resources/sprites/margins.json Tue Jul 04 13:23:15 2017 +0200 @@ -1,6 +1,15 @@ { - "image": "images/margins.png", - "cell": [ 32, 32 ], - "margin": [ 4, 6 ], - "space": [ 2, 3 ] + "image": "images/margins.png", + "cell": { + "width": 32, + "height": 32 + }, + "margin": { + "width": 4, + "height": 6 + }, + "space": { + "width": 2, + "height": 3 + } }
--- a/examples/sprite/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/sprite/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -17,6 +17,7 @@ */ #include <chrono> +#include <iostream> #include <thread> #include <exception>
--- a/examples/sprite/resources/sprites/margins.json Fri Jun 16 12:38:04 2017 +0200 +++ b/examples/sprite/resources/sprites/margins.json Tue Jul 04 13:23:15 2017 +0200 @@ -1,6 +1,15 @@ { - "image": "images/margins.png", - "cell": [ 32, 32 ], - "margin": [ 4, 6 ], - "space": [ 2, 3 ] + "image": "images/margins.png", + "cell": { + "width": 32, + "height": 32 + }, + "margin": { + "width": 4, + "height": 6 + }, + "space": { + "width": 2, + "height": 3 + } }
--- a/libclient-js/CMakeLists.txt Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient-js/CMakeLists.txt Tue Jul 04 13:23:15 2017 +0200 @@ -45,7 +45,6 @@ ${libmlk-client-js_SOURCE_DIR}/malikania/js_point.cpp ${libmlk-client-js_SOURCE_DIR}/malikania/js_rectangle.cpp ${libmlk-client-js_SOURCE_DIR}/malikania/js_sprite.cpp - ${libmlk-client-js_SOURCE_DIR}/malikania/js_size.cpp ${libmlk-client-js_SOURCE_DIR}/malikania/js_window.cpp )
--- a/libclient-js/malikania/js_image.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient-js/malikania/js_image.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -16,6 +16,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <cassert> + #include "js_client_resources_loader.hpp" #include "js_image.hpp" #include "js_point.hpp"
--- a/libclient-js/malikania/js_size.cpp Fri Jun 16 12:38:04 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * js_size.cpp -- size description (JavaScript binding) - * - * Copyright (c) 2013-2017 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 mlk { - -namespace { - -client::size parse(duk_context* ctx, duk_idx_t index, bool required, client::size ret = {}) -{ - dukx_stack_assert 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 = client::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) -{ - client::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 = client::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 - -client::size dukx_get_size(duk_context* ctx, duk_idx_t index) -{ - return parse(ctx, index, false); -} - -client::size dukx_require_size(duk_context* ctx, duk_idx_t index) -{ - return parse(ctx, index, true); -} - -client::size dukx_optional_size(duk_context* ctx, duk_idx_t index, client::size def) -{ - return parse(ctx, index, false, std::move(def)); -} - -void dukx_push_size(duk_context* ctx, const client::size& size) -{ - dukx_stack_assert sa(ctx, 1); - - duk_push_object(ctx); - dukx_put_size(ctx, size); -} - -void dukx_put_size(duk_context* ctx, const client::size& size) -{ - assert(duk_is_object(ctx, -1)); - - dukx_stack_assert 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) -{ - dukx_stack_assert 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); -} - -} // !mlk
--- a/libclient-js/malikania/js_size.hpp Fri Jun 16 12:38:04 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * js_size.hpp -- size description (JavaScript binding) - * - * Copyright (c) 2013-2017 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 <malikania/duktape.hpp> -#include <malikania/client/size.hpp> - -namespace mlk { - -/** - * 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 - */ -client::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 - */ -client::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 - */ -client::size dukx_optional_size(duk_context* ctx, duk_idx_t index, client::size def); - -/** - * Push the size as object. - * - * \param ctx the context - * \param size the size - */ -void dukx_push_size(duk_context* ctx, const client::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 client::size& size); - -void dukx_load_size(duk_context* ctx); - -} // !mlk - -#endif // !MALIKANIA_JS_SIZE_HPP
--- a/libclient/CMakeLists.txt Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/CMakeLists.txt Tue Jul 04 13:23:15 2017 +0200 @@ -37,7 +37,6 @@ ${libmlk-client_SOURCE_DIR}/malikania/client/mouse.hpp ${libmlk-client_SOURCE_DIR}/malikania/client/point.hpp ${libmlk-client_SOURCE_DIR}/malikania/client/rectangle.hpp - ${libmlk-client_SOURCE_DIR}/malikania/client/size.hpp ${libmlk-client_SOURCE_DIR}/malikania/client/sprite.hpp ${libmlk-client_SOURCE_DIR}/malikania/client/theme.hpp ${libmlk-client_SOURCE_DIR}/malikania/client/unique_layout.hpp
--- a/libclient/malikania/client/backend/sdl/font_backend.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/backend/sdl/font_backend.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -52,7 +52,7 @@ throw std::runtime_error(SDL_GetError()); } - return mlk::client::size(static_cast<unsigned>(width), static_cast<unsigned>(height)); + return mlk::size(static_cast<unsigned>(width), static_cast<unsigned>(height)); } } // !client
--- a/libclient/malikania/client/backend/sdl/font_backend.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/backend/sdl/font_backend.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -31,7 +31,6 @@ namespace client { class font; -class size; class font::backend_impl { private: @@ -45,7 +44,7 @@ return m_font.get(); } - mlk::client::size clip(const mlk::client::font& self, const std::string& text) const; + mlk::size clip(const mlk::client::font& self, const std::string& text) const; }; } // !client
--- a/libclient/malikania/client/backend/sdl/image_backend.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/backend/sdl/image_backend.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -57,7 +57,7 @@ throw std::runtime_error(SDL_GetError()); } - m_size = mlk::client::size( + m_size = mlk::size( static_cast<unsigned>(m_surface->w), static_cast<unsigned>(m_surface->h) );
--- a/libclient/malikania/client/backend/sdl/image_backend.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/backend/sdl/image_backend.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -40,7 +40,7 @@ std::unique_ptr<SDL_Surface, void (*)(SDL_Surface *)> m_surface; std::unique_ptr<SDL_Texture, void (*)(SDL_Texture *)> m_texture; - mlk::client::size m_size; + mlk::size m_size; void create_texture(window& window); @@ -52,7 +52,7 @@ return m_texture.get(); } - inline const mlk::client::size& size() const noexcept + inline const mlk::size& size() const noexcept { return m_size; }
--- a/libclient/malikania/client/button.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/button.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -41,7 +41,7 @@ w.theme().draw_button(w, *this, rect); } -mlk::client::size button::size(window& w) const noexcept +mlk::size button::size(window& w) const noexcept { return w.theme().size_button(*this); }
--- a/libclient/malikania/client/button.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/button.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -91,7 +91,7 @@ /** * \copydoc widget::size */ - mlk::client::size size(window& w) const noexcept override; + mlk::size size(window& w) const noexcept override; }; } // !client
--- a/libclient/malikania/client/font.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/font.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -32,7 +32,7 @@ font::~font() noexcept = default; -size font::clip(const std::string& text) const +mlk::size font::clip(const std::string& text) const { return m_backend->clip(*this, text); }
--- a/libclient/malikania/client/font.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/font.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -100,7 +100,7 @@ * \param text the text to clip * \return the required size */ - mlk::client::size clip(const std::string& text) const; + mlk::size clip(const std::string& text) const; /** * Default move assignment operator.
--- a/libclient/malikania/client/frame.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/frame.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -27,9 +27,9 @@ namespace client { -mlk::client::size frame::size(window &win) +mlk::size frame::size(window &win) { - return m_layout ? m_layout->size(win) : mlk::client::size(); + return m_layout ? m_layout->size(win) : mlk::size(); } void frame::draw(window& win)
--- a/libclient/malikania/client/frame.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/frame.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -44,7 +44,7 @@ private: std::shared_ptr<mlk::client::layout> m_layout; mlk::client::point m_position; - mlk::client::size m_padding{10, 10}; + mlk::size m_padding{10, 10}; public: /** @@ -117,7 +117,7 @@ * * \return the frame padding */ - inline const mlk::client::size& padding() const noexcept + inline const mlk::size& padding() const noexcept { return m_padding; } @@ -127,7 +127,7 @@ * * \return the padding */ - inline mlk::client::size& padding() noexcept + inline mlk::size& padding() noexcept { return m_padding; } @@ -137,7 +137,7 @@ * * \param padding the padding */ - inline void set_padding(mlk::client::size padding) noexcept + inline void set_padding(mlk::size padding) noexcept { m_padding = std::move(padding); } @@ -151,7 +151,7 @@ * \param win the window * \return the size required to draw this frame */ - virtual mlk::client::size size(window& win); + virtual mlk::size size(window& win); /** * Draw the frame and its content.
--- a/libclient/malikania/client/image.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/image.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -31,7 +31,7 @@ image::~image() noexcept = default; -const mlk::client::size& image::size() const noexcept +const mlk::size& image::size() const noexcept { return m_backend->size(); }
--- a/libclient/malikania/client/image.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/image.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -92,7 +92,7 @@ * * \return the size */ - const mlk::client::size& size() const noexcept; + const mlk::size& size() const noexcept; /** * Draw the image to the window.
--- a/libclient/malikania/client/label.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/label.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -35,7 +35,7 @@ w.theme().draw_label(w, *this, rect); } -mlk::client::size label::size(window& w) const noexcept +mlk::size label::size(window& w) const noexcept { return w.theme().size_label(*this); }
--- a/libclient/malikania/client/label.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/label.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -87,7 +87,7 @@ /** * \copydoc widget::size */ - mlk::client::size size(window& w) const noexcept override; + mlk::size size(window& w) const noexcept override; }; } // !client
--- a/libclient/malikania/client/layout.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/layout.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -25,11 +25,12 @@ namespace mlk { +class size; + namespace client { class mouse_click_event; class rectangle; -class size; class window; /** @@ -64,7 +65,7 @@ /** * Return the required minimum size to draw the whole layout. */ - virtual mlk::client::size size(window& win) const = 0; + virtual mlk::size size(window& win) const = 0; /** * Draw the layout content at the given position.
--- a/libclient/malikania/client/loader.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/loader.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -16,62 +16,23 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <boost/format.hpp> - -#include <cassert> +#include <json.hpp> #include "animation.hpp" +#include "font.hpp" +#include "image.hpp" #include "loader.hpp" +#include "locator.hpp" #include "size.hpp" #include "sprite.hpp" #include "util.hpp" -using boost::str; -using boost::format; - using namespace nlohmann; namespace mlk { namespace client { -size 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 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 loader::load_font(const std::string& id, unsigned size) { return font(locator().read(id), size); @@ -91,11 +52,11 @@ } 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") + load_image(util::json::require_string(value, "/image"_json_pointer)), + util::json::require_size(value, "/cell"_json_pointer), + util::json::get_size(value, "/size"_json_pointer), + util::json::get_size(value, "/space"_json_pointer), + util::json::get_size(value, "/margin"_json_pointer) ); } @@ -107,7 +68,7 @@ throw std::runtime_error("not a JSON object"); } - auto sprite = load_sprite(require_string(id, value, "sprite")); + auto sprite = load_sprite(util::json::require_string(value, "/sprite"_json_pointer)); // Load all frames. auto property = util::json::require_array(value, "/frames"_json_pointer);
--- a/libclient/malikania/client/loader.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/loader.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -26,50 +26,22 @@ #include <malikania/loader.hpp> -#include "animation.hpp" -#include "font.hpp" -#include "image.hpp" -#include "size.hpp" -#include "sprite.hpp" +#include <string> namespace mlk { namespace client { +class animation; +class font; +class image; +class size; +class sprite; + /** * \brief Load client resources. */ class loader : public mlk::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.
--- a/libclient/malikania/client/size.hpp Fri Jun 16 12:38:04 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - * size.hpp -- size description - * - * Copyright (c) 2013-2017 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_SIZE_HPP -#define MALIKANIA_CLIENT_SIZE_HPP - -namespace mlk { - -namespace client { - -/** - * \brief size description. - */ -class size { -private: - unsigned m_width; - unsigned m_height; - -public: - /** - * Constructor. - * - * \param width the size width - * \param height the size height - */ - inline size(unsigned width = 0, unsigned height = 0) noexcept - : m_width(width) - , m_height(height) - { - } - - /** - * Get the width. - * - * \return the width - */ - inline unsigned width() const noexcept - { - return m_width; - } - - /** - * Get the height. - * - * \return the height - */ - inline unsigned height() const noexcept - { - return m_height; - } - - /** - * Check if the size is 0, 0. - * - * \return true if height and width are 0 - */ - inline bool is_null() const noexcept - { - return m_height == 0 && m_width == 0; - } -}; - -/** - * Compare equality. - * - * \param s1 the first size - * \param s2 the second size - * \return true if they equal - */ -inline bool operator==(const size& s1, const size& s2) noexcept -{ - return s1.width() == s2.width() && s1.height() == s2.height(); -} - -/** - * Compare equality. - * - * \param s1 the first size - * \param s2 the second size - * \return false if they equal - */ -inline bool operator!=(const size& s1, const size& s2) noexcept -{ - return !(s1 == s2); -} - -} // !client - -} // !mlk - -#endif // !MALIKANIA_CLIENT_SIZE_HPP
--- a/libclient/malikania/client/sprite.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/sprite.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -25,10 +25,10 @@ namespace client { sprite::sprite(mlk::client::image image, - mlk::client::size cell, - mlk::client::size size, - mlk::client::size space, - mlk::client::size margin) noexcept + mlk::size cell, + mlk::size size, + mlk::size space, + mlk::size margin) noexcept : m_image(std::move(image)) , m_cell(std::move(cell)) , m_margin(std::move(margin))
--- a/libclient/malikania/client/sprite.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/sprite.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -36,10 +36,10 @@ class sprite { private: mlk::client::image m_image; - mlk::client::size m_cell; - mlk::client::size m_margin; - mlk::client::size m_space; - mlk::client::size m_size; + mlk::size m_cell; + mlk::size m_margin; + mlk::size m_space; + mlk::size m_size; unsigned m_rows; unsigned m_columns; @@ -56,10 +56,10 @@ * \param size the sprite size (if 0, taken from the image) */ sprite(mlk::client::image image, - mlk::client::size cell, - mlk::client::size margin = { 0, 0 }, - mlk::client::size space = { 0, 0 }, - mlk::client::size size = { 0, 0 }) noexcept; + mlk::size cell, + mlk::size margin = { 0, 0 }, + mlk::size space = { 0, 0 }, + mlk::size size = { 0, 0 }) noexcept; /** * Get the underlying image. @@ -86,7 +86,7 @@ * * \return the cell size */ - inline const size& cell() const noexcept + inline const mlk::size& cell() const noexcept { return m_cell; } @@ -96,7 +96,7 @@ * * \return the margin size */ - inline const size& margin() noexcept + inline const mlk::size& margin() noexcept { return m_margin; } @@ -106,7 +106,7 @@ * * \return the space size */ - inline const size& space() const noexcept + inline const mlk::size& space() const noexcept { return m_space; }
--- a/libclient/malikania/client/unique_layout.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/unique_layout.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -43,9 +43,9 @@ } } -mlk::client::size unique_layout::size(window& win) const +mlk::size unique_layout::size(window& win) const { - return m_widget ? m_widget->size(win) : mlk::client::size(); + return m_widget ? m_widget->size(win) : mlk::size(); } void unique_layout::draw(window& win, const rectangle& dst)
--- a/libclient/malikania/client/unique_layout.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/unique_layout.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -92,7 +92,7 @@ /** * \copydoc layout::size */ - mlk::client::size size(window& win) const override; + mlk::size size(window& win) const override; /** * \copydoc layout::draw
--- a/libclient/malikania/client/widget.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/widget.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -43,7 +43,7 @@ void widget::draw(window& w, const point& pos) { - mlk::client::size sz = size(w); + mlk::size sz = size(w); mlk::client::rectangle rect{ pos.x(), pos.y(), sz.width(), sz.height()
--- a/libclient/malikania/client/widget.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libclient/malikania/client/widget.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -26,13 +26,14 @@ namespace mlk { +class size; + namespace client { class key_event; class mouse_click_event; class point; class rectangle; -class size; class window; /** @@ -97,7 +98,7 @@ * * \return the widget size */ - virtual mlk::client::size size(window& w) const noexcept = 0; + virtual mlk::size size(window& w) const noexcept = 0; }; } // !client
--- a/libcommon-js/CMakeLists.txt Fri Jun 16 12:38:04 2017 +0200 +++ b/libcommon-js/CMakeLists.txt Tue Jul 04 13:23:15 2017 +0200 @@ -23,12 +23,14 @@ ${libmlk-common-js_SOURCE_DIR}/malikania/duktape.hpp ${libmlk-common-js_SOURCE_DIR}/malikania/js_elapsed_timer.hpp ${libmlk-common-js_SOURCE_DIR}/malikania/js_resources_loader.hpp + ${libmlk-common-js_SOURCE_DIR}/malikania/js_size.hpp ) set( SOURCES ${libmlk-common-js_SOURCE_DIR}/malikania/js_elapsed_timer.cpp ${libmlk-common-js_SOURCE_DIR}/malikania/js_resources_loader.cpp + ${libmlk-common-js_SOURCE_DIR}/malikania/js_size.cpp ) malikania_define_library(
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcommon-js/malikania/js_size.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -0,0 +1,146 @@ +/* + * js_size.cpp -- size description (JavaScript binding) + * + * Copyright (c) 2013-2017 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 mlk { + +namespace { + +size parse(duk_context* ctx, duk_idx_t index, bool required, size ret = {}) +{ + dukx_stack_assert 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) +{ + dukx_stack_assert 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)); + + dukx_stack_assert 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) +{ + dukx_stack_assert 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); +} + +} // !mlk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcommon-js/malikania/js_size.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -0,0 +1,93 @@ +/* + * js_size.hpp -- size description (JavaScript binding) + * + * Copyright (c) 2013-2017 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 <malikania/duktape.hpp> +#include <malikania/size.hpp> + +namespace mlk { + +/** + * 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); + +} // !mlk + +#endif // !MALIKANIA_JS_SIZE_HPP
--- a/libcommon/CMakeLists.txt Fri Jun 16 12:38:04 2017 +0200 +++ b/libcommon/CMakeLists.txt Tue Jul 04 13:23:15 2017 +0200 @@ -24,6 +24,7 @@ ${libmlk-common_SOURCE_DIR}/malikania/id.hpp ${libmlk-common_SOURCE_DIR}/malikania/loader.hpp ${libmlk-common_SOURCE_DIR}/malikania/locator.hpp + ${libmlk-common_SOURCE_DIR}/malikania/size.hpp ${libmlk-common_SOURCE_DIR}/malikania/util.hpp )
--- a/libcommon/malikania/loader.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libcommon/malikania/loader.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -16,69 +16,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <boost/format.hpp> - -#include <cassert> - #include "game.hpp" #include "loader.hpp" #include "locator.hpp" +#include "util.hpp" namespace mlk { -void 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 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; -} - loader::loader(mlk::locator& locator) : m_locator(locator) { @@ -92,15 +36,9 @@ 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"], + return game{util::json::require_string(value, "/name"_json_pointer), + util::json::require_string(value, "/version"_json_pointer), + util::json::require_string(value, "/requires"_json_pointer), value.count("license") > 0 ? value["license"] : "", value.count("author") > 0 ? value["author"] : ""}; }
--- a/libcommon/malikania/loader.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libcommon/malikania/loader.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -19,16 +19,10 @@ #ifndef MALIKANIA_LOADER_HPP #define MALIKANIA_LOADER_HPP -#include <string> -#include <unordered_map> - -#include <json.hpp> - -#include "locator.hpp" - namespace mlk { class game; +class locator; /** * \brief Open resources files using a locator. @@ -42,41 +36,6 @@ private: mlk::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.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcommon/malikania/size.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -0,0 +1,118 @@ +/* + * size.hpp -- size description + * + * Copyright (c) 2013-2017 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_SIZE_HPP +#define MALIKANIA_SIZE_HPP + +#include <ostream> + +namespace mlk { + +/** + * \brief size description. + */ +class size { +private: + unsigned m_width; + unsigned m_height; + +public: + /** + * Constructor. + * + * \param width the size width + * \param height the size height + */ + inline size(unsigned width = 0, unsigned height = 0) noexcept + : m_width(width) + , m_height(height) + { + } + + /** + * Get the width. + * + * \return the width + */ + inline unsigned width() const noexcept + { + return m_width; + } + + /** + * Get the height. + * + * \return the height + */ + inline unsigned height() const noexcept + { + return m_height; + } + + /** + * Check if the size is 0, 0. + * + * \return true if height and width are 0 + */ + inline bool is_null() const noexcept + { + return m_height == 0 && m_width == 0; + } +}; + +/** + * Compare equality. + * + * \param s1 the first size + * \param s2 the second size + * \return true if they equal + */ +inline bool operator==(const size& s1, const size& s2) noexcept +{ + return s1.width() == s2.width() && s1.height() == s2.height(); +} + +/** + * Compare equality. + * + * \param s1 the first size + * \param s2 the second size + * \return false if they equal + */ +inline bool operator!=(const size& s1, const size& s2) noexcept +{ + return !(s1 == s2); +} + +/** + * Prints the size object. + * + * \param out the output + * \param size the size object + * \return out + */ +inline std::ostream& operator<<(std::ostream& out, const size& size) +{ + out << "{" << size.width() << ", " << size.height() << "}"; + + return out; +} + +} // !mlk + +#endif // !MALIKANIA_SIZE_HPP
--- a/libcommon/malikania/util.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libcommon/malikania/util.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -17,6 +17,7 @@ */ #include <cassert> +#include <climits> #include <string> #include <stdexcept> @@ -58,6 +59,7 @@ #include <boost/filesystem.hpp> #include "util.hpp" +#include "size.hpp" namespace { @@ -297,6 +299,26 @@ return value; } +nlohmann::json get(const nlohmann::json& object, + const nlohmann::json::json_pointer& pointer, + const nlohmann::json::value_t expected, + const nlohmann::json def) +{ + assert(object.is_object()); + + nlohmann::json value; + + try { + value = object.at(pointer); + } catch (...) { + } + + if (value.type() != expected) + value = def; + + return value; +} + nlohmann::json require_array(const nlohmann::json& object, const nlohmann::json::json_pointer& pointer) { @@ -312,7 +334,19 @@ int require_int(const nlohmann::json& object, const nlohmann::json::json_pointer& pointer) { - return require(object, pointer, nlohmann::json::value_t::number_integer); + nlohmann::json v; + + try { + v = object.at(pointer); + + if (v.is_number_integer()) + return v.get<int>(); + else if (v.is_number_unsigned() && v.get<unsigned>() <= static_cast<unsigned>(INT_MAX)) + return static_cast<int>(v.get<unsigned>()); + } catch (...) { + } + + throw property_error(object, pointer, v.type(), nlohmann::json::value_t::number_integer); } nlohmann::json require_object(const nlohmann::json& object, @@ -330,7 +364,76 @@ unsigned require_uint(const nlohmann::json& object, const nlohmann::json::json_pointer& pointer) { - return require(object, pointer, nlohmann::json::value_t::number_unsigned); + nlohmann::json v; + + try { + v = object.at(pointer); + + if (v.is_number_unsigned()) + return v.get<unsigned>(); + else if (v.is_number_integer() && v.get<int>() >= 0) + return static_cast<unsigned>(v.get<int>()); + } catch (...) { + } + + throw property_error(object, pointer, v.type(), nlohmann::json::value_t::number_unsigned); +} + +mlk::size require_size(const nlohmann::json& object, + const nlohmann::json::json_pointer& index) +{ + using pointer = nlohmann::json::json_pointer; + + return { + require_uint(object, pointer(index.to_string() + "/width")), + require_uint(object, pointer(index.to_string() + "/height")) + }; +} + +int get_int(const nlohmann::json &object, + const nlohmann::json::json_pointer &pointer, + int value) noexcept +{ + try { + auto v = object.at(pointer); + + if (v.is_number_integer()) + value = v.get<int>(); + else if (v.is_number_unsigned() && v.get<unsigned>() <= static_cast<unsigned>(INT_MAX)) + value = static_cast<int>(v.get<unsigned>()); + } catch (...) { + } + + return value; +} + +int get_uint(const nlohmann::json &object, + const nlohmann::json::json_pointer& pointer, + unsigned value) noexcept +{ + try { + auto v = object.at(pointer); + + if (v.is_number_unsigned()) + value = v.get<unsigned>(); + else if (v.is_number_integer() && v.get<int>() >= 0) + value = static_cast<unsigned>(v.get<int>()); + } catch (...) { + } + + return value; +} + +mlk::size get_size(const nlohmann::json& object, + const nlohmann::json::json_pointer& pointer, + const mlk::size& def) noexcept +{ + using json_pointer = nlohmann::json::json_pointer; + + return { + get_uint(object, json_pointer(pointer.to_string() + "/width"), def.width()), + get_uint(object, json_pointer(pointer.to_string() + "/height"), def.height()) + }; } } // !json
--- a/libcommon/malikania/util.hpp Fri Jun 16 12:38:04 2017 +0200 +++ b/libcommon/malikania/util.hpp Tue Jul 04 13:23:15 2017 +0200 @@ -30,6 +30,7 @@ #include <vector> #include "json.hpp" +#include "size.hpp" namespace mlk { @@ -268,6 +269,59 @@ unsigned require_uint(const nlohmann::json& object, const nlohmann::json::json_pointer& pointer); +/** + * Require a size object at the given pointer. + * + * \pre object.is_object + * \param object the json object + * \param pointer the pointer to the property + * \return the value + * \throw property_error on errors + */ +mlk::size require_size(const nlohmann::json& object, + const nlohmann::json::json_pointer& pointer); + +/** + * Get an integer at the given pointer or default value if not present or + * invalid. + * + * \pre object.is_object + * \param object the json object + * \param pointer the pointer to the property + * \param def the default value + * \return an integer + */ +int get_int(const nlohmann::json& object, + const nlohmann::json::json_pointer& pointer, + int def = 0) noexcept; + +/** + * Get an unsigned integer at the given pointer or default value if not present + * or invalid. + * + * \pre object.is_object + * \param object the json object + * \param pointer the pointer to the property + * \param def the default value + * \return an integer + */ +int get_uint(const nlohmann::json& object, + const nlohmann::json::json_pointer& pointer, + unsigned def = 0) noexcept; + +/** + * Get a size object at the given pointer or a default value. + * + * \pre object.is_object + * \param object the json object + * \param pointer the pointer to the property + * \param def the default value to return in case of error + * \return a size or a default value + */ +mlk::size get_size(const nlohmann::json& object, + const nlohmann::json::json_pointer& pointer, + const mlk::size& def = {}) noexcept; + } // !json } // !util
--- a/tests/libclient/CMakeLists.txt Fri Jun 16 12:38:04 2017 +0200 +++ b/tests/libclient/CMakeLists.txt Tue Jul 04 13:23:15 2017 +0200 @@ -20,11 +20,9 @@ add_subdirectory(line) add_subdirectory(point) add_subdirectory(rectangle) -add_subdirectory(size) # JavaScript bindings add_subdirectory(js-color) add_subdirectory(js-line) add_subdirectory(js-point) add_subdirectory(js-rectangle) -add_subdirectory(js-size)
--- a/tests/libclient/js-size/CMakeLists.txt Fri Jun 16 12:38:04 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -# -# CMakeLists.txt -- CMake build system for malikania -# -# Copyright (c) 2013-2017 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. -# - -malikania_create_test( - NAME js-size - LIBRARIES libmlk-client-js - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp -)
--- a/tests/libclient/js-size/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,406 +0,0 @@ -/* - * main.cpp -- test Size (JavaScript binding) - * - * Copyright (c) 2013-2017 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. - */ - -#define BOOST_TEST_MODULE "Javascript Size" -#include <boost/test/unit_test.hpp> - -#include <malikania/js_size.hpp> - -using namespace mlk; - -class test_size { -protected: - dukx_context m_ctx; - -public: - test_size() - { - duk_push_object(m_ctx); - duk_put_global_string(m_ctx, "Malikania"); - dukx_load_size(m_ctx); - } -}; - -BOOST_FIXTURE_TEST_SUITE(test_size_suite, test_size) - -/* - * Valid constructors. - * ------------------------------------------------------------------ - */ - -BOOST_AUTO_TEST_SUITE(constructors) - -BOOST_AUTO_TEST_CASE(constructor_default) -{ - try { - auto ret = duk_peval_string(m_ctx, - "s = Malikania.Size();" - "w = s.width;" - "h = s.height;" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "w"); - BOOST_REQUIRE_EQUAL(0U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "h"); - BOOST_REQUIRE_EQUAL(0U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_CASE(constructor_2_args) -{ - try { - auto ret = duk_peval_string(m_ctx, - "s = Malikania.Size(100, 200);" - "w = s.width;" - "h = s.height;" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "w"); - BOOST_REQUIRE_EQUAL(100U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "h"); - BOOST_REQUIRE_EQUAL(200U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_CASE(constructor_object) -{ - try { - auto ret = duk_peval_string(m_ctx, - "s = Malikania.Size({ width: 100, height: 200 });" - "w = s.width;" - "h = s.height;" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "w"); - BOOST_REQUIRE_EQUAL(100U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "h"); - BOOST_REQUIRE_EQUAL(200U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_CASE(constructor_new) -{ - try { - auto ret = duk_peval_string(m_ctx, - "s = new Malikania.Size({ width: 100, height: 200 });" - "w = s.width;" - "h = s.height;" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "w"); - BOOST_REQUIRE_EQUAL(100U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "h"); - BOOST_REQUIRE_EQUAL(200U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_SUITE_END() - -/* - * Invalid constructors. - * ------------------------------------------------------------------ - */ - -BOOST_AUTO_TEST_SUITE(invalid_constructors) - -BOOST_AUTO_TEST_CASE(constructor_arg_1) -{ - try { - auto ret = duk_peval_string(m_ctx, - "try {" - " Malikania.Size(null);" - "} catch (e) {" - " name = e.name;" - " correct = (e instanceof TypeError);" - "}" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "name"); - BOOST_REQUIRE_EQUAL("TypeError", duk_to_string(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "correct"); - BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_CASE(constructor_range_1) -{ - try { - auto ret = duk_peval_string(m_ctx, - "try {" - " Malikania.Size(-1, 200);" - "} catch (e) {" - " name = e.name;" - " correct = (e instanceof RangeError);" - "}" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "name"); - BOOST_REQUIRE_EQUAL("RangeError", duk_to_string(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "correct"); - BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_CASE(constructor_range_2) -{ - try { - auto ret = duk_peval_string(m_ctx, - "try {" - " Malikania.Size(100, -1);" - "} catch (e) {" - " name = e.name;" - " correct = (e instanceof RangeError);" - "}" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "name"); - BOOST_REQUIRE_EQUAL("RangeError", duk_to_string(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "correct"); - BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_CASE(constructor_range_3) -{ - try { - auto ret = duk_peval_string(m_ctx, - "try {" - " Malikania.Size({ width: -1, height: 200 });" - "} catch (e) {" - " name = e.name;" - " correct = (e instanceof RangeError);" - "}" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "name"); - BOOST_REQUIRE_EQUAL("RangeError", duk_to_string(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "correct"); - BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_CASE(constructor_range_4) -{ - try { - auto ret = duk_peval_string(m_ctx, - "try {" - " Malikania.Size({ width: 100, height: -1 });" - "} catch (e) {" - " name = e.name;" - " correct = (e instanceof RangeError);" - "}" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "name"); - BOOST_REQUIRE_EQUAL("RangeError", duk_to_string(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "correct"); - BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_SUITE_END() - -/* - * Require. - * ------------------------------------------------------------------ - */ - -BOOST_AUTO_TEST_SUITE(require) - -BOOST_AUTO_TEST_CASE(success) -{ - try { - duk_push_c_function(m_ctx, [] (auto ctx) { - auto size = dukx_require_size(ctx, 0); - - duk_push_uint(ctx, size.width()); - duk_put_global_string(ctx, "w"); - duk_push_uint(ctx, size.height()); - duk_put_global_string(ctx, "h"); - - return 0; - }, 1); - duk_put_global_string(m_ctx, "build"); - - auto ret = duk_peval_string(m_ctx, "build({ width: 100, height: 200 });"); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "w"); - BOOST_REQUIRE_EQUAL(100U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "h"); - BOOST_REQUIRE_EQUAL(200U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_CASE(fail) -{ - try { - duk_push_c_function(m_ctx, [] (auto ctx) { - dukx_require_size(ctx, 0); - - return 0; - }, 1); - duk_put_global_string(m_ctx, "build"); - - auto ret = duk_peval_string(m_ctx, - "try {" - " build({});" - "} catch (e) {" - " name = e.name;" - " correct = (e instanceof Error);" - "}" - ); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "name"); - BOOST_REQUIRE_EQUAL("Error", duk_to_string(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "correct"); - BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_SUITE_END() - -/* - * Get. - * ------------------------------------------------------------------ - */ - -BOOST_AUTO_TEST_SUITE(get) - -BOOST_AUTO_TEST_CASE(adjust_all) -{ - try { - duk_push_c_function(m_ctx, [] (auto ctx) { - auto size = dukx_get_size(ctx, 0); - - duk_push_uint(ctx, size.width()); - duk_put_global_string(ctx, "w"); - duk_push_uint(ctx, size.height()); - duk_put_global_string(ctx, "h"); - - return 0; - }, 1); - duk_put_global_string(m_ctx, "build"); - - auto ret = duk_peval_string(m_ctx, "build({});"); - - if (ret != 0) { - throw dukx_get_exception(m_ctx, -1); - } - - duk_get_global_string(m_ctx, "w"); - BOOST_REQUIRE_EQUAL(0U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - duk_get_global_string(m_ctx, "h"); - BOOST_REQUIRE_EQUAL(0U, duk_to_uint(m_ctx, -1)); - duk_pop(m_ctx); - } catch (const std::exception &ex) { - BOOST_FAIL(ex.what()); - } -} - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END()
--- a/tests/libclient/size/CMakeLists.txt Fri Jun 16 12:38:04 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -# -# CMakeLists.txt -- CMake build system for malikania -# -# Copyright (c) 2013-2017 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. -# - -malikania_create_test( - NAME size - LIBRARIES libmlk-client - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp -)
--- a/tests/libclient/size/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * main.cpp -- test mlk::client::size - * - * Copyright (c) 2013-2017 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. - */ - -#define BOOST_TEST_MODULE "Size" -#include <boost/test/unit_test.hpp> - -#include <malikania/client/size.hpp> - -namespace mlk { - -namespace client { - -std::ostream& operator<<(std::ostream& out, const size& size) -{ - out << "{" << size.width() << ", " << size.height() << "}"; - - return out; -} - -} // !client - -} // !mlk - -BOOST_AUTO_TEST_CASE(none) -{ - mlk::client::size size; - - BOOST_REQUIRE_EQUAL(0U, size.width()); - BOOST_REQUIRE_EQUAL(0U, size.height()); -} - -BOOST_AUTO_TEST_CASE(null) -{ - BOOST_REQUIRE(mlk::client::size().is_null()); - BOOST_REQUIRE(!mlk::client::size(0, 10).is_null()); - BOOST_REQUIRE(!mlk::client::size(10, 0).is_null()); -} - -BOOST_AUTO_TEST_CASE(standard) -{ - mlk::client::size size(10, 20); - - BOOST_REQUIRE_EQUAL(10U, size.width()); - BOOST_REQUIRE_EQUAL(20U, size.height()); -} - -BOOST_AUTO_TEST_CASE(operator_eq) -{ - mlk::client::size size1, size2; - - BOOST_REQUIRE_EQUAL(size1, size2); -} - -BOOST_AUTO_TEST_CASE(operator_eq_1) -{ - mlk::client::size size1(10, 20); - mlk::client::size size2(10, 20); - - BOOST_REQUIRE_EQUAL(size1, size2); -} - -BOOST_AUTO_TEST_CASE(operator_neq) -{ - BOOST_REQUIRE_NE(mlk::client::size(10), mlk::client::size(20)); - BOOST_REQUIRE_NE(mlk::client::size(10, 10), mlk::client::size(10, 20)); -}
--- a/tests/libcommon/CMakeLists.txt Fri Jun 16 12:38:04 2017 +0200 +++ b/tests/libcommon/CMakeLists.txt Tue Jul 04 13:23:15 2017 +0200 @@ -17,4 +17,8 @@ # add_subdirectory(util) +add_subdirectory(size) + +# JavaScript bindings add_subdirectory(js-elapsed-timer) +add_subdirectory(js-size)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/libcommon/js-size/CMakeLists.txt Tue Jul 04 13:23:15 2017 +0200 @@ -0,0 +1,23 @@ +# +# CMakeLists.txt -- CMake build system for malikania +# +# Copyright (c) 2013-2017 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. +# + +malikania_create_test( + NAME js-size + LIBRARIES libmlk-common-js + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/libcommon/js-size/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -0,0 +1,406 @@ +/* + * main.cpp -- test Size (JavaScript binding) + * + * Copyright (c) 2013-2017 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. + */ + +#define BOOST_TEST_MODULE "Javascript Size" +#include <boost/test/unit_test.hpp> + +#include <malikania/js_size.hpp> + +using namespace mlk; + +class test_size { +protected: + dukx_context m_ctx; + +public: + test_size() + { + duk_push_object(m_ctx); + duk_put_global_string(m_ctx, "Malikania"); + dukx_load_size(m_ctx); + } +}; + +BOOST_FIXTURE_TEST_SUITE(test_size_suite, test_size) + +/* + * Valid constructors. + * ------------------------------------------------------------------ + */ + +BOOST_AUTO_TEST_SUITE(constructors) + +BOOST_AUTO_TEST_CASE(constructor_default) +{ + try { + auto ret = duk_peval_string(m_ctx, + "s = Malikania.Size();" + "w = s.width;" + "h = s.height;" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "w"); + BOOST_REQUIRE_EQUAL(0U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "h"); + BOOST_REQUIRE_EQUAL(0U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_CASE(constructor_2_args) +{ + try { + auto ret = duk_peval_string(m_ctx, + "s = Malikania.Size(100, 200);" + "w = s.width;" + "h = s.height;" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "w"); + BOOST_REQUIRE_EQUAL(100U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "h"); + BOOST_REQUIRE_EQUAL(200U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_CASE(constructor_object) +{ + try { + auto ret = duk_peval_string(m_ctx, + "s = Malikania.Size({ width: 100, height: 200 });" + "w = s.width;" + "h = s.height;" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "w"); + BOOST_REQUIRE_EQUAL(100U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "h"); + BOOST_REQUIRE_EQUAL(200U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_CASE(constructor_new) +{ + try { + auto ret = duk_peval_string(m_ctx, + "s = new Malikania.Size({ width: 100, height: 200 });" + "w = s.width;" + "h = s.height;" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "w"); + BOOST_REQUIRE_EQUAL(100U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "h"); + BOOST_REQUIRE_EQUAL(200U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_SUITE_END() + +/* + * Invalid constructors. + * ------------------------------------------------------------------ + */ + +BOOST_AUTO_TEST_SUITE(invalid_constructors) + +BOOST_AUTO_TEST_CASE(constructor_arg_1) +{ + try { + auto ret = duk_peval_string(m_ctx, + "try {" + " Malikania.Size(null);" + "} catch (e) {" + " name = e.name;" + " correct = (e instanceof TypeError);" + "}" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "name"); + BOOST_REQUIRE_EQUAL("TypeError", duk_to_string(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "correct"); + BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_CASE(constructor_range_1) +{ + try { + auto ret = duk_peval_string(m_ctx, + "try {" + " Malikania.Size(-1, 200);" + "} catch (e) {" + " name = e.name;" + " correct = (e instanceof RangeError);" + "}" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "name"); + BOOST_REQUIRE_EQUAL("RangeError", duk_to_string(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "correct"); + BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_CASE(constructor_range_2) +{ + try { + auto ret = duk_peval_string(m_ctx, + "try {" + " Malikania.Size(100, -1);" + "} catch (e) {" + " name = e.name;" + " correct = (e instanceof RangeError);" + "}" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "name"); + BOOST_REQUIRE_EQUAL("RangeError", duk_to_string(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "correct"); + BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_CASE(constructor_range_3) +{ + try { + auto ret = duk_peval_string(m_ctx, + "try {" + " Malikania.Size({ width: -1, height: 200 });" + "} catch (e) {" + " name = e.name;" + " correct = (e instanceof RangeError);" + "}" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "name"); + BOOST_REQUIRE_EQUAL("RangeError", duk_to_string(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "correct"); + BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_CASE(constructor_range_4) +{ + try { + auto ret = duk_peval_string(m_ctx, + "try {" + " Malikania.Size({ width: 100, height: -1 });" + "} catch (e) {" + " name = e.name;" + " correct = (e instanceof RangeError);" + "}" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "name"); + BOOST_REQUIRE_EQUAL("RangeError", duk_to_string(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "correct"); + BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_SUITE_END() + +/* + * Require. + * ------------------------------------------------------------------ + */ + +BOOST_AUTO_TEST_SUITE(require) + +BOOST_AUTO_TEST_CASE(success) +{ + try { + duk_push_c_function(m_ctx, [] (auto ctx) { + auto size = dukx_require_size(ctx, 0); + + duk_push_uint(ctx, size.width()); + duk_put_global_string(ctx, "w"); + duk_push_uint(ctx, size.height()); + duk_put_global_string(ctx, "h"); + + return 0; + }, 1); + duk_put_global_string(m_ctx, "build"); + + auto ret = duk_peval_string(m_ctx, "build({ width: 100, height: 200 });"); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "w"); + BOOST_REQUIRE_EQUAL(100U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "h"); + BOOST_REQUIRE_EQUAL(200U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_CASE(fail) +{ + try { + duk_push_c_function(m_ctx, [] (auto ctx) { + dukx_require_size(ctx, 0); + + return 0; + }, 1); + duk_put_global_string(m_ctx, "build"); + + auto ret = duk_peval_string(m_ctx, + "try {" + " build({});" + "} catch (e) {" + " name = e.name;" + " correct = (e instanceof Error);" + "}" + ); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "name"); + BOOST_REQUIRE_EQUAL("Error", duk_to_string(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "correct"); + BOOST_REQUIRE(duk_to_boolean(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_SUITE_END() + +/* + * Get. + * ------------------------------------------------------------------ + */ + +BOOST_AUTO_TEST_SUITE(get) + +BOOST_AUTO_TEST_CASE(adjust_all) +{ + try { + duk_push_c_function(m_ctx, [] (auto ctx) { + auto size = dukx_get_size(ctx, 0); + + duk_push_uint(ctx, size.width()); + duk_put_global_string(ctx, "w"); + duk_push_uint(ctx, size.height()); + duk_put_global_string(ctx, "h"); + + return 0; + }, 1); + duk_put_global_string(m_ctx, "build"); + + auto ret = duk_peval_string(m_ctx, "build({});"); + + if (ret != 0) { + throw dukx_get_exception(m_ctx, -1); + } + + duk_get_global_string(m_ctx, "w"); + BOOST_REQUIRE_EQUAL(0U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + duk_get_global_string(m_ctx, "h"); + BOOST_REQUIRE_EQUAL(0U, duk_to_uint(m_ctx, -1)); + duk_pop(m_ctx); + } catch (const std::exception &ex) { + BOOST_FAIL(ex.what()); + } +} + +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE_END()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/libcommon/size/CMakeLists.txt Tue Jul 04 13:23:15 2017 +0200 @@ -0,0 +1,23 @@ +# +# CMakeLists.txt -- CMake build system for malikania +# +# Copyright (c) 2013-2017 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. +# + +malikania_create_test( + NAME size + LIBRARIES libmlk-common + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/libcommon/size/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -0,0 +1,66 @@ +/* + * main.cpp -- test mlk::size + * + * Copyright (c) 2013-2017 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. + */ + +#define BOOST_TEST_MODULE "Size" +#include <boost/test/unit_test.hpp> + +#include <malikania/size.hpp> + +BOOST_AUTO_TEST_CASE(none) +{ + mlk::size size; + + BOOST_REQUIRE_EQUAL(0U, size.width()); + BOOST_REQUIRE_EQUAL(0U, size.height()); +} + +BOOST_AUTO_TEST_CASE(null) +{ + BOOST_REQUIRE(mlk::size().is_null()); + BOOST_REQUIRE(!mlk::size(0, 10).is_null()); + BOOST_REQUIRE(!mlk::size(10, 0).is_null()); +} + +BOOST_AUTO_TEST_CASE(standard) +{ + mlk::size size(10, 20); + + BOOST_REQUIRE_EQUAL(10U, size.width()); + BOOST_REQUIRE_EQUAL(20U, size.height()); +} + +BOOST_AUTO_TEST_CASE(operator_eq) +{ + mlk::size size1, size2; + + BOOST_REQUIRE_EQUAL(size1, size2); +} + +BOOST_AUTO_TEST_CASE(operator_eq_1) +{ + mlk::size size1(10, 20); + mlk::size size2(10, 20); + + BOOST_REQUIRE_EQUAL(size1, size2); +} + +BOOST_AUTO_TEST_CASE(operator_neq) +{ + BOOST_REQUIRE_NE(mlk::size(10), mlk::size(20)); + BOOST_REQUIRE_NE(mlk::size(10, 10), mlk::size(10, 20)); +}
--- a/tests/libcommon/util/main.cpp Fri Jun 16 12:38:04 2017 +0200 +++ b/tests/libcommon/util/main.cpp Tue Jul 04 13:23:15 2017 +0200 @@ -20,6 +20,7 @@ #include <boost/test/unit_test.hpp> #include <malikania/util.hpp> +#include <malikania/size.hpp> using namespace mlk; using namespace nlohmann; @@ -335,3 +336,136 @@ } BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(json_require_size) + +/* + * util::json::require_size + * ------------------------------------------------------------------ + */ + +BOOST_AUTO_TEST_CASE(simple) +{ + json object{ + { "size", { + { "width", 10 }, + { "height", 20 } + } + } + }; + + BOOST_REQUIRE_EQUAL(util::json::require_size(object, "/size"_json_pointer), mlk::size(10, 20)); +} + +BOOST_AUTO_TEST_CASE(not_object) +{ + json object{ + { "size", false } + }; + + try { + util::json::require_size(object, "/size"_json_pointer); + BOOST_FAIL("exception expected"); + } catch (const util::json::property_error& ex) { + BOOST_REQUIRE_EQUAL(ex.type(), json::value_t::null); + BOOST_REQUIRE_EQUAL(ex.expected(), json::value_t::number_unsigned); + } +} + +BOOST_AUTO_TEST_CASE(not_int_width) +{ + json object{ + { "size", { + { "width", "10" }, + { "height", 20 } + } + } + }; + + try { + util::json::require_size(object, "/size"_json_pointer); + BOOST_FAIL("exception expected"); + } catch (const util::json::property_error& ex) { + BOOST_REQUIRE_EQUAL(ex.type(), json::value_t::string); + BOOST_REQUIRE_EQUAL(ex.expected(), json::value_t::number_unsigned); + } +} + +BOOST_AUTO_TEST_CASE(not_int_height) +{ + json object{ + { "size", { + { "width", 10 }, + { "height", "20" } + } + } + }; + + try { + util::json::require_size(object, "/size"_json_pointer); + BOOST_FAIL("exception expected"); + } catch (const util::json::property_error& ex) { + BOOST_REQUIRE_EQUAL(ex.type(), json::value_t::string); + BOOST_REQUIRE_EQUAL(ex.expected(), json::value_t::number_unsigned); + } +} + +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(json_get_size) + +BOOST_AUTO_TEST_CASE(simple) +{ + json object{ + { "size", { + { "width", 10 }, + { "height", 20 } + } + } + }; + + BOOST_REQUIRE_EQUAL(util::json::get_size(object, "/size"_json_pointer), mlk::size(10, 20)); +} + +BOOST_AUTO_TEST_CASE(not_object) +{ + json object{ + { "size", false } + }; + + mlk::size def(10, 20); + + BOOST_REQUIRE_EQUAL(util::json::get_size(object, "/size"_json_pointer, def), def); +} + +BOOST_AUTO_TEST_CASE(not_int_width) +{ + json object{ + { "size", { + { "width", "10" }, + { "height", 20 } + } + } + }; + + mlk::size def(10, 20); + + BOOST_REQUIRE_EQUAL(util::json::get_size(object, "/size"_json_pointer, def), def); +} + +BOOST_AUTO_TEST_CASE(not_int_height) +{ + json object{ + { "size", { + { "width", 10 }, + { "height", "20" } + } + } + }; + + mlk::size def(10, 20); + + BOOST_REQUIRE_EQUAL(util::json::get_size(object, "/size"_json_pointer, def), def); +} + +BOOST_AUTO_TEST_SUITE_END()