include/wrenbind17/pop.hpp

include/wrenbind17/pop.hpp #

Namespaces #

Name
wrenbind17

Source code #

#pragma once

#include <wren.hpp>

#include <string>
#include <memory>

#include "object.hpp"

namespace wrenbind17 {
    void getClassType(WrenVM* vm, std::string& module, std::string& name, size_t hash);
    detail::ForeignPtrConvertor* getClassCast(WrenVM* vm, size_t hash, size_t other);

#ifndef DOXYGEN_SHOULD_SKIP_THIS
    namespace detail {
        // ============================================================================================================
        //                                       CHECK SLOTS FOR TYPE
        // ============================================================================================================
        inline const char* wrenSlotTypeToStr(const WrenType type) {
            switch (type) {
                case WREN_TYPE_BOOL:
                    return "bool";
                case WREN_TYPE_FOREIGN:
                    return "instance";
                case WREN_TYPE_LIST:
                    return "list";
                case WREN_TYPE_NULL:
                    return "null";
                case WREN_TYPE_NUM:
                    return "number";
                case WREN_TYPE_STRING:
                    return "string";
                case WREN_TYPE_UNKNOWN:
                default:
                    return "unknown";
            }
        }

        template <typename T> inline bool is(WrenVM* vm, const int idx) {
            const auto type = wrenGetSlotType(vm, idx);
            if (type != WrenType::WREN_TYPE_FOREIGN)
                return false;

            auto slot = wrenGetSlotForeign(vm, idx);
            const auto foreign = reinterpret_cast<Foreign*>(slot);
            return foreign->hash() == typeid(T).hash_code();
        }

        template <> inline bool is<bool>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_BOOL;
        }

