Mercurial > malikania
view libclient-js/malikania/js_rectangle.cpp @ 43:fabbe1759cec
Misc: switch to mlk namespace, closes #589
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 29 Nov 2016 22:25:17 +0100 |
parents | a47a4477f347 |
children | 96ba0c5cf893 |
line wrap: on
line source
/* * 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 mlk { 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); } } // !mlk