11#define Py_LIMITED_API 0x030600F0
22#include " Python.h"
3+ #include " stdio_filebuf.h"
34
4- #include < cstdio>
5- #include < exception>
6- #include < iostream>
7- #include < locale>
5+ typedef std::pair<stdio_filebuf<char > *, FILE *> buffer_pair;
6+ // buffer_pair from_pyobject(PyObject *pyfile);
87
9- // https://android.googlesource.com/platform/frameworks/native/+/refs/heads/main/services/vr/performanced
10- // Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
11- // Copyright (c) 2016 Google, Inc.
12- //
13- // Permission is hereby granted, free of charge, to any person obtaining a copy
14- // of this software and associated documentation files (the "Software"), to deal
15- // in the Software without restriction, including without limitation the rights
16- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17- // copies of the Software, and to permit persons to whom the Software is
18- // furnished to do so, subject to the following conditions:
19- //
20- // The above copyright notice and this permission notice shall be included in
21- // all copies or substantial portions of the Software.
22- //
23- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29- // THE SOFTWARE.
8+ // struct PyIStream : public std::istream {
9+ // PyIStream(PyObject *pyfile) : buffers(from_pyobject(pyfile)), std::istream(std::get<0>(buffers)) {}
3010
31- template <class _CharT > class stdio_filebuf : public std ::basic_streambuf<_CharT, std::char_traits<_CharT>>
32- {
33- public:
34- typedef _CharT char_type;
35- typedef std::char_traits<char_type> traits_type;
36- typedef typename traits_type::int_type int_type;
37- typedef typename traits_type::pos_type pos_type;
38- typedef typename traits_type::off_type off_type;
39- typedef typename traits_type::state_type state_type;
40- explicit stdio_filebuf (FILE *__fp);
41- ~stdio_filebuf () override ;
11+ // ~PyIStream()
12+ // {
13+ // FILE *f;
14+ // stdio_filebuf<char> *buf;
4215
43- protected:
44- virtual int_type underflow () override ;
45- virtual int_type uflow () override ;
46- virtual int_type pbackfail (int_type __c = traits_type::eof()) override ;
47- virtual void imbue (const std::locale &__loc) override ;
16+ // if ((f = std::get<1>(buffers))) {
17+ // fclose(f);
18+ // }
19+ // if ((buf = std::get<0>(buffers))) {
20+ // delete buf;
21+ // }
22+ // }
4823
49- private:
50- FILE *__file_;
51- const std::codecvt<char_type, char , state_type> *__cv_;
52- state_type __st_;
53- int __encoding_;
54- int_type __last_consumed_;
55- bool __last_consumed_is_next_;
56- bool __always_noconv_;
57- stdio_filebuf (const stdio_filebuf &);
58- stdio_filebuf &operator =(const stdio_filebuf &);
59- int_type __getchar (bool __consume);
60- static const int __limit = 8 ;
61- };
62- template <class _CharT >
63- stdio_filebuf<_CharT>::stdio_filebuf(FILE *__fp) : __file_(__fp), __last_consumed_(traits_type::eof()), __last_consumed_is_next_(false )
64- {
65- imbue (this ->getloc ());
66- }
67- template <class _CharT > stdio_filebuf<_CharT>::~stdio_filebuf ()
68- {
69- if (__file_)
70- fclose (__file_);
71- }
72- template <class _CharT > void stdio_filebuf<_CharT>::imbue(const std::locale &__loc)
73- {
74- __cv_ = &std::use_facet<std::codecvt<char_type, char , state_type>>(__loc);
75- __encoding_ = __cv_->encoding ();
76- __always_noconv_ = __cv_->always_noconv ();
77- if (__encoding_ > __limit)
78- throw std::runtime_error (" unsupported locale for standard io" );
79- }
80- template <class _CharT > typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::underflow() { return __getchar (false ); }
81- template <class _CharT > typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::uflow() { return __getchar (true ); }
82- template <class _CharT > typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::__getchar(bool __consume)
83- {
84- if (__last_consumed_is_next_) {
85- int_type __result = __last_consumed_;
86- if (__consume) {
87- __last_consumed_ = traits_type::eof ();
88- __last_consumed_is_next_ = false ;
89- }
90- return __result;
91- }
92- char __extbuf[__limit];
93- int __nread = std::max (1 , __encoding_);
94- for (int __i = 0 ; __i < __nread; ++__i) {
95- int __c = getc (__file_);
96- if (__c == EOF)
97- return traits_type::eof ();
98- __extbuf[__i] = static_cast <char >(__c);
99- }
100- char_type __1buf;
101- if (__always_noconv_)
102- __1buf = static_cast <char_type>(__extbuf[0 ]);
103- else {
104- const char *__enxt;
105- char_type *__inxt;
106- std::codecvt_base::result __r;
107- do {
108- state_type __sv_st = __st_;
109- __r = __cv_->in (__st_, __extbuf, __extbuf + __nread, __enxt, &__1buf, &__1buf + 1 , __inxt);
110- switch (__r) {
111- case std::codecvt_base::ok:
112- break ;
113- case std::codecvt_base::partial:
114- __st_ = __sv_st;
115- if (__nread == sizeof (__extbuf))
116- return traits_type::eof ();
117- {
118- int __c = getc (__file_);
119- if (__c == EOF)
120- return traits_type::eof ();
121- __extbuf[__nread] = static_cast <char >(__c);
122- }
123- ++__nread;
124- break ;
125- case std::codecvt_base::error:
126- return traits_type::eof ();
127- case std::codecvt_base::noconv:
128- __1buf = static_cast <char_type>(__extbuf[0 ]);
129- break ;
130- }
131- } while (__r == std::codecvt_base::partial);
132- }
133- if (!__consume) {
134- for (int __i = __nread; __i > 0 ;) {
135- if (ungetc (traits_type::to_int_type (__extbuf[--__i]), __file_) == EOF)
136- return traits_type::eof ();
24+ // private:
25+ // buffer_pair buffers;
26+ // };
27+
28+ struct PyIStream : public std ::istream {
29+ PyIStream (PyObject *pyfile)
30+ {
31+ if (pyfile == Py_None) {
32+ throw std::runtime_error (" None is not a valid input stream" );
13733 }
138- } else
139- __last_consumed_ = traits_type::to_int_type (__1buf);
140- return traits_type::to_int_type (__1buf);
141- }
142- template <class _CharT > typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::pbackfail(int_type __c)
143- {
144- if (traits_type::eq_int_type (__c, traits_type::eof ())) {
145- if (!__last_consumed_is_next_) {
146- __c = __last_consumed_;
147- __last_consumed_is_next_ = !traits_type::eq_int_type (__last_consumed_, traits_type::eof ());
34+ auto fileno = PyObject_GetAttrString (pyfile, " fileno" );
35+ if (!fileno) {
36+ throw std::runtime_error (" Passed object has no fileno() method" );
14837 }
149- return __c;
150- }
151- if (__last_consumed_is_next_) {
152- char __extbuf[__limit];
153- char *__enxt;
154- const char_type __ci = traits_type::to_char_type (__last_consumed_);
155- const char_type *__inxt;
156- switch (__cv_->out (__st_, &__ci, &__ci + 1 , __inxt, __extbuf, __extbuf + sizeof (__extbuf), __enxt)) {
157- case std::codecvt_base::ok:
158- break ;
159- case std::codecvt_base::noconv:
160- __extbuf[0 ] = static_cast <char >(__last_consumed_);
161- __enxt = __extbuf + 1 ;
162- break ;
163- case std::codecvt_base::partial:
164- case std::codecvt_base::error:
165- return traits_type::eof ();
38+ fd = PyObject_AsFileDescriptor (pyfile);
39+ if (fd == -1 ) {
40+ throw std::runtime_error (" Failed to get file descriptor" );
16641 }
167- while (__enxt > __extbuf)
168- if (ungetc (*--__enxt, __file_) == EOF)
169- return traits_type::eof ();
170- }
171- __last_consumed_ = __c;
172- __last_consumed_is_next_ = true ;
173- return __c;
174- }
17542
176- typedef std::pair<stdio_filebuf<char > *, FILE *> buffer_pair;
177- static buffer_pair from_pyobject (PyObject *pyfile)
178- {
179- if (pyfile == Py_None) {
180- throw std::runtime_error (" None is not a valid input stream" );
181- }
182- auto fileno = PyObject_GetAttrString (pyfile, " fileno" );
183- if (!fileno) {
184- throw std::runtime_error (" Passed object has no fileno() method" );
185- }
43+ f = fdopen (fd, " r" );
44+ if (!f) {
45+ throw std::runtime_error (" Failed to open input stream" );
46+ }
18647
187- auto fd = PyObject_AsFileDescriptor (pyfile);
188- if (fd == -1 ) {
189- throw std::runtime_error (" Failed to get file descriptor" );
190- }
48+ buf = new stdio_filebuf<char >(f);
19149
192- auto f = fdopen (fd, " r" );
193- if (!f) {
194- throw std::runtime_error (" Failed to open input stream" );
50+ init (buf);
19551 }
19652
197- return buffer_pair (new stdio_filebuf<char >(f), f);
198- }
199-
200- struct PyIStream : public std ::istream {
201- PyIStream (PyObject *pyfile) : buffers(from_pyobject(pyfile)), std::istream(std::get<0 >(buffers)) {}
202-
20353 ~PyIStream ()
20454 {
205- FILE *f;
206- stdio_filebuf<char > *buf;
207-
208- if ((f = std::get<1 >(buffers))) {
55+ if (f) {
20956 fclose (f);
21057 }
211- if (( buf = std::get< 0 >(buffers)) ) {
58+ if (buf) {
21259 free (buf);
21360 }
21461 }
21562
21663private:
217- buffer_pair buffers;
64+ int fd = -1 ;
65+ FILE *f = nullptr ;
21866 stdio_filebuf<char > *buf = nullptr ;
21967};
0 commit comments