Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:06:13

0001 // Copyright (c) 2021 The Pybind Development Team.
0002 // All rights reserved. Use of this source code is governed by a
0003 // BSD-style license that can be found in the LICENSE file.
0004 
0005 #pragma once
0006 
0007 #include <pybind11/cast.h>
0008 #include <pybind11/detail/common.h>
0009 #include <pybind11/detail/descr.h>
0010 #include <pybind11/pybind11.h>
0011 #include <pybind11/pytypes.h>
0012 
0013 #include <string>
0014 
0015 #ifdef __has_include
0016 #    if defined(PYBIND11_CPP17)
0017 #        if __has_include(<filesystem>)
0018 #            include <filesystem>
0019 #            define PYBIND11_HAS_FILESYSTEM 1
0020 #        elif __has_include(<experimental/filesystem>)
0021 #            include <experimental/filesystem>
0022 #            define PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM 1
0023 #        endif
0024 #    endif
0025 #endif
0026 
0027 #if !defined(PYBIND11_HAS_FILESYSTEM) && !defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)           \
0028     && !defined(PYBIND11_HAS_FILESYSTEM_IS_OPTIONAL)
0029 #    error                                                                                        \
0030         "Neither #include <filesystem> nor #include <experimental/filesystem is available. (Use -DPYBIND11_HAS_FILESYSTEM_IS_OPTIONAL to ignore.)"
0031 #endif
0032 
0033 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0034 PYBIND11_NAMESPACE_BEGIN(detail)
0035 
0036 #ifdef PYPY_VERSION
0037 #    define PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(...) (__VA_ARGS__)
0038 #else
0039 #    define PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(...)                                   \
0040         (reinterpret_cast<void *>(__VA_ARGS__))
0041 #endif
0042 
0043 #if defined(PYBIND11_HAS_FILESYSTEM) || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
0044 template <typename T>
0045 struct path_caster {
0046 
0047 private:
0048     static PyObject *unicode_from_fs_native(const std::string &w) {
0049 #    if !defined(PYPY_VERSION)
0050         return PyUnicode_DecodeFSDefaultAndSize(w.c_str(), ssize_t(w.size()));
0051 #    else
0052         // PyPy mistakenly declares the first parameter as non-const.
0053         return PyUnicode_DecodeFSDefaultAndSize(const_cast<char *>(w.c_str()), ssize_t(w.size()));
0054 #    endif
0055     }
0056 
0057     static PyObject *unicode_from_fs_native(const std::wstring &w) {
0058         return PyUnicode_FromWideChar(w.c_str(), ssize_t(w.size()));
0059     }
0060 
0061 public:
0062     static handle cast(const T &path, return_value_policy, handle) {
0063         if (auto py_str = unicode_from_fs_native(path.native())) {
0064             return module_::import("pathlib")
0065                 .attr("Path")(reinterpret_steal<object>(py_str))
0066                 .release();
0067         }
0068         return nullptr;
0069     }
0070 
0071     bool load(handle handle, bool) {
0072         // PyUnicode_FSConverter and PyUnicode_FSDecoder normally take care of
0073         // calling PyOS_FSPath themselves, but that's broken on PyPy (PyPy
0074         // issue #3168) so we do it ourselves instead.
0075         PyObject *buf = PyOS_FSPath(handle.ptr());
0076         if (!buf) {
0077             PyErr_Clear();
0078             return false;
0079         }
0080         PyObject *native = nullptr;
0081         if constexpr (std::is_same_v<typename T::value_type, char>) {
0082             if (PyUnicode_FSConverter(buf, PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(&native))
0083                 != 0) {
0084                 if (auto *c_str = PyBytes_AsString(native)) {
0085                     // AsString returns a pointer to the internal buffer, which
0086                     // must not be free'd.
0087                     value = c_str;
0088                 }
0089             }
0090         } else if constexpr (std::is_same_v<typename T::value_type, wchar_t>) {
0091             if (PyUnicode_FSDecoder(buf, PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(&native))
0092                 != 0) {
0093                 if (auto *c_str = PyUnicode_AsWideCharString(native, nullptr)) {
0094                     // AsWideCharString returns a new string that must be free'd.
0095                     value = c_str; // Copies the string.
0096                     PyMem_Free(c_str);
0097                 }
0098             }
0099         }
0100         Py_XDECREF(native);
0101         Py_DECREF(buf);
0102         if (PyErr_Occurred()) {
0103             PyErr_Clear();
0104             return false;
0105         }
0106         return true;
0107     }
0108 
0109     PYBIND11_TYPE_CASTER(T, const_name("os.PathLike"));
0110 };
0111 
0112 #endif // PYBIND11_HAS_FILESYSTEM || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
0113 
0114 #if defined(PYBIND11_HAS_FILESYSTEM)
0115 template <>
0116 struct type_caster<std::filesystem::path> : public path_caster<std::filesystem::path> {};
0117 #elif defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
0118 template <>
0119 struct type_caster<std::experimental::filesystem::path>
0120     : public path_caster<std::experimental::filesystem::path> {};
0121 #endif
0122 
0123 PYBIND11_NAMESPACE_END(detail)
0124 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)