|
10 | 10 | // Note: Do not include this file directly! Include "napi.h" instead. |
11 | 11 |
|
12 | 12 | #include <cstring> |
| 13 | +#include <type_traits> |
13 | 14 |
|
14 | 15 | namespace Napi { |
15 | 16 |
|
@@ -599,6 +600,106 @@ inline Symbol::Symbol() : Name() { |
599 | 600 | inline Symbol::Symbol(napi_env env, napi_value value) : Name(env, value) { |
600 | 601 | } |
601 | 602 |
|
| 603 | +//////////////////////////////////////////////////////////////////////////////// |
| 604 | +// Automagic value creation |
| 605 | +//////////////////////////////////////////////////////////////////////////////// |
| 606 | + |
| 607 | +namespace details { |
| 608 | +template <typename T> |
| 609 | +struct vf_number { |
| 610 | + static Number From(napi_env env, T value) { |
| 611 | + return Number::New(env, static_cast<double>(value)); |
| 612 | + } |
| 613 | +}; |
| 614 | + |
| 615 | +template<> |
| 616 | +struct vf_number<bool> { |
| 617 | + static Boolean From(napi_env env, bool value) { |
| 618 | + return Boolean::New(env, value); |
| 619 | + } |
| 620 | +}; |
| 621 | + |
| 622 | +struct vf_utf8_charp { |
| 623 | + static String From(napi_env env, const char* value) { |
| 624 | + return String::New(env, value); |
| 625 | + } |
| 626 | +}; |
| 627 | + |
| 628 | +struct vf_utf16_charp { |
| 629 | + static String From(napi_env env, const char16_t* value) { |
| 630 | + return String::New(env, value); |
| 631 | + } |
| 632 | +}; |
| 633 | +struct vf_utf8_string { |
| 634 | + static String From(napi_env env, const std::string& value) { |
| 635 | + return String::New(env, value); |
| 636 | + } |
| 637 | +}; |
| 638 | + |
| 639 | +struct vf_utf16_string { |
| 640 | + static String From(napi_env env, const std::u16string& value) { |
| 641 | + return String::New(env, value); |
| 642 | + } |
| 643 | +}; |
| 644 | + |
| 645 | +template <typename T> |
| 646 | +struct vf_fallback { |
| 647 | + static Value From(napi_env env, const T& value) { |
| 648 | + return Value(env, value); |
| 649 | + } |
| 650 | +}; |
| 651 | + |
| 652 | +template <typename...> struct disjunction : std::false_type {}; |
| 653 | +template <typename B> struct disjunction<B> : B {}; |
| 654 | +template <typename B, typename... Bs> |
| 655 | +struct disjunction<B, Bs...> |
| 656 | + : std::conditional<bool(B::value), B, disjunction<Bs...>>::type {}; |
| 657 | + |
| 658 | +template <typename T> |
| 659 | +struct can_make_string |
| 660 | + : disjunction<typename std::is_convertible<T, const char *>::type, |
| 661 | + typename std::is_convertible<T, const char16_t *>::type, |
| 662 | + typename std::is_convertible<T, std::string>::type, |
| 663 | + typename std::is_convertible<T, std::u16string>::type> {}; |
| 664 | +} |
| 665 | + |
| 666 | +template <typename T> |
| 667 | +Value Value::From(napi_env env, const T& value) { |
| 668 | + using Helper = typename std::conditional< |
| 669 | + std::is_integral<T>::value || std::is_floating_point<T>::value, |
| 670 | + details::vf_number<T>, |
| 671 | + typename std::conditional< |
| 672 | + details::can_make_string<T>::value, |
| 673 | + String, |
| 674 | + details::vf_fallback<T> |
| 675 | + >::type |
| 676 | + >::type; |
| 677 | + return Helper::From(env, value); |
| 678 | +} |
| 679 | + |
| 680 | +template <typename T> |
| 681 | +String String::From(napi_env env, const T& value) { |
| 682 | + struct Dummy {}; |
| 683 | + using Helper = typename std::conditional< |
| 684 | + std::is_convertible<T, const char*>::value, |
| 685 | + details::vf_utf8_charp, |
| 686 | + typename std::conditional< |
| 687 | + std::is_convertible<T, const char16_t*>::value, |
| 688 | + details::vf_utf16_charp, |
| 689 | + typename std::conditional< |
| 690 | + std::is_convertible<T, std::string>::value, |
| 691 | + details::vf_utf8_string, |
| 692 | + typename std::conditional< |
| 693 | + std::is_convertible<T, std::u16string>::value, |
| 694 | + details::vf_utf16_string, |
| 695 | + Dummy |
| 696 | + >::type |
| 697 | + >::type |
| 698 | + >::type |
| 699 | + >::type; |
| 700 | + return Helper::From(env, value); |
| 701 | +} |
| 702 | + |
602 | 703 | //////////////////////////////////////////////////////////////////////////////// |
603 | 704 | // Object class |
604 | 705 | //////////////////////////////////////////////////////////////////////////////// |
@@ -705,58 +806,32 @@ inline Value Object::Get(const std::string& utf8name) const { |
705 | 806 | return Get(utf8name.c_str()); |
706 | 807 | } |
707 | 808 |
|
708 | | -inline void Object::Set(napi_value key, napi_value value) { |
709 | | - napi_status status = napi_set_property(_env, _value, key, value); |
| 809 | +template <typename ValueType> |
| 810 | +inline void Object::Set(napi_value key, const ValueType& value) { |
| 811 | + napi_status status = |
| 812 | + napi_set_property(_env, _value, key, Value::From(_env, value)); |
710 | 813 | NAPI_THROW_IF_FAILED(_env, status); |
711 | 814 | } |
712 | 815 |
|
713 | | -inline void Object::Set(Value key, Value value) { |
714 | | - napi_status status = napi_set_property(_env, _value, key, value); |
| 816 | +template <typename ValueType> |
| 817 | +inline void Object::Set(Value key, const ValueType& value) { |
| 818 | + napi_status status = |
| 819 | + napi_set_property(_env, _value, key, Value::From(_env, value)); |
715 | 820 | NAPI_THROW_IF_FAILED(_env, status); |
716 | 821 | } |
717 | 822 |
|
718 | | -inline void Object::Set(const char* utf8name, Value value) { |
719 | | - napi_status status = napi_set_named_property(_env, _value, utf8name, value); |
| 823 | +template <typename ValueType> |
| 824 | +inline void Object::Set(const char* utf8name, const ValueType& value) { |
| 825 | + napi_status status = |
| 826 | + napi_set_named_property(_env, _value, utf8name, Value::From(_env, value)); |
720 | 827 | NAPI_THROW_IF_FAILED(_env, status); |
721 | 828 | } |
722 | 829 |
|
723 | | -inline void Object::Set(const char* utf8name, napi_value value) { |
724 | | - napi_status status = napi_set_named_property(_env, _value, utf8name, value); |
725 | | - NAPI_THROW_IF_FAILED(_env, status); |
726 | | -} |
727 | | - |
728 | | -inline void Object::Set(const char* utf8name, const char* utf8value) { |
729 | | - Set(utf8name, String::New(Env(), utf8value)); |
730 | | -} |
731 | | - |
732 | | -inline void Object::Set(const char* utf8name, bool boolValue) { |
733 | | - Set(utf8name, Boolean::New(Env(), boolValue)); |
734 | | -} |
735 | | - |
736 | | -inline void Object::Set(const char* utf8name, double numberValue) { |
737 | | - Set(utf8name, Number::New(Env(), numberValue)); |
738 | | -} |
739 | | - |
740 | | -inline void Object::Set(const std::string& utf8name, napi_value value) { |
741 | | - Set(utf8name.c_str(), value); |
742 | | -} |
743 | | - |
744 | | -inline void Object::Set(const std::string& utf8name, Value value) { |
| 830 | +template <typename ValueType> |
| 831 | +inline void Object::Set(const std::string& utf8name, const ValueType& value) { |
745 | 832 | Set(utf8name.c_str(), value); |
746 | 833 | } |
747 | 834 |
|
748 | | -inline void Object::Set(const std::string& utf8name, std::string& utf8value) { |
749 | | - Set(utf8name.c_str(), String::New(Env(), utf8value)); |
750 | | -} |
751 | | - |
752 | | -inline void Object::Set(const std::string& utf8name, bool boolValue) { |
753 | | - Set(utf8name.c_str(), Boolean::New(Env(), boolValue)); |
754 | | -} |
755 | | - |
756 | | -inline void Object::Set(const std::string& utf8name, double numberValue) { |
757 | | - Set(utf8name.c_str(), Number::New(Env(), numberValue)); |
758 | | -} |
759 | | - |
760 | 835 | inline bool Object::Delete(napi_value key) { |
761 | 836 | bool result; |
762 | 837 | napi_status status = napi_delete_property(_env, _value, key, &result); |
@@ -793,32 +868,13 @@ inline Value Object::Get(uint32_t index) const { |
793 | 868 | return Value(_env, value); |
794 | 869 | } |
795 | 870 |
|
796 | | -inline void Object::Set(uint32_t index, napi_value value) { |
797 | | - napi_status status = napi_set_element(_env, _value, index, value); |
| 871 | +template <typename ValueType> |
| 872 | +inline void Object::Set(uint32_t index, const ValueType& value) { |
| 873 | + napi_status status = |
| 874 | + napi_set_element(_env, _value, index, Value::From(_env, value)); |
798 | 875 | NAPI_THROW_IF_FAILED(_env, status); |
799 | 876 | } |
800 | 877 |
|
801 | | -inline void Object::Set(uint32_t index, Value value) { |
802 | | - napi_status status = napi_set_element(_env, _value, index, value); |
803 | | - NAPI_THROW_IF_FAILED(_env, status); |
804 | | -} |
805 | | - |
806 | | -inline void Object::Set(uint32_t index, const char* utf8value) { |
807 | | - Set(index, static_cast<napi_value>(String::New(Env(), utf8value))); |
808 | | -} |
809 | | - |
810 | | -inline void Object::Set(uint32_t index, const std::string& utf8value) { |
811 | | - Set(index, static_cast<napi_value>(String::New(Env(), utf8value))); |
812 | | -} |
813 | | - |
814 | | -inline void Object::Set(uint32_t index, bool boolValue) { |
815 | | - Set(index, static_cast<napi_value>(Boolean::New(Env(), boolValue))); |
816 | | -} |
817 | | - |
818 | | -inline void Object::Set(uint32_t index, double numberValue) { |
819 | | - Set(index, static_cast<napi_value>(Number::New(Env(), numberValue))); |
820 | | -} |
821 | | - |
822 | 878 | inline bool Object::Delete(uint32_t index) { |
823 | 879 | bool result; |
824 | 880 | napi_status status = napi_delete_element(_env, _value, index, &result); |
|
0 commit comments