Mercurial > code
changeset 415:ac4573b9bb4b
Js: add js::Pointer for non-managed pointers
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 08 Oct 2015 08:29:48 +0200 |
parents | 0b6f7f7c8a6c |
children | a93dfbb65648 |
files | C++/modules/Js/Js.h C++/tests/Js/main.cpp |
diffstat | 2 files changed, 102 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/modules/Js/Js.h Wed Oct 07 15:06:10 2015 +0200 +++ b/C++/modules/Js/Js.h Thu Oct 08 08:29:48 2015 +0200 @@ -84,6 +84,20 @@ }; /** + * @class Pointer + * @brief Push a non-managed pointer to Duktape, the pointer will never be deleted. + * @note For a managed pointer with prototype, see TypeInfoPointer + */ +template <typename T> +class Pointer { +public: + /** + * The pointer to push. + */ + T *object; +}; + +/** * @class Function * @brief Duktape/C function definition. */ @@ -1183,6 +1197,44 @@ }; /** + * @brief Implementation for non-managed pointers. + * + * Provides: get, is, optional, push, require. + */ +template <typename T> +class TypeInfo<Pointer<T>> { +public: + static inline T *get(Context &ctx, int index) + { + return static_cast<T *>(duk_to_pointer(ctx, index)); + } + + static inline bool is(Context &ctx, int index) + { + return duk_is_pointer(ctx, index); + } + + static inline T *optional(Context &ctx, int index, Pointer<T> defaultValue) + { + if (!duk_is_pointer(ctx, index)) { + return defaultValue.object; + } + + return static_cast<T *>(duk_to_pointer(ctx, index)); + } + + static inline void push(Context &ctx, const Pointer<T> &p) + { + duk_push_pointer(ctx, p.object); + } + + static inline T *require(Context &ctx, int index) + { + return static_cast<T *>(duk_require_pointer(ctx, index)); + } +}; + +/** * @class TypeInfo<Global> * @brief Push the global object to the stack. *
--- a/C++/tests/Js/main.cpp Wed Oct 07 15:06:10 2015 +0200 +++ b/C++/tests/Js/main.cpp Thu Oct 08 08:29:48 2015 +0200 @@ -137,6 +137,16 @@ ASSERT_EQ(3, array[2]); } +TEST(PushAndGet, pointer) +{ + Context context; + + ASSERT_EQ(0, context.top()); + context.push(Pointer<int>{new int(1)}); + ASSERT_EQ(1, *context.get<Pointer<int>>(-1)); + ASSERT_EQ(1, context.top()); +} + /* -------------------------------------------------------- * Require * -------------------------------------------------------- */ @@ -246,6 +256,27 @@ ASSERT_EQ(0, context.top()); } +TEST(Require, pointer) +{ + Context context; + + ASSERT_EQ(0, context.top()); + + try { + context.push(Function{[] (Context &ctx) -> int { + ctx.require<Pointer<int>>(0); + + return 0; + }}); + context.peval(); + + FAIL() << "exception expected"; + } catch (...) { + } + + ASSERT_EQ(0, context.top()); +} + /* -------------------------------------------------------- * Is * -------------------------------------------------------- */ @@ -340,6 +371,16 @@ ASSERT_EQ(1, context.top()); } +TEST(Is, pointer) +{ + Context context; + + ASSERT_EQ(0, context.top()); + context.push(Pointer<int>{new int(1)}); + ASSERT_TRUE(context.is<Pointer<int>>(-1)); + ASSERT_EQ(1, context.top()); +} + /* -------------------------------------------------------- * Optional * -------------------------------------------------------- */ @@ -394,6 +435,15 @@ ASSERT_EQ(0, context.top()); } +TEST(Optional, pointer) +{ + Context context; + + ASSERT_EQ(0, context.top()); + ASSERT_EQ(nullptr, context.optional<js::Pointer<int>>(0, js::Pointer<int>{nullptr})); + ASSERT_EQ(0, context.top()); +} + /* -------------------------------------------------------- * Basics * -------------------------------------------------------- */