irccd  3.0.3
duk.hpp
1 /*
2  * duk.hpp -- miscellaneous Duktape extras
3  *
4  * Copyright (c) 2017-2019 David Demelier <markand@malikania.fr>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifndef IRCCD_JS_DUK_HPP
20 #define IRCCD_JS_DUK_HPP
21 
29 #include <exception>
30 #include <memory>
31 #include <string>
32 #include <string_view>
33 #include <vector>
34 
35 #include "duktape.h"
36 
37 namespace irccd {
38 
39 namespace js {
40 
44 namespace duk {
45 
46 // {{{ stack_guard
47 
59 class stack_guard {
60 #if !defined(NDEBUG)
61 private:
62  duk_context* context_;
63  unsigned expected_;
64  int at_start_;
65 #endif
66 
67 public:
76  stack_guard(duk_context* ctx, unsigned expected = 0) noexcept;
77 
83  ~stack_guard() noexcept;
84 };
85 
86 // }}}
87 
88 // {{{ context
89 
95 class context {
96 private:
97  std::unique_ptr<duk_context, void (*)(duk_context*)> handle_;
98 
99  context(const context&) = delete;
100  void operator=(const context&) = delete;
101 
102 public:
106  context() noexcept;
107 
111  context(context&&) noexcept = default;
112 
118  operator duk_context*() noexcept;
119 
125  operator duk_context*() const noexcept;
126 
132  auto operator=(context&&) noexcept -> context& = default;
133 };
134 
135 // }}}
136 
137 // {{{ stack_info
138 
144 class stack_info : public std::exception {
145 private:
146  std::string name_;
147  std::string message_;
148  std::string stack_;
149  std::string file_name_;
150  unsigned line_number_;
151 
152 public:
162  stack_info(std::string name,
163  std::string message,
164  std::string stack,
165  std::string file_name,
166  unsigned line_number = 0) noexcept;
167 
173  auto get_name() const noexcept -> const std::string&;
174 
180  auto get_message() const noexcept -> const std::string&;
181 
187  auto get_stack() const noexcept -> const std::string&;
188 
194  auto get_file_name() const noexcept -> const std::string&;
195 
201  auto get_line_number() const noexcept -> unsigned;
202 
208  auto what() const noexcept -> const char* override;
209 };
210 
211 // }}}
212 
213 // {{{ type_traits
214 
253 template <typename T>
254 struct type_traits;
255 
256 // }}}
257 
258 // {{{ push
259 
269 template <typename T>
270 auto push(duk_context* ctx, T&& value) -> int
271 {
272  using Type = typename std::decay<T>::type;
273 
274  type_traits<Type>::push(ctx, std::forward<T>(value));
275 
276  return 1;
277 }
278 
279 // }}}
280 
281 // {{{ get
282 
292 template <typename T>
293 auto get(duk_context* ctx, duk_idx_t index)
294 {
295  using Type = typename std::decay<T>::type;
296 
297  return type_traits<Type>::get(ctx, index);
298 }
299 
300 // }}}
301 
302 // {{{ require
303 
313 template <typename T>
314 auto require(duk_context* ctx, duk_idx_t index)
315 {
316  using Type = typename std::decay<T>::type;
317 
318  return type_traits<Type>::require(ctx, index);
319 }
320 
321 // }}}
322 
323 // {{{ error
324 
329 class error {
330 private:
331  int type_{DUK_ERR_ERROR};
332  std::string message_;
333 
334 protected:
342  error(int type, std::string message) noexcept;
343 
344 public:
350  error(std::string message) noexcept;
351 
355  ~error() = default;
356 
363  void create(duk_context* ctx) const;
364 };
365 
366 // }}}
367 
368 // {{{ eval_error
369 
373 class eval_error : public error {
374 public:
380  eval_error(std::string message) noexcept;
381 };
382 
383 // }}}
384 
385 // {{{ range_error
386 
390 class range_error : public error {
391 public:
397  range_error(std::string message) noexcept;
398 };
399 
400 // }}}
401 
402 // {{{ reference_error
403 
407 class reference_error : public error {
408 public:
414  reference_error(std::string message) noexcept;
415 };
416 
417 // }}}
418 
419 // {{{ syntax_error
420 
424 class syntax_error : public error {
425 public:
431  syntax_error(std::string message) noexcept;
432 };
433 
434 // }}}
435 
436 // {{{ type_error
437 
441 class type_error : public error {
442 public:
448  type_error(std::string message) noexcept;
449 };
450 
451 // }}}
452 
453 // {{{ uri_error
454 
458 class uri_error : public error {
459 public:
465  uri_error(std::string message) noexcept;
466 };
467 
468 // }}}
469 
470 // {{{ raise
471 
486 template <typename Error>
487 void raise(duk_context* ctx, Error&& error)
488 {
489  using type = std::decay_t<Error>;
490 
491  type_traits<type>::raise(ctx, std::forward<Error>(error));
492 }
493 
494 // }}}
495 
496 // {{{ get_stack
497 
507 auto get_stack(duk_context* ctx, int index, bool pop = true) -> stack_info;
508 
509 // }}}
510 
511 // {{{ type_traits<std::exception>
512 
516 template <>
517 struct type_traits<std::exception> {
524  static void raise(duk_context* ctx, const std::exception& ex);
525 };
526 
527 // }}}
528 
529 // {{{ type_traits<error>
530 
534 template <>
542  static void raise(duk_context* ctx, const error& ex);
543 };
544 
545 // }}}
546 
547 // {{{ type_traits<bool>
548 
552 template <>
553 struct type_traits<bool> {
562  static void push(duk_context* ctx, bool value);
563 
573  static auto get(duk_context* ctx, duk_idx_t index) -> bool;
574 
584  static auto require(duk_context* ctx, duk_idx_t index) -> bool;
585 };
586 
587 // }}}
588 
589 // {{{ type_traits<duk_double_t>
590 
594 template <>
595 struct type_traits<duk_double_t> {
604  static void push(duk_context* ctx, duk_double_t value);
605 
615  static auto get(duk_context* ctx, duk_idx_t index) -> duk_double_t;
616 
626  static auto require(duk_context* ctx, duk_idx_t index) -> duk_double_t;
627 };
628 
629 // }}}
630 
631 // {{{ type_traits<duk_int_t>
632 
636 template <>
637 struct type_traits<duk_int_t> {
646  static void push(duk_context* ctx, duk_int_t value);
647 
657  static auto get(duk_context* ctx, duk_idx_t index) -> duk_int_t;
658 
668  static auto require(duk_context* ctx, duk_idx_t index) -> duk_int_t;
669 };
670 
671 // }}}
672 
673 // {{{ type_traits<duk_uint_t>
674 
678 template <>
679 struct type_traits<duk_uint_t> {
688  static void push(duk_context* ctx, duk_uint_t value);
689 
699  static auto get(duk_context* ctx, duk_idx_t index) -> duk_uint_t;
700 
710  static auto require(duk_context* ctx, duk_idx_t index) -> duk_uint_t;
711 };
712 
713 // }}}
714 
715 // {{{ type_traits<const char*>
716 
720 template <>
721 struct type_traits<const char*> {
730  static void push(duk_context* ctx, const char* value);
731 
741  static auto get(duk_context* ctx, duk_idx_t index) -> const char*;
742 
752  static auto require(duk_context* ctx, duk_idx_t index) -> const char*;
753 };
754 
755 // }}}
756 
757 // {{{ type_traits<std::string>
758 
762 template <>
763 struct type_traits<std::string> {
772  static void push(duk_context* ctx, const std::string& value);
773 
783  static auto get(duk_context* ctx, duk_idx_t index) -> std::string;
784 
794  static auto require(duk_context* ctx, duk_idx_t index) -> std::string;
795 };
796 
797 // }}}
798 
799 // {{{ type_traits<std::string_view>
800 
804 template <>
805 struct type_traits<std::string_view> : public std::true_type {
814  static void push(duk_context* ctx, std::string_view value);
815 
825  static auto get(duk_context* ctx, duk_idx_t index) -> std::string_view;
826 
836  static auto require(duk_context* ctx, duk_idx_t index) -> std::string_view;
837 };
838 
839 // }}}
840 
841 // {{{ type_traits<std::vector<T>>
842 
846 template <typename T>
847 struct type_traits<std::vector<T>> : public std::true_type {
854  static void push(duk_context* ctx, const std::vector<T>& values)
855  {
856  duk_push_array(ctx);
857 
858  for (std::size_t i = 0; i < values.size(); ++i) {
859  type_traits<T>::push(ctx, values[i]);
860  duk_put_prop_index(ctx, -2, i);
861  }
862  }
863 
871  static auto get(duk_context* ctx, duk_idx_t index) -> std::vector<T>
872  {
873  const auto length = duk_get_length(ctx, index);
874 
875  std::vector<T> result;
876 
877  result.reserve(length);
878 
879  for (auto i = 0U; i < length; ++i) {
880  duk_get_prop_index(ctx, index, i);
881  result.push_back(type_traits<T>::get(ctx, -1));
882  duk_pop(ctx);
883  }
884 
885  return result;
886  }
887 };
888 
889 // }}}
890 
891 } // !duk
892 
893 } // !js
894 
895 } // !irccd
896 
897 #endif // !IRCCD_JS_DUK_HPP
RAII based Duktape handler.
Definition: duk.hpp:95
Base ECMAScript error class.
Definition: duk.hpp:329
error(std::string message) noexcept
void create(duk_context *ctx) const
error(int type, std::string message) noexcept
Error in eval() function.
Definition: duk.hpp:373
eval_error(std::string message) noexcept
Value is out of range.
Definition: duk.hpp:390
range_error(std::string message) noexcept
Trying to use a variable that does not exist.
Definition: duk.hpp:407
reference_error(std::string message) noexcept
Stack sanity checker.
Definition: duk.hpp:59
stack_guard(duk_context *ctx, unsigned expected=0) noexcept
Error description.
Definition: duk.hpp:144
stack_info(std::string name, std::string message, std::string stack, std::string file_name, unsigned line_number=0) noexcept
Syntax error in the script.
Definition: duk.hpp:424
syntax_error(std::string message) noexcept
Invalid type given.
Definition: duk.hpp:441
type_error(std::string message) noexcept
URI manipulation failure.
Definition: duk.hpp:458
uri_error(std::string message) noexcept
auto require(duk_context *ctx, duk_idx_t index)
Definition: duk.hpp:314
auto get(duk_context *ctx, duk_idx_t index)
Definition: duk.hpp:293
auto push(duk_context *ctx, T &&value) -> int
Definition: duk.hpp:270
auto get_stack(duk_context *ctx, int index, bool pop=true) -> stack_info
Parent namespace.
Definition: acceptor.hpp:43
Definition: bot.hpp:253
static void push(duk_context *ctx, bool value)
static auto get(duk_context *ctx, duk_idx_t index) -> bool
static auto require(duk_context *ctx, duk_idx_t index) -> bool
static auto get(duk_context *ctx, duk_idx_t index) -> const char *
static auto require(duk_context *ctx, duk_idx_t index) -> const char *
static void push(duk_context *ctx, const char *value)
static auto require(duk_context *ctx, duk_idx_t index) -> duk_double_t
static void push(duk_context *ctx, duk_double_t value)
static auto get(duk_context *ctx, duk_idx_t index) -> duk_double_t
static void push(duk_context *ctx, duk_int_t value)
static auto require(duk_context *ctx, duk_idx_t index) -> duk_int_t
static auto get(duk_context *ctx, duk_idx_t index) -> duk_int_t
static void push(duk_context *ctx, duk_uint_t value)
static auto get(duk_context *ctx, duk_idx_t index) -> duk_uint_t
static auto require(duk_context *ctx, duk_idx_t index) -> duk_uint_t
static void push(duk_context *ctx, const std::string &value)
static auto get(duk_context *ctx, duk_idx_t index) -> std::string
static auto require(duk_context *ctx, duk_idx_t index) -> std::string
static void push(duk_context *ctx, std::string_view value)
static auto require(duk_context *ctx, duk_idx_t index) -> std::string_view
static auto get(duk_context *ctx, duk_idx_t index) -> std::string_view
static void push(duk_context *ctx, const std::vector< T > &values)
Definition: duk.hpp:854
static auto get(duk_context *ctx, duk_idx_t index) -> std::vector< T >
Definition: duk.hpp:871
Operations on different types.
Definition: duk.hpp:254