# Makefile for OpenWrt # # Copyright (C) 2006 OpenWrt.org # Copyright (C) 2006 by Felix Fietkau # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # RELEASE:=Kamikaze #VERSION:=2.0 # uncomment for final release #-------------------------------------------------------------- # Just run 'make menuconfig', configure stuff, then run 'make'. # You shouldn't need to mess with anything beyond this point... #-------------------------------------------------------------- all: world SHELL:=/usr/bin/env bash export LC_ALL=C export LANG=C export TOPDIR=${CURDIR} export IS_TTY=$(shell tty -s && echo 1 || echo 0) include $(TOPDIR)/include/verbose.mk OPENWRTVERSION:=$(RELEASE) ifneq ($(VERSION),) OPENWRTVERSION:=$(VERSION) ($(OPENWRTVERSION)) else REV:=$(shell LANG=C svn info | awk '/^Revision:/ { print$$2 }' ) ifneq ($(REV),) OPENWRTVERSION:=$(OPENWRTVERSION)/r$(REV) endif endif export OPENWRTVERSION ifeq ($(FORCE),) .config scripts/config/conf scripts/config/mconf: tmp/.prereq-build world: tmp/.prereq-package tmp/.prereq-target endif package/%/Makefile: ; target/%/Makefile: ; tmp/.packageinfo tmp/.targetinfo: FORCE mkdir -p tmp/info $(NO_TRACE_MAKE) -s -f include/scan.mk SCAN_TARGET="targetinfo" SCAN_DIR="target/linux" SCAN_NAME="target" SCAN_DEPS="" SCAN_TARGET_DEPS="$(wildcard target/*/Makefile include/kernel*.mk)" SCAN_EXTRA="" $(NO_TRACE_MAKE) -s -f include/scan.mk SCAN_TARGET="packageinfo" SCAN_DIR="package" SCAN_NAME="package" SCAN_DEPS="$(wildcard package/*/Makefile include/package*.mk include/kernel.mk)" SCAN_EXTRA="" tmpinfo-clean: FORCE -rm -rf tmp/.*info tmp/.config-%.in: tmp/.%info scripts/metadata.pl ./scripts/metadata.pl $*_config < $< > $@ || rm -f $@ .config: ./scripts/config/conf tmp/.config-target.in tmp/.config-package.in if [ \! -f .config ]; then \ [ -e $(HOME)/.openwrt/defconfig ] && cp $(HOME)/.openwrt/defconfig .config; \ $(NO_TRACE_MAKE) menuconfig; \ fi $< -D .config Config.in &> /dev/null scripts/config/mconf: $(MAKE) -C scripts/config all scripts/config/conf: $(MAKE) -C scripts/config conf config: scripts/config/conf tmp/.config-target.in tmp/.config-package.in FORCE $< Config.in config-clean: FORCE $(NO_TRACE_MAKE) -C scripts/config clean defconfig: scripts/config/conf tmp/.config-target.in tmp/.config-package.in FORCE touch .config $< -D .config Config.in oldconfig: scripts/config/conf tmp/.config-target.in tmp/.config-package.in FORCE $< -o Config.in menuconfig: scripts/config/mconf tmp/.config-target.in tmp/.config-package.in FORCE if [ \! -f .config -a -e $(HOME)/.openwrt/defconfig ]; then \ cp $(HOME)/.openwrt/defconfig .config; \ fi $< Config.in kernel_menuconfig: .config FORCE -$(MAKE) target/linux-prepare $(NO_TRACE_MAKE) -C target/linux menuconfig package/% target/%: tmp/.packageinfo toolchain/% package/% target/%: tmp/.targetinfo package/% target/% tools/% toolchain/%: FORCE $(MAKE) -C $(patsubst %/$*,%,$@) $* tmp/.prereq-build: include/prereq-build.mk mkdir -p tmp rm -f tmp/.host.mk $(NO_TRACE_MAKE) -s -f $(TOPDIR)/include/prereq-build.mk prereq 2>/dev/null || { \ echo "Prerequisite check failed. Use FORCE=1 to override."; \ false; \ } touch $@ tmp/.prereq-%: include/prereq.mk tmp/.%info .config mkdir -p tmp rm -f tmp/.host.mk $(NO_TRACE_MAKE) -s -C $* prereq 2>/dev/null || { \ echo "Prerequisite check failed. Use FORCE=1 to override."; \ false; \ } touch $@ prereq: tmp/.prereq-build tmp/.prereq-package tmp/.prereq-target FORCE download: .config FORCE $(MAKE) tools/download $(MAKE) toolchain/download $(MAKE) package/download $(MAKE) target/download world: .config FORCE $(MAKE) tools/install $(MAKE) toolchain/install $(MAKE) target/compile $(MAKE) package/compile $(MAKE) package/install $(MAKE) target/install $(MAKE) package/index clean: FORCE rm -rf build_* bin tmp dirclean: clean rm -rf staging_dir_* toolchain_build_* tool_build distclean: dirclean config-clean symlinkclean docclean rm -rf dl help: cat README doc: $(MAKE) -C docs/ openwrt.pdf docclean: $(MAKE) -C docs/ clean symlinkclean: -find package -type l | xargs rm -f .SILENT: clean dirclean distclean symlinkclean config-clean download world help tmp/.packageinfo tmp/.targetinfo tmpinfo-clean tmp/.config-package.in tmp/.config-target.in .config scripts/config/mconf scripts/config/conf menuconfig tmp/.prereq-build tmp/.prereq-package tmp/.prereq-target FORCE: ; .PHONY: FORCE help 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
/*
    tests/test_builtin_casters.cpp -- Casters available without any additional headers

    Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch>

    All rights reserved. Use of this source code is governed by a
    BSD-style license that can be found in the LICENSE file.
*/

