From 902f25985b69dee283944db19727d507e6f7d3bf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 21 Apr 2021 10:44:29 +0530 Subject: [PATCH] DRYer --- setup/extensions.json | 7 +- .../mtp/windows/device_enumeration.cpp | 2 +- src/calibre/srv/fast_css_transform.cpp | 25 ++----- src/calibre/utils/cpp_binding.h | 71 +++++++++++++++++++ src/calibre/utils/windows/common.h | 57 +-------------- src/calibre/utils/windows/winutil.cpp | 3 +- 6 files changed, 82 insertions(+), 83 deletions(-) create mode 100644 src/calibre/utils/cpp_binding.h diff --git a/setup/extensions.json b/setup/extensions.json index 5e76a922d2..8b04b4b6fb 100644 --- a/setup/extensions.json +++ b/setup/extensions.json @@ -116,6 +116,7 @@ }, { "name": "fast_css_transform", + "headers": "calibre/utils/cpp_binding.h", "sources": "calibre/srv/fast_css_transform.cpp", "inc_dirs": "perfect-hashing", "needs_c++14": true @@ -145,7 +146,7 @@ { "name": "winutil", "only": "windows", - "headers": "calibre/utils/windows/common.h", + "headers": "calibre/utils/cpp_binding.h calibre/utils/windows/common.h", "sources": "calibre/utils/windows/winutil.cpp", "libraries": "shell32 wininet advapi32", "cflags": "/X" @@ -153,7 +154,7 @@ { "name": "winsapi", "only": "windows", - "headers": "calibre/utils/windows/common.h", + "headers": "calibre/utils/cpp_binding.h calibre/utils/windows/common.h", "sources": "calibre/utils/windows/winsapi.cpp", "libraries": "SAPI Ole32", "cflags": "/X" @@ -162,7 +163,7 @@ "name": "wpd", "only": "windows", "sources": "calibre/devices/mtp/windows/utils.cpp calibre/devices/mtp/windows/device_enumeration.cpp calibre/devices/mtp/windows/content_enumeration.cpp calibre/devices/mtp/windows/device.cpp calibre/devices/mtp/windows/wpd.cpp", - "headers": "calibre/devices/mtp/windows/global.h calibre/utils/windows/common.h", + "headers": "calibre/utils/cpp_binding.h calibre/devices/mtp/windows/global.h calibre/utils/windows/common.h", "libraries": "ole32 oleaut32 portabledeviceguids user32", "cflags": "/X" }, diff --git a/src/calibre/devices/mtp/windows/device_enumeration.cpp b/src/calibre/devices/mtp/windows/device_enumeration.cpp index 6c624c9b26..a3ceac38d1 100644 --- a/src/calibre/devices/mtp/windows/device_enumeration.cpp +++ b/src/calibre/devices/mtp/windows/device_enumeration.cpp @@ -127,7 +127,7 @@ get_storage_info(IPortableDevice *device) { // {{{ Py_END_ALLOW_THREADS; if (SUCCEEDED(hr)) { com_wchar_raii cleanup[arraysz(object_ids)]; - for (i = 0; i < arraysz(object_ids); i++) { cleanup[i].set_ptr(object_ids[i]); }; + for (i = 0; i < arraysz(object_ids); i++) { cleanup[i].attach(object_ids[i]); }; for(i = 0; i < fetched; i++) { CComPtr values; Py_BEGIN_ALLOW_THREADS; diff --git a/src/calibre/srv/fast_css_transform.cpp b/src/calibre/srv/fast_css_transform.cpp index ba19ae2632..53a1baaf14 100644 --- a/src/calibre/srv/fast_css_transform.cpp +++ b/src/calibre/srv/fast_css_transform.cpp @@ -24,6 +24,7 @@ #include #include #include +#include "../utils/cpp_binding.h" // character classes {{{ static inline bool @@ -78,25 +79,6 @@ class python_error : public std::runtime_error { python_error(const char *msg) : std::runtime_error(msg) {} }; -class pyobject_raii { - private: - PyObject *handle; - pyobject_raii( const pyobject_raii & ) ; - pyobject_raii & operator=( const pyobject_raii & ) ; - - public: - pyobject_raii() : handle(NULL) {} - pyobject_raii(PyObject* h, bool incref=false) : handle(h) { if (incref && handle) Py_INCREF(handle); } - - ~pyobject_raii() { Py_CLEAR(handle); } - - PyObject *ptr() { return handle; } - void set_ptr(PyObject *val) { handle = val; } - PyObject **address() { return &handle; } - explicit operator bool() const { return handle != NULL; } - PyObject *detach() { PyObject *ans = handle; handle = NULL; return ans; } -}; - // Parse numbers {{{ typedef long long integer_type; @@ -670,9 +652,10 @@ class TokenQueue { } public: - TokenQueue(const size_t src_sz, PyObject *url_callback=NULL) : - pool(), queue(), out(), scratch(), scratch2(), url_callback(url_callback, true) { + TokenQueue(const size_t src_sz, PyObject *url_callback_pointer=NULL) : + pool(), queue(), out(), scratch(), scratch2(), url_callback(url_callback_pointer) { out.reserve(src_sz * 2); scratch.reserve(16); scratch2.reserve(16); + Py_XINCREF(url_callback.ptr()); } void rewind_output() { out.pop_back(); } diff --git a/src/calibre/utils/cpp_binding.h b/src/calibre/utils/cpp_binding.h new file mode 100644 index 0000000000..76f5f14508 --- /dev/null +++ b/src/calibre/utils/cpp_binding.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#pragma once + +#define PY_SSIZE_T_CLEAN +#define UNICODE +#define _UNICODE +#include +#include + +#define arraysz(x) (sizeof(x)/sizeof(x[0])) + +template(NULL)> +class generic_raii { + private: + T handle; + generic_raii( const generic_raii & ) ; + generic_raii & operator=( const generic_raii & ) ; + + public: + explicit generic_raii(T h = null) : handle(h) {} + ~generic_raii() { release(); } + + void release() { + if (handle != null) { + free_T(handle); + handle = null; + } + } + + T ptr() { return handle; } + T detach() { T ans = handle; handle = null; return ans; } + void attach(T val) { release(); handle = val; } + T* address() { return &handle; } + explicit operator bool() const { return handle != null; } + T* operator &() { return &handle; } +}; + +typedef generic_raii wchar_raii; +static inline void python_object_destructor(void *p) { PyObject *x = reinterpret_cast(p); Py_XDECREF(x); } +typedef generic_raii pyobject_raii; + + +static inline int +py_to_wchar(PyObject *obj, wchar_raii *output) { + if (!PyUnicode_Check(obj)) { + if (obj == Py_None) { return 1; } + PyErr_SetString(PyExc_TypeError, "unicode object expected"); + return 0; + } + wchar_t *buf = PyUnicode_AsWideCharString(obj, NULL); + if (!buf) { PyErr_NoMemory(); return 0; } + output->attach(buf); + return 1; +} + +static inline int +py_to_wchar_no_none(PyObject *obj, wchar_raii *output) { + if (!PyUnicode_Check(obj)) { + PyErr_SetString(PyExc_TypeError, "unicode object expected"); + return 0; + } + wchar_t *buf = PyUnicode_AsWideCharString(obj, NULL); + if (!buf) { PyErr_NoMemory(); return 0; } + output->attach(buf); + return 1; +} diff --git a/src/calibre/utils/windows/common.h b/src/calibre/utils/windows/common.h index 8045fa7235..91b90f6fef 100644 --- a/src/calibre/utils/windows/common.h +++ b/src/calibre/utils/windows/common.h @@ -11,7 +11,7 @@ #include #include #include -#define arraysz(x) (sizeof(x)/sizeof(x[0])) +#include "../cpp_binding.h" static inline PyObject* set_error_from_hresult(PyObject *exc_type, const char *file, const int line, const HRESULT hr, const char *prefix="", PyObject *name=NULL) { @@ -24,61 +24,6 @@ set_error_from_hresult(PyObject *exc_type, const char *file, const int line, con } #define error_from_hresult(hr, ...) set_error_from_hresult(PyExc_OSError, __FILE__, __LINE__, hr, __VA_ARGS__) -template -class generic_raii { - private: - T handle; - generic_raii( const generic_raii & ) ; - generic_raii & operator=( const generic_raii & ) ; - - public: - explicit generic_raii(T h = null) : handle(h) {} - ~generic_raii() { release(); } - - void release() { - if (handle != null) { - free_T(handle); - handle = null; - } - } - - T ptr() { return handle; } - T detach() { T ans = handle; handle = null; return ans; } - void set_ptr(T val) { handle = val; } - T* address() { return &handle; } - explicit operator bool() const { return handle != null; } - T* operator &() { return &handle; } -}; - -typedef generic_raii wchar_raii; typedef generic_raii com_wchar_raii; -static inline void python_object_destructor(void *p) { PyObject *x = reinterpret_cast(p); Py_XDECREF(x); } -typedef generic_raii pyobject_raii; static inline void handle_destructor(HANDLE p) { CloseHandle(p); } typedef generic_raii handle_raii; - - -static int -py_to_wchar(PyObject *obj, wchar_raii *output) { - if (!PyUnicode_Check(obj)) { - if (obj == Py_None) { return 1; } - PyErr_SetString(PyExc_TypeError, "unicode object expected"); - return 0; - } - wchar_t *buf = PyUnicode_AsWideCharString(obj, NULL); - if (!buf) { PyErr_NoMemory(); return 0; } - output->set_ptr(buf); - return 1; -} - -static int -py_to_wchar_no_none(PyObject *obj, wchar_raii *output) { - if (!PyUnicode_Check(obj)) { - PyErr_SetString(PyExc_TypeError, "unicode object expected"); - return 0; - } - wchar_t *buf = PyUnicode_AsWideCharString(obj, NULL); - if (!buf) { PyErr_NoMemory(); return 0; } - output->set_ptr(buf); - return 1; -} diff --git a/src/calibre/utils/windows/winutil.cpp b/src/calibre/utils/windows/winutil.cpp index 0c71f5616f..a769e76846 100644 --- a/src/calibre/utils/windows/winutil.cpp +++ b/src/calibre/utils/windows/winutil.cpp @@ -832,8 +832,7 @@ get_long_path_name(PyObject *self, PyObject *args) { Py_END_ALLOW_THREADS if (needed_size >= current_size - 32) { current_size = needed_size + 32; - PyMem_Free(buf.ptr()); - buf.set_ptr((wchar_t*)PyMem_Malloc(current_size * sizeof(wchar_t))); + buf.attach((wchar_t*)PyMem_Malloc(current_size * sizeof(wchar_t))); if (!buf) return PyErr_NoMemory(); Py_BEGIN_ALLOW_THREADS needed_size = GetLongPathNameW(path.ptr(), buf.ptr(), current_size);