11#ifndef  __FILE_COMPAT_H__ 
22#define  __FILE_COMPAT_H__ 
33
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 
548
6- #if  NPY_API_VERSION  <  0x4  /* corresponds to Numpy 1.5 */ 
749/* 
850 * PyFile_* compatibility 
951 */ 
10- #if  defined( NPY_PY3K ) 
52+ #if  PY3K 
1153
1254/* 
1355 * Get a FILE* handle to the file represented by the Python object 
1456 */ 
1557static  NPY_INLINE  FILE * 
16- npy_PyFile_Dup (PyObject  * file , char  * mode )
58+ mpl_PyFile_Dup (PyObject  * file , char  * mode ,  mpl_off_t   * orig_pos )
1759{
1860    int  fd , fd2 ;
1961    PyObject  * ret , * os ;
20-     Py_ssize_t  pos ;
62+     mpl_off_t  pos ;
2163    FILE  * handle ;
64+ 
2265    /* Flush first to ensure things end up in the file in the correct order */ 
2366    ret  =  PyObject_CallMethod (file , "flush" , "" );
2467    if  (ret  ==  NULL ) {
@@ -29,6 +72,9 @@ npy_PyFile_Dup(PyObject *file, char *mode)
2972    if  (fd  ==  -1 ) {
3073        return  NULL ;
3174    }
75+ 
76+     /* The handle needs to be dup'd because we have to call fclose 
77+        at the end */ 
3278    os  =  PyImport_ImportModule ("os" );
3379    if  (os  ==  NULL ) {
3480        return  NULL ;
@@ -40,6 +86,8 @@ npy_PyFile_Dup(PyObject *file, char *mode)
4086    }
4187    fd2  =  PyNumber_AsSsize_t (ret , NULL );
4288    Py_DECREF (ret );
89+ 
90+     /* Convert to FILE* handle */ 
4391#ifdef  _WIN32 
4492    handle  =  _fdopen (fd2 , mode );
4593#else 
@@ -49,6 +97,15 @@ npy_PyFile_Dup(PyObject *file, char *mode)
4997        PyErr_SetString (PyExc_IOError ,
5098                        "Getting a FILE* from a Python file object failed" );
5199    }
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 */ 
52109    ret  =  PyObject_CallMethod (file , "tell" , "" );
53110    if  (ret  ==  NULL ) {
54111        fclose (handle );
@@ -60,22 +117,46 @@ npy_PyFile_Dup(PyObject *file, char *mode)
60117        fclose (handle );
61118        return  NULL ;
62119    }
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+     }
64124    return  handle ;
65125}
66126
67127/* 
68128 * Close the dup-ed file handle, and seek the Python one to the current position 
69129 */ 
70130static  NPY_INLINE  int 
71- npy_PyFile_DupClose (PyObject  * file , FILE *  handle )
131+ mpl_PyFile_DupClose (PyObject  * file , FILE *  handle ,  mpl_off_t   orig_pos )
72132{
133+     int  fd ;
73134    PyObject  * ret ;
74-     Py_ssize_t  position ;
135+     mpl_off_t  position ;
136+ 
75137    position  =  npy_ftell (handle );
138+ 
139+     /* Close the FILE* handle */ 
76140    fclose (handle );
77141
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 );
79160    if  (ret  ==  NULL ) {
80161        return  -1 ;
81162    }
@@ -84,7 +165,7 @@ npy_PyFile_DupClose(PyObject *file, FILE* handle)
84165}
85166
86167static  NPY_INLINE  int 
87- npy_PyFile_Check (PyObject  * file )
168+ mpl_PyFile_Check (PyObject  * file )
88169{
89170    int  fd ;
90171    fd  =  PyObject_AsFileDescriptor (file );
@@ -97,13 +178,14 @@ npy_PyFile_Check(PyObject *file)
97178
98179#else 
99180
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
102184
103185#endif 
104186
105187static  NPY_INLINE  PyObject * 
106- npy_PyFile_OpenFile (PyObject  * filename , const  char  * mode )
188+ mpl_PyFile_OpenFile (PyObject  * filename , const  char  * mode )
107189{
108190    PyObject  * open ;
109191    open  =  PyDict_GetItemString (PyEval_GetBuiltins (), "open" );
@@ -113,12 +195,8 @@ npy_PyFile_OpenFile(PyObject *filename, const char *mode)
113195    return  PyObject_CallFunction (open , "Os" , filename , mode );
114196}
115197
116- #endif  /* NPY_API_VERSION < 0x4 */ 
117- 
118- #if  NPY_API_VERSION  <  0x7  /* corresponds to Numpy 1.7 */ 
119- 
120198static  NPY_INLINE  int 
121- npy_PyFile_CloseFile (PyObject  * file )
199+ mpl_PyFile_CloseFile (PyObject  * file )
122200{
123201    PyObject  * ret ;
124202
@@ -130,6 +208,8 @@ npy_PyFile_CloseFile(PyObject *file)
130208    return  0 ;
131209}
132210
133- #endif  /* NPY_API_VERSION < 0x7 */ 
211+ #ifdef  __cplusplus 
212+ }
213+ #endif 
134214
135215#endif  /* ifndef __FILE_COMPAT_H__ */ 
0 commit comments