#include "pybind11_tests.h"
#include <pybind11/complex.h>

#if defined(_MSC_VER)
#  pragma warning(push)
#  pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
#endif

TEST_SUBMODULE(builtin_casters, m) {
    // test_simple_string
    m.def("string_roundtrip", [](const char *s) { return s; });

    // test_unicode_conversion
    // Some test characters in utf16 and utf32 encodings.  The last one (the 𝐀) contains a null byte
    char32_t a32 = 0x61 /*a*/, z32 = 0x7a /*z*/, ib32 = 0x203d /*β€½*/, cake32 = 0x1f382 /*πŸŽ‚*/,              mathbfA32 = 0x1d400 /*𝐀*/;
    char16_t b16 = 0x62 /*b*/, z16 = 0x7a,       ib16 = 0x203d,       cake16_1 = 0xd83c, cake16_2 = 0xdf82, mathbfA16_1 = 0xd835, mathbfA16_2 = 0xdc00;
    std::wstring wstr;
    wstr.push_back(0x61); // a
    wstr.push_back(0x2e18); // ⸘
    if (sizeof(wchar_t) == 2) { wstr.push_back(mathbfA16_1); wstr.push_back(mathbfA16_2); } // 𝐀, utf16
    else { wstr.push_back((wchar_t) mathbfA32); } // 𝐀, utf32
    wstr.push_back(0x7a); // z

    m.def("good_utf8_string", []() { return std::string((const char*)u8"Say utf8\u203d \U0001f382 \U0001d400"); }); // Say utf8β€½ πŸŽ‚ 𝐀
    m.def("good_utf16_string", [=]() { return std::u16string({ b16, ib16, cake16_1, cake16_2, mathbfA16_1, mathbfA16_2, z16 }); }); // bβ€½πŸŽ‚π€z
    m.def("good_utf32_string", [=]() { return std::u32string({ a32, mathbfA32, cake32, ib32, z32 }); }); // aπ€πŸŽ‚β€½z
    m.def("good_wchar_string", [=]() { return wstr; }); // a‽𝐀z
    m.def("bad_utf8_string", []()  { return std::string("abc\xd0" "def"); });
    m.def("bad_utf16_string", [=]() { return std::u16string({ b16, char16_t(0xd800), z16 }); });
    // Under Python 2.7, invalid unicode UTF-32 characters don't appear to trigger UnicodeDecodeError
    if (PY_MAJOR_VERSION >= 3)
        m.def("bad_utf32_string", [=]() { return std::u32string({ a32, char32_t(0xd800), z32 }); });
    if (PY_MAJOR_VERSION >= 3 || sizeof(wchar_t) == 2)
        m.def("bad_wchar_string", [=]() { return std::wstring({ wchar_t(0x61), wchar_t(0xd800) }); });
    m.def("u8_Z", []() -> char { return 'Z'; });
    m.def("u8_eacute", []() -> char { return '\xe9'; });
    m.def("u16_ibang", [=]() -> char16_t { return ib16; });
    m.def("u32_mathbfA", [=]() -> char32_t { return mathbfA32; });
    m.def("wchar_heart", []() -> wchar_t { return 0x2665; });

    // test_single_char_arguments
    m.attr("wchar_size") = py::cast(sizeof(wchar_t));
    m.def("ord_char", [](char c) -> int { return static_cast<unsigned char>(c); });
    m.def("ord_char_lv", [](char &c) -> int { return static_cast<unsigned char>(c); });
    m.def("ord_char16", [](char16_t c) -> uint16_t { return c; });
    m.def("ord_char16_lv", [](char16_t &c) -> uint16_t { return c; });
    m.def("ord_char32", [](char32_t c) -> uint32_t { return c; });
    m.def("ord_wchar", [](wchar_t c) -> int { return c; });

    // test_bytes_to_string
    m.def("strlen", [](char *s) { return strlen(s); });
    m.def("string_length", [](std::string s) { return s.length(); });

#ifdef PYBIND11_HAS_U8STRING
    m.attr("has_u8string") = true;
    m.def("good_utf8_u8string", []() { return std::u8string(u8"Say utf8\u203d \U0001f382 \U0001d400"); }); // Say utf8β€½ πŸŽ‚ 𝐀
    m.def("bad_utf8_u8string", []()  { return std::u8string((const char8_t*)"abc\xd0" "def"); });

    m.def("u8_char8_Z", []() -> char8_t { return u8'Z'; });

    // test_single_char_arguments
    m.def("ord_char8", [](char8_t c) -> int { return static_cast<unsigned char>(c); });
    m.def("ord_char8_lv", [](char8_t &c) -> int { return static_cast<unsigned char>(c); });
#endif

    // test_string_view
#ifdef PYBIND11_HAS_STRING_VIEW
    m.attr("has_string_view") = true;
    m.def("string_view_print",   [](std::string_view s)    { py::print(s, s.size()); });
    m.def("string_view16_print", [](std::u16string_view s) { py::print(s, s.size()); });
    m.def("string_view32_print", [](std::u32string_view s) { py::print(s, s.size()); });
    m.def("string_view_chars",   [](std::string_view s)    { py::list l; for (auto c : s) l.append((std::uint8_t) c); return l; });
    m.def("string_view16_chars", [](std::u16string_view s) { py::list l; for (auto c : s) l.append((int) c); return l; });
    m.def("string_view32_chars", [](std::u32string_view s) { py::list l; for (auto c : s) l.append((int) c); return l; });
    m.def("string_view_return",   []() { return std::string_view((const char*)u8"utf8 secret \U0001f382"); });
    m.def("string_view16_return", []() { return std::u16string_view(u"utf16 secret \U0001f382"); });
    m.def("string_view32_return", []() { return std::u32string_view(U"utf32 secret \U0001f382"); });

#   ifdef PYBIND11_HAS_U8STRING
    m.def("string_view8_print",  [](std::u8string_view s) { py::print(s, s.size()); });
    m.def("string_view8_chars",  [](std::u8string_view s) { py::list l; for (auto c : s) l.append((std::uint8_t) c); return l; });
    m.def("string_view8_return", []() { return std::u8string_view(u8"utf8 secret \U0001f382"); });
#   endif
#endif

    // test_integer_casting
    m.def("i32_str", [](std::int32_t v) { return std::to_string(v); });
    m.def("u32_str", [](std::uint32_t v) { return std::to_string(v); });
    m.def("i64_str", [](std::int64_t v) { return std::to_string(v); });
    m.def("u64_str", [](std::uint64_t v) { return std::to_string(v); });

    // test_tuple
    m.def("pair_passthrough", [](std::pair<bool, std::string> input) {
        return std::make_pair(input.second, input.first);
    }, "Return a pair in reversed order");
    m.def("tuple_passthrough", [](std::tuple<bool, std::string, int> input) {
        return std::make_tuple(std::get<2>(input), std::get<1>(input), std::get<0>(input));
    }, "Return a triple in reversed order");
    m.def("empty_tuple", []() { return std::tuple<>(); });
    static std::pair<RValueCaster, RValueCaster> lvpair;
    static std::tuple<RValueCaster, RValueCaster, RValueCaster> lvtuple;
    static std::pair<RValueCaster, std::tuple<RValueCaster, std::pair<RValueCaster, RValueCaster>>> lvnested;
    m.def("rvalue_pair", []() { return std::make_pair(RValueCaster{}, RValueCaster{}); });
    m.def("lvalue_pair", []() -> const decltype(lvpair) & { return lvpair; });
    m.def("rvalue_tuple", []() { return std::make_tuple(RValueCaster{}, RValueCaster{}, RValueCaster{}); });
    m.def("lvalue_tuple", []() -> const decltype(lvtuple) & { return lvtuple; });
    m.def("rvalue_nested", []() {
        return std::make_pair(RValueCaster{}, std::make_tuple(RValueCaster{}, std::make_pair(RValueCaster{}, RValueCaster{}))); });
    m.def("lvalue_nested", []() -> const decltype(lvnested) & { return lvnested; });

    static std::pair<int, std::string> int_string_pair{2, "items"};
    m.def("int_string_pair", []() { return &int_string_pair; });

    // test_builtins_cast_return_none
    m.def("return_none_string", []() -> std::string * { return nullptr; });
    m.def("return_none_char",   []() -> const char *  { return nullptr; });
    m.def("return_none_bool",   []() -> bool *        { return nullptr; });
    m.def("return_none_int",    []() -> int *         { return nullptr; });
    m.def("return_none_float",  []() -> float *       { return nullptr; });
    m.def("return_none_pair",   []() -> std::pair<int,int> * { return nullptr; });

    // test_none_deferred
    m.def("defer_none_cstring", [](char *) { return false; });
    m.def("defer_none_cstring", [](py::none) { return true; });
    m.def("defer_none_custom", [](UserType *) { return false; });
    m.def("defer_none_custom", [](py::none) { return true; });
    m.def("nodefer_none_void", [](void *) { return true; });
    m.def("nodefer_none_void", [](py::none) { return false; });

    // test_void_caster
    m.def("load_nullptr_t", [](std::nullptr_t) {}); // not useful, but it should still compile
    m.def("cast_nullptr_t", []() { return std::nullptr_t{}; });

    // test_bool_caster
    m.def("bool_passthrough", [](bool arg) { return arg; });
    m.def("bool_passthrough_noconvert", [](bool arg) { return arg; }, py::arg().noconvert());

    // test_reference_wrapper
    m.def("refwrap_builtin", [](std::reference_wrapper<int> p) { return 10 * p.get(); });
    m.def("refwrap_usertype", [](std::reference_wrapper<UserType> p) { return p.get().value(); });
    // Not currently supported (std::pair caster has return-by-value cast operator);
    // triggers static_assert failure.
    //m.def("refwrap_pair", [](std::reference_wrapper<std::pair<int, int>>) { });

    m.def("refwrap_list", [](bool copy) {
        static IncType x1(1), x2(2);
        py::list l;
        for (auto &f : {std::ref(x1), std::ref(x2)}) {
            l.append(py::cast(f, copy ? py::return_value_policy::copy
                                      : py::return_value_policy::reference));
        }
        return l;
    }, "copy"_a);

    m.def("refwrap_iiw", [](const IncType &w) { return w.value(); });
    m.def("refwrap_call_iiw", [](IncType &w, py::function f) {
        py::list l;
        l.append(f(std::ref(w)));
        l.append(f(std::cref(w)));
        IncType x(w.value());
        l.append(f(std::ref(x)));
        IncType y(w.value());
        auto r3 = std::ref(y);
        l.append(f(r3));
        return l;
    });

    // test_complex
    m.def("complex_cast", [](float x) { return "{}"_s.format(x); });
    m.def("complex_cast", [](std::complex<float> x) { return "({}, {})"_s.format(x.real(), x.imag()); });

    // test int vs. long (Python 2)
    m.def("int_cast", []() {return (int) 42;});
    m.def("long_cast", []() {return (long) 42;});
    m.def("longlong_cast", []() {return  ULLONG_MAX;});

    /// test void* cast operator
    m.def("test_void_caster", []() -> bool {
        void *v = (void *) 0xabcd;
        py::object o = py::cast(v);
        return py::cast<void *>(o) == v;
    });
}