1
1
#ifndef __FILE_COMPAT_H__
2
2
#define __FILE_COMPAT_H__
3
3
4
- #include "numpy/npy_3kcompat.h"
4
+ #include <Python.h>
5
+ #include <stdio.h>
6
+ #include "numpy/npy_common.h"
7
+ #include "numpy/ndarrayobject.h"
8
+ #include "mplutils.h"
9
+
10
+ #ifdef __cplusplus
11
+ extern "C" {
12
+ #endif
13
+
14
+ #if defined(_MSC_VER ) && defined(_WIN64 ) && (_MSC_VER > 1400 )
15
+ #include <io.h>
16
+ #define npy_fseek _fseeki64
17
+ #define npy_ftell _ftelli64
18
+ #define npy_lseek _lseeki64
19
+ #define mpl_off_t npy_int64
20
+
21
+ #if NPY_SIZEOF_INT == 8
22
+ #define MPL_OFF_T_PYFMT "i"
23
+ #elif NPY_SIZEOF_LONG == 8
24
+ #define MPL_OFF_T_PYFMT "l"
25
+ #elif NPY_SIZEOF_LONGLONG == 8
26
+ #define MPL_OFF_T_PYFMT "L"
27
+ #else
28
+ #error Unsupported size for type off_t
29
+ #endif
30
+ #else
31
+ #define npy_fseek fseek
32
+ #define npy_ftell ftell
33
+ #define npy_lseek lseek
34
+ #define mpl_off_t off_t
35
+
36
+ #if NPY_SIZEOF_INT == NPY_SIZEOF_SHORT
37
+ #define MPL_OFF_T_PYFMT "h"
38
+ #elif NPY_SIZEOF_INT == NPY_SIZEOF_INT
39
+ #define MPL_OFF_T_PYFMT "i"
40
+ #elif NPY_SIZEOF_INT == NPY_SIZEOF_LONG
41
+ #define MPL_OFF_T_PYFMT "l"
42
+ #elif NPY_SIZEOF_INT == NPY_SIZEOF_LONGLONG
43
+ #define MPL_OFF_T_PYFMT "L"
44
+ #else
45
+ #error Unsupported size for type off_t
46
+ #endif
47
+ #endif
5
48
6
- #if NPY_API_VERSION < 0x4 /* corresponds to Numpy 1.5 */
7
49
/*
8
50
* PyFile_* compatibility
9
51
*/
10
- #if defined( NPY_PY3K )
52
+ #if PY3K
11
53
12
54
/*
13
55
* Get a FILE* handle to the file represented by the Python object
14
56
*/
15
57
static NPY_INLINE FILE *
16
- npy_PyFile_Dup (PyObject * file , char * mode )
58
+ mpl_PyFile_Dup (PyObject * file , char * mode , mpl_off_t * orig_pos )
17
59
{
18
60
int fd , fd2 ;
19
61
PyObject * ret , * os ;
20
- Py_ssize_t pos ;
62
+ mpl_off_t pos ;
21
63
FILE * handle ;
64
+
22
65
/* Flush first to ensure things end up in the file in the correct order */
23
66
ret = PyObject_CallMethod (file , "flush" , "" );
24
67
if (ret == NULL ) {
@@ -29,6 +72,9 @@ npy_PyFile_Dup(PyObject *file, char *mode)
29
72
if (fd == -1 ) {
30
73
return NULL ;
31
74
}
75
+
76
+ /* The handle needs to be dup'd because we have to call fclose
77
+ at the end */
32
78
os = PyImport_ImportModule ("os" );
33
79
if (os == NULL ) {
34
80
return NULL ;
@@ -40,6 +86,8 @@ npy_PyFile_Dup(PyObject *file, char *mode)
40
86
}
41
87
fd2 = PyNumber_AsSsize_t (ret , NULL );
42
88
Py_DECREF (ret );
89
+
90
+ /* Convert to FILE* handle */
43
91
#ifdef _WIN32
44
92
handle = _fdopen (fd2 , mode );
45
93
#else
@@ -49,6 +97,15 @@ npy_PyFile_Dup(PyObject *file, char *mode)
49
97
PyErr_SetString (PyExc_IOError ,
50
98
"Getting a FILE* from a Python file object failed" );
51
99
}
100
+
101
+ /* Record the original raw file handle position */
102
+ * orig_pos = npy_ftell (handle );
103
+ if (* orig_pos == -1 ) {
104
+ PyErr_SetString (PyExc_IOError , "obtaining file position failed" );
105
+ return NULL ;
106
+ }
107
+
108
+ /* Seek raw handle to the Python-side position */
52
109
ret = PyObject_CallMethod (file , "tell" , "" );
53
110
if (ret == NULL ) {
54
111
fclose (handle );
@@ -60,22 +117,46 @@ npy_PyFile_Dup(PyObject *file, char *mode)
60
117
fclose (handle );
61
118
return NULL ;
62
119
}
63
- npy_fseek (handle , pos , SEEK_SET );
120
+ if (npy_fseek (handle , pos , SEEK_SET ) == -1 ) {
121
+ PyErr_SetString (PyExc_IOError , "seeking file failed" );
122
+ return NULL ;
123
+ }
64
124
return handle ;
65
125
}
66
126
67
127
/*
68
128
* Close the dup-ed file handle, and seek the Python one to the current position
69
129
*/
70
130
static NPY_INLINE int
71
- npy_PyFile_DupClose (PyObject * file , FILE * handle )
131
+ mpl_PyFile_DupClose (PyObject * file , FILE * handle , mpl_off_t orig_pos )
72
132
{
133
+ int fd ;
73
134
PyObject * ret ;
74
- Py_ssize_t position ;
135
+ mpl_off_t position ;
136
+
75
137
position = npy_ftell (handle );
138
+
139
+ /* Close the FILE* handle */
76
140
fclose (handle );
77
141
78
- ret = PyObject_CallMethod (file , "seek" , NPY_SSIZE_T_PYFMT "i" , position , 0 );
142
+ /* Restore original file handle position, in order to not confuse
143
+ Python-side data structures */
144
+ fd = PyObject_AsFileDescriptor (file );
145
+ if (fd == -1 ) {
146
+ return -1 ;
147
+ }
148
+ if (npy_lseek (fd , orig_pos , SEEK_SET ) == -1 ) {
149
+ PyErr_SetString (PyExc_IOError , "seeking file failed" );
150
+ return -1 ;
151
+ }
152
+
153
+ if (position == -1 ) {
154
+ PyErr_SetString (PyExc_IOError , "obtaining file position failed" );
155
+ return -1 ;
156
+ }
157
+
158
+ /* Seek Python-side handle to the FILE* handle position */
159
+ ret = PyObject_CallMethod (file , "seek" , MPL_OFF_T_PYFMT "i" , position , 0 );
79
160
if (ret == NULL ) {
80
161
return -1 ;
81
162
}
@@ -84,7 +165,7 @@ npy_PyFile_DupClose(PyObject *file, FILE* handle)
84
165
}
85
166
86
167
static NPY_INLINE int
87
- npy_PyFile_Check (PyObject * file )
168
+ mpl_PyFile_Check (PyObject * file )
88
169
{
89
170
int fd ;
90
171
fd = PyObject_AsFileDescriptor (file );
@@ -97,13 +178,14 @@ npy_PyFile_Check(PyObject *file)
97
178
98
179
#else
99
180
100
- #define npy_PyFile_Dup (file , mode ) PyFile_AsFile(file)
101
- #define npy_PyFile_DupClose (file , handle ) (0)
181
+ #define mpl_PyFile_Dup (file , mode , orig_pos_p ) PyFile_AsFile(file)
182
+ #define mpl_PyFile_DupClose (file , handle , orig_pos ) (0)
183
+ #define mpl_PyFile_Check PyFile_Check
102
184
103
185
#endif
104
186
105
187
static NPY_INLINE PyObject *
106
- npy_PyFile_OpenFile (PyObject * filename , const char * mode )
188
+ mpl_PyFile_OpenFile (PyObject * filename , const char * mode )
107
189
{
108
190
PyObject * open ;
109
191
open = PyDict_GetItemString (PyEval_GetBuiltins (), "open" );
@@ -113,12 +195,8 @@ npy_PyFile_OpenFile(PyObject *filename, const char *mode)
113
195
return PyObject_CallFunction (open , "Os" , filename , mode );
114
196
}
115
197
116
- #endif /* NPY_API_VERSION < 0x4 */
117
-
118
- #if NPY_API_VERSION < 0x7 /* corresponds to Numpy 1.7 */
119
-
120
198
static NPY_INLINE int
121
- npy_PyFile_CloseFile (PyObject * file )
199
+ mpl_PyFile_CloseFile (PyObject * file )
122
200
{
123
201
PyObject * ret ;
124
202
@@ -130,6 +208,8 @@ npy_PyFile_CloseFile(PyObject *file)
130
208
return 0 ;
131
209
}
132
210
133
- #endif /* NPY_API_VERSION < 0x7 */
211
+ #ifdef __cplusplus
212
+ }
213
+ #endif
134
214
135
215
#endif /* ifndef __FILE_COMPAT_H__ */
0 commit comments