mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make get_long_path more efficient
Only do filesystem I/O once per call in the common case of paths of less that 4096 chars
This commit is contained in:
parent
b7e6b8fbee
commit
a13dd062f3
@ -33,6 +33,7 @@ class wchar_raii {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
wchar_raii() : handle(NULL) {}
|
wchar_raii() : handle(NULL) {}
|
||||||
|
wchar_raii(wchar_t *h) : handle(h) {}
|
||||||
|
|
||||||
~wchar_raii() {
|
~wchar_raii() {
|
||||||
if (handle) {
|
if (handle) {
|
||||||
|
@ -770,18 +770,24 @@ static PyObject *
|
|||||||
get_long_path_name(PyObject *self, PyObject *args) {
|
get_long_path_name(PyObject *self, PyObject *args) {
|
||||||
wchar_raii path;
|
wchar_raii path;
|
||||||
if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &path)) return NULL;
|
if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &path)) return NULL;
|
||||||
DWORD sz = GetLongPathNameW(path.ptr(), NULL, 0) * 2;
|
DWORD current_size = 4096;
|
||||||
if (!sz) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
wchar_raii buf((wchar_t*)PyMem_Malloc(current_size * sizeof(wchar_t)));
|
||||||
wchar_t *buf = (wchar_t*) PyMem_Malloc(sz);
|
|
||||||
if (!buf) return PyErr_NoMemory();
|
if (!buf) return PyErr_NoMemory();
|
||||||
if (!GetLongPathNameW(path.ptr(), buf, sz-1)) {
|
DWORD needed_size = GetLongPathNameW(path.ptr(), buf.ptr(), current_size);
|
||||||
PyMem_Free(buf);
|
if (needed_size >= current_size - 32) {
|
||||||
return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
current_size = needed_size + 32;
|
||||||
|
PyMem_Free(buf.ptr());
|
||||||
|
buf.set_ptr((wchar_t*)PyMem_Malloc(current_size * sizeof(wchar_t)));
|
||||||
|
if (!buf) return PyErr_NoMemory();
|
||||||
|
needed_size = GetLongPathNameW(path.ptr(), buf.ptr(), current_size);
|
||||||
}
|
}
|
||||||
buf[sz-1] = 0;
|
if (!needed_size) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
PyObject *ans = PyUnicode_FromWideChar(buf, -1);
|
if (needed_size >= current_size - 2) {
|
||||||
PyMem_Free(buf);
|
PyErr_SetString(PyExc_OSError, "filename length changed between calls");
|
||||||
return ans;
|
return NULL;
|
||||||
|
}
|
||||||
|
buf.ptr()[current_size-1] = 0;
|
||||||
|
return PyUnicode_FromWideChar(buf.ptr(), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
Loading…
x
Reference in New Issue
Block a user