        template <> inline bool is<std::string>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_STRING;
        }

        template <> inline bool is<std::nullptr_t>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NULL;
        }

        template <> inline bool is<float>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<double>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<int>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<int8_t>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<char>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<unsigned char>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<short>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<unsigned short>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<unsigned>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<long>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<long long>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<unsigned long>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <> inline bool is<unsigned long long>(WrenVM* vm, const int idx) {
            return wrenGetSlotType(vm, idx) == WrenType::WREN_TYPE_NUM;
        }

        template <typename T> struct CheckSlot {
            static bool f(WrenVM* vm, const int idx) {
                return is<T>(vm, idx);
            }
        };

        template <typename T> struct CheckSlot<T&> {
            static bool f(WrenVM* vm, const int idx) {
                return is<T>(vm, idx);
            }
        };

        template <typename T> struct CheckSlot<const T&> {
            static bool f(WrenVM* vm, const int idx) {
                return is<T>(vm, idx);
            }
        };

        template <typename T> struct CheckSlot<T*> {
            static bool f(WrenVM* vm, const int idx) {
                return is<T>(vm, idx);
            }
        };

        template <typename T> struct CheckSlot<const T*> {
            static bool f(WrenVM* vm, const int idx) {
                return is<T>(vm, idx);
            }
        };

        template <typename T> struct CheckSlot<std::shared_ptr<T>> {
            static bool f(WrenVM* vm, const int idx) {
                return is<T>(vm, idx);
            }
        };

        template <typename T> struct CheckSlot<const std::shared_ptr<T>&> {
            static bool f(WrenVM* vm, const int idx) {
                return is<T>(vm, idx);
            }
        };

        // ============================================================================================================
        //                                       BASIC TYPES
        // ============================================================================================================
        template <WrenType Type> inline void validate(WrenVM* vm, int idx) {
            const auto t = wrenGetSlotType(vm, idx);
            if (t != Type)
                throw BadCast("Bad cast when getting value from Wren got " + std::string(wrenSlotTypeToStr(t)) +
                              " expected " + std::string(wrenSlotTypeToStr(Type)));
        }

        template <typename T> std::shared_ptr<T> getSlotForeign(WrenVM* vm, void* slot) {
            using Type = typename std::remove_const<typename std::remove_pointer<T>::type>::type;
            using ForeignTypeConvertor = ForeignSharedPtrConvertor<Type>;

            const auto foreign = reinterpret_cast<Foreign*>(slot);
            if (foreign->hash() != typeid(Type).hash_code()) {
                try {
                    auto base = getClassCast(vm, foreign->hash(), typeid(Type).hash_code());
                    auto derived = reinterpret_cast<ForeignTypeConvertor*>(base);
                    if (!derived) {
                        throw BadCast("Bad cast the value cannot be upcast to the expected type");
                    }
                    return derived->cast(foreign);
                } catch (std::out_of_range& e) {
                    (void)e;
                    throw BadCast("Bad cast the value is not the expected type");
                }
            }

            auto ptr = reinterpret_cast<ForeignObject<Type>*>(foreign);
            return ptr->shared();
        }

        template <typename T> const std::shared_ptr<T> getSlotForeign(WrenVM* vm, const int idx) {
            validate<WrenType::WREN_TYPE_FOREIGN>(vm, idx);
            return getSlotForeign<T>(vm, wrenGetSlotForeign(vm, idx));
        }

        template <typename T> T getSlot(WrenVM* vm, int idx) {
            static_assert(!std::is_same<std::string, T>(), "type can't be std::string");
            static_assert(!is_shared_ptr<T>::value, "type can't be shared_ptr<T>");
            validate<WrenType::WREN_TYPE_FOREIGN>(vm, idx);
            return *getSlotForeign<typename std::remove_reference<T>::type>(vm, idx).get();
        }

        template <typename T> struct PopHelper {
            static inline T f(WrenVM* vm, int idx) {
                return getSlot<T>(vm, idx);
            }
        };

        template <typename T> struct PopHelper<T*> {
            static inline T* f(WrenVM* vm, int idx) {
                const auto type = wrenGetSlotType(vm, idx);
                if (type == WrenType::WREN_TYPE_NULL)
                    return nullptr;
                else if (type != WrenType::WREN_TYPE_FOREIGN)
                    throw BadCast("Bad cast when getting value from Wren");
                return getSlotForeign<typename std::remove_const<T>::type>(vm, idx).get();
            }
        };

        template <typename T> struct PopHelper<const T&> {
            static inline const T& f(WrenVM* vm, int idx) {
                static_assert(!std::is_same<std::string, T>(), "type can't be std::string");
                static_assert(!std::is_same<std::nullptr_t, T>(), "type can't be std::nullptr_t");
                static_assert(!is_shared_ptr<T>::value, "type can't be shared_ptr<T>");
                return *getSlotForeign<T>(vm, idx).get();
            }
        };

        template <typename T> struct PopHelper<std::shared_ptr<T>> {
            static inline std::shared_ptr<T> f(WrenVM* vm, int idx) {
                const auto type = wrenGetSlotType(vm, idx);
                if (type == WrenType::WREN_TYPE_NULL)
                    return nullptr;
                else if (type != WrenType::WREN_TYPE_FOREIGN)
                    throw BadCast("Bad cast when getting value from Wren");
                return getSlotForeign<T>(vm, idx);
            }
        };

        template <typename T> struct PopHelper<const std::shared_ptr<T>&> {
            static inline std::shared_ptr<T> f(WrenVM* vm, int idx) {
                const auto type = wrenGetSlotType(vm, idx);
                if (type == WrenType::WREN_TYPE_NULL)
                    return nullptr;
                else if (type != WrenType::WREN_TYPE_FOREIGN)
                    throw BadCast("Bad cast when getting value from Wren");
                return getSlotForeign<T>(vm, idx);
            }
        };

        template <> inline Handle getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_UNKNOWN>(vm, idx);
            return Handle(getSharedVm(vm), wrenGetSlotHandle(vm, idx));
        }

        template <> inline std::string getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_STRING>(vm, idx);
            return std::string(wrenGetSlotString(vm, idx));
        }

        template <> inline std::nullptr_t getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NULL>(vm, idx);
            return nullptr;
        }

        template <> inline bool getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_BOOL>(vm, idx);
            return wrenGetSlotBool(vm, idx);
        }

        template <> inline int8_t getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<int8_t>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline char getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<char>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline int getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<int>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline short getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<short>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline long getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<long>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline unsigned char getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<unsigned char>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline unsigned long getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<unsigned long>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline unsigned short getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<unsigned short>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline unsigned getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<unsigned>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline long long getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<long long>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline unsigned long long getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<unsigned long long>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline float getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<float>(wrenGetSlotDouble(vm, idx));
        }

        template <> inline double getSlot(WrenVM* vm, int idx) {
            validate<WrenType::WREN_TYPE_NUM>(vm, idx);
            return static_cast<double>(wrenGetSlotDouble(vm, idx));
        }

#define WRENBIND17_POP_HELPER(Type)                                                                                    \
    template <> struct PopHelper<const Type&> {                                                                        \
        static inline Type f(WrenVM* vm, int idx) {                                                                    \
            return getSlot<Type>(vm, idx);                                                                             \
        }                                                                                                              \
    };

        WRENBIND17_POP_HELPER(std::string)
        WRENBIND17_POP_HELPER(std::nullptr_t)
        WRENBIND17_POP_HELPER(bool)
        WRENBIND17_POP_HELPER(int8_t)
        WRENBIND17_POP_HELPER(char)
        WRENBIND17_POP_HELPER(int)
        WRENBIND17_POP_HELPER(short)
        WRENBIND17_POP_HELPER(long)
        WRENBIND17_POP_HELPER(unsigned long)
        WRENBIND17_POP_HELPER(unsigned)
        WRENBIND17_POP_HELPER(long long)
        WRENBIND17_POP_HELPER(unsigned long long)
        WRENBIND17_POP_HELPER(unsigned short)
        WRENBIND17_POP_HELPER(unsigned char)
        WRENBIND17_POP_HELPER(float)
        WRENBIND17_POP_HELPER(double)
    } // namespace detail
#endif
} // namespace wrenbind17

Updated on 17 October 2023 at 12:26:25 UTC