Skip to content

Commit c2e98b6

Browse files
committed
Fix libc++ compatibility
1 parent f073303 commit c2e98b6

File tree

4 files changed

+167
-161
lines changed

4 files changed

+167
-161
lines changed

.clang-format

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Default Linux style
2+
BasedOnStyle: LLVM
3+
IndentWidth: 4
4+
UseTab: Never
5+
BreakBeforeBraces: Linux
6+
AllowShortIfStatementsOnASingleLine: false
7+
IndentCaseLabels: false
8+
ColumnLimit: 150
9+
AccessModifierOffset: -4

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ SOURCES = $(SRC_DIR)/libparse_wrap.cpp $(SRC_DIR)/libparse.cpp
66
OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES))
77
HEADERS = $(SRC_DIR)/libparse.h $(SRC_DIR)/py_iostream.h
88

9-
CXXFLAGS += -g -std=c++17 -I$(shell python3 -c "import sysconfig; print(sysconfig.get_path('include'))")
9+
CXXFLAGS += -g -std=c++11 -I$(shell python3 -c "import sysconfig; print(sysconfig.get_path('include'))")
1010

1111

1212
all: _libparse.so

libparse/py_iostream.h

Lines changed: 155 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#define Py_LIMITED_API 0x030600F0
22
#include "Python.h"
3+
34
#include <cstdio>
45
#include <iostream>
56
#include <locale>
@@ -25,198 +26,193 @@
2526
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2627
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2728
// THE SOFTWARE.
28-
template <class _CharT>
29-
class stdio_filebuf
30-
: public std::basic_streambuf<_CharT, std::char_traits<_CharT>> {
29+
30+
template <class _CharT> class stdio_filebuf : public std::basic_streambuf<_CharT, std::char_traits<_CharT>>
31+
{
3132
public:
32-
typedef _CharT char_type;
33-
typedef std::char_traits<char_type> traits_type;
34-
typedef typename traits_type::int_type int_type;
35-
typedef typename traits_type::pos_type pos_type;
36-
typedef typename traits_type::off_type off_type;
37-
typedef typename traits_type::state_type state_type;
38-
explicit stdio_filebuf(FILE *__fp);
39-
~stdio_filebuf() override;
33+
typedef _CharT char_type;
34+
typedef std::char_traits<char_type> traits_type;
35+
typedef typename traits_type::int_type int_type;
36+
typedef typename traits_type::pos_type pos_type;
37+
typedef typename traits_type::off_type off_type;
38+
typedef typename traits_type::state_type state_type;
39+
explicit stdio_filebuf(FILE *__fp);
40+
~stdio_filebuf() override;
4041

4142
protected:
42-
virtual int_type underflow() override;
43-
virtual int_type uflow() override;
44-
virtual int_type pbackfail(int_type __c = traits_type::eof()) override;
45-
virtual void imbue(const std::locale &__loc) override;
43+
virtual int_type underflow() override;
44+
virtual int_type uflow() override;
45+
virtual int_type pbackfail(int_type __c = traits_type::eof()) override;
46+
virtual void imbue(const std::locale &__loc) override;
4647

4748
private:
48-
FILE *__file_;
49-
const std::codecvt<char_type, char, state_type> *__cv_;
50-
state_type __st_;
51-
int __encoding_;
52-
int_type __last_consumed_;
53-
bool __last_consumed_is_next_;
54-
bool __always_noconv_;
55-
stdio_filebuf(const stdio_filebuf &);
56-
stdio_filebuf &operator=(const stdio_filebuf &);
57-
int_type __getchar(bool __consume);
58-
static const int __limit = 8;
49+
FILE *__file_;
50+
const std::codecvt<char_type, char, state_type> *__cv_;
51+
state_type __st_;
52+
int __encoding_;
53+
int_type __last_consumed_;
54+
bool __last_consumed_is_next_;
55+
bool __always_noconv_;
56+
stdio_filebuf(const stdio_filebuf &);
57+
stdio_filebuf &operator=(const stdio_filebuf &);
58+
int_type __getchar(bool __consume);
59+
static const int __limit = 8;
5960
};
6061
template <class _CharT>
61-
stdio_filebuf<_CharT>::stdio_filebuf(FILE *__fp)
62-
: __file_(__fp), __last_consumed_(traits_type::eof()),
63-
__last_consumed_is_next_(false) {
64-
imbue(this->getloc());
65-
}
66-
template <class _CharT> stdio_filebuf<_CharT>::~stdio_filebuf() {
67-
if (__file_)
68-
fclose(__file_);
69-
}
70-
template <class _CharT>
71-
void stdio_filebuf<_CharT>::imbue(const std::locale &__loc) {
72-
__cv_ = &std::use_facet<std::codecvt<char_type, char, state_type>>(__loc);
73-
__encoding_ = __cv_->encoding();
74-
__always_noconv_ = __cv_->always_noconv();
75-
if (__encoding_ > __limit)
76-
std::__throw_runtime_error("unsupported locale for standard io");
62+
stdio_filebuf<_CharT>::stdio_filebuf(FILE *__fp) : __file_(__fp), __last_consumed_(traits_type::eof()), __last_consumed_is_next_(false)
63+
{
64+
imbue(this->getloc());
7765
}
78-
template <class _CharT>
79-
typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::underflow() {
80-
return __getchar(false);
66+
template <class _CharT> stdio_filebuf<_CharT>::~stdio_filebuf()
67+
{
68+
if (__file_)
69+
fclose(__file_);
8170
}
82-
template <class _CharT>
83-
typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::uflow() {
84-
return __getchar(true);
71+
template <class _CharT> void stdio_filebuf<_CharT>::imbue(const std::locale &__loc)
72+
{
73+
__cv_ = &std::use_facet<std::codecvt<char_type, char, state_type>>(__loc);
74+
__encoding_ = __cv_->encoding();
75+
__always_noconv_ = __cv_->always_noconv();
76+
if (__encoding_ > __limit)
77+
std::__throw_runtime_error("unsupported locale for standard io");
8578
}
86-
template <class _CharT>
87-
typename stdio_filebuf<_CharT>::int_type
88-
stdio_filebuf<_CharT>::__getchar(bool __consume) {
89-
if (__last_consumed_is_next_) {
90-
int_type __result = __last_consumed_;
91-
if (__consume) {
92-
__last_consumed_ = traits_type::eof();
93-
__last_consumed_is_next_ = false;
79+
template <class _CharT> typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::underflow() { return __getchar(false); }
80+
template <class _CharT> typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::uflow() { return __getchar(true); }
81+
template <class _CharT> typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::__getchar(bool __consume)
82+
{
83+
if (__last_consumed_is_next_) {
84+
int_type __result = __last_consumed_;
85+
if (__consume) {
86+
__last_consumed_ = traits_type::eof();
87+
__last_consumed_is_next_ = false;
88+
}
89+
return __result;
9490
}
95-
return __result;
96-
}
97-
char __extbuf[__limit];
98-
int __nread = std::max(1, __encoding_);
99-
for (int __i = 0; __i < __nread; ++__i) {
100-
int __c = getc(__file_);
101-
if (__c == EOF)
102-
return traits_type::eof();
103-
__extbuf[__i] = static_cast<char>(__c);
104-
}
105-
char_type __1buf;
106-
if (__always_noconv_)
107-
__1buf = static_cast<char_type>(__extbuf[0]);
108-
else {
109-
const char *__enxt;
110-
char_type *__inxt;
111-
std::codecvt_base::result __r;
112-
do {
113-
state_type __sv_st = __st_;
114-
__r = __cv_->in(__st_, __extbuf, __extbuf + __nread, __enxt, &__1buf,
115-
&__1buf + 1, __inxt);
116-
switch (__r) {
117-
case std::codecvt_base::ok:
118-
break;
119-
case std::codecvt_base::partial:
120-
__st_ = __sv_st;
121-
if (__nread == sizeof(__extbuf))
122-
return traits_type::eof();
123-
{
124-
int __c = getc(__file_);
125-
if (__c == EOF)
91+
char __extbuf[__limit];
92+
int __nread = std::max(1, __encoding_);
93+
for (int __i = 0; __i < __nread; ++__i) {
94+
int __c = getc(__file_);
95+
if (__c == EOF)
12696
return traits_type::eof();
127-
__extbuf[__nread] = static_cast<char>(__c);
128-
}
129-
++__nread;
130-
break;
131-
case std::codecvt_base::error:
132-
return traits_type::eof();
133-
case std::codecvt_base::noconv:
97+
__extbuf[__i] = static_cast<char>(__c);
98+
}
99+
char_type __1buf;
100+
if (__always_noconv_)
134101
__1buf = static_cast<char_type>(__extbuf[0]);
135-
break;
136-
}
137-
} while (__r == std::codecvt_base::partial);
138-
}
139-
if (!__consume) {
140-
for (int __i = __nread; __i > 0;) {
141-
if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF)
142-
return traits_type::eof();
102+
else {
103+
const char *__enxt;
104+
char_type *__inxt;
105+
std::codecvt_base::result __r;
106+
do {
107+
state_type __sv_st = __st_;
108+
__r = __cv_->in(__st_, __extbuf, __extbuf + __nread, __enxt, &__1buf, &__1buf + 1, __inxt);
109+
switch (__r) {
110+
case std::codecvt_base::ok:
111+
break;
112+
case std::codecvt_base::partial:
113+
__st_ = __sv_st;
114+
if (__nread == sizeof(__extbuf))
115+
return traits_type::eof();
116+
{
117+
int __c = getc(__file_);
118+
if (__c == EOF)
119+
return traits_type::eof();
120+
__extbuf[__nread] = static_cast<char>(__c);
121+
}
122+
++__nread;
123+
break;
124+
case std::codecvt_base::error:
125+
return traits_type::eof();
126+
case std::codecvt_base::noconv:
127+
__1buf = static_cast<char_type>(__extbuf[0]);
128+
break;
129+
}
130+
} while (__r == std::codecvt_base::partial);
143131
}
144-
} else
145-
__last_consumed_ = traits_type::to_int_type(__1buf);
146-
return traits_type::to_int_type(__1buf);
132+
if (!__consume) {
133+
for (int __i = __nread; __i > 0;) {
134+
if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF)
135+
return traits_type::eof();
136+
}
137+
} else
138+
__last_consumed_ = traits_type::to_int_type(__1buf);
139+
return traits_type::to_int_type(__1buf);
147140
}
148-
template <class _CharT>
149-
typename stdio_filebuf<_CharT>::int_type
150-
stdio_filebuf<_CharT>::pbackfail(int_type __c) {
151-
if (traits_type::eq_int_type(__c, traits_type::eof())) {
152-
if (!__last_consumed_is_next_) {
153-
__c = __last_consumed_;
154-
__last_consumed_is_next_ =
155-
!traits_type::eq_int_type(__last_consumed_, traits_type::eof());
141+
template <class _CharT> typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::pbackfail(int_type __c)
142+
{
143+
if (traits_type::eq_int_type(__c, traits_type::eof())) {
144+
if (!__last_consumed_is_next_) {
145+
__c = __last_consumed_;
146+
__last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_, traits_type::eof());
147+
}
148+
return __c;
156149
}
157-
return __c;
158-
}
159-
if (__last_consumed_is_next_) {
160-
char __extbuf[__limit];
161-
char *__enxt;
162-
const char_type __ci = traits_type::to_char_type(__last_consumed_);
163-
const char_type *__inxt;
164-
switch (__cv_->out(__st_, &__ci, &__ci + 1, __inxt, __extbuf,
165-
__extbuf + sizeof(__extbuf), __enxt)) {
166-
case std::codecvt_base::ok:
167-
break;
168-
case std::codecvt_base::noconv:
169-
__extbuf[0] = static_cast<char>(__last_consumed_);
170-
__enxt = __extbuf + 1;
171-
break;
172-
case std::codecvt_base::partial:
173-
case std::codecvt_base::error:
174-
return traits_type::eof();
150+
if (__last_consumed_is_next_) {
151+
char __extbuf[__limit];
152+
char *__enxt;
153+
const char_type __ci = traits_type::to_char_type(__last_consumed_);
154+
const char_type *__inxt;
155+
switch (__cv_->out(__st_, &__ci, &__ci + 1, __inxt, __extbuf, __extbuf + sizeof(__extbuf), __enxt)) {
156+
case std::codecvt_base::ok:
157+
break;
158+
case std::codecvt_base::noconv:
159+
__extbuf[0] = static_cast<char>(__last_consumed_);
160+
__enxt = __extbuf + 1;
161+
break;
162+
case std::codecvt_base::partial:
163+
case std::codecvt_base::error:
164+
return traits_type::eof();
165+
}
166+
while (__enxt > __extbuf)
167+
if (ungetc(*--__enxt, __file_) == EOF)
168+
return traits_type::eof();
175169
}
176-
while (__enxt > __extbuf)
177-
if (ungetc(*--__enxt, __file_) == EOF)
178-
return traits_type::eof();
179-
}
180-
__last_consumed_ = __c;
181-
__last_consumed_is_next_ = true;
182-
return __c;
170+
__last_consumed_ = __c;
171+
__last_consumed_is_next_ = true;
172+
return __c;
183173
}
184174

185-
struct PyIStream : public std::istream {
186-
PyIStream(PyObject *pyfile) {
175+
typedef std::pair<stdio_filebuf<char> *, FILE *> buffer_pair;
176+
static buffer_pair from_pyobject(PyObject *pyfile)
177+
{
187178
if (pyfile == Py_None) {
188-
throw std::runtime_error("None is not a valid input stream");
179+
throw std::runtime_error("None is not a valid input stream");
189180
}
190181
auto fileno = PyObject_GetAttrString(pyfile, "fileno");
191182
if (!fileno) {
192-
throw std::runtime_error("Passed object has no fileno() method");
183+
throw std::runtime_error("Passed object has no fileno() method");
193184
}
194-
fd = PyObject_AsFileDescriptor(pyfile);
185+
186+
auto fd = PyObject_AsFileDescriptor(pyfile);
195187
if (fd == -1) {
196-
throw std::runtime_error("Failed to get file descriptor");
188+
throw std::runtime_error("Failed to get file descriptor");
197189
}
198190

199-
f = fdopen(fd, "r");
191+
auto f = fdopen(fd, "r");
200192
if (!f) {
201-
throw std::runtime_error("Failed to open input stream");
193+
throw std::runtime_error("Failed to open input stream");
202194
}
203195

204-
buf = new stdio_filebuf<char>(f);
196+
return buffer_pair(new stdio_filebuf<char>(f), f);
197+
}
205198

206-
init(buf);
207-
}
199+
struct PyIStream : public std::istream {
200+
PyIStream(PyObject *pyfile) : buffers(from_pyobject(pyfile)), std::istream(std::get<0>(buffers)) {}
208201

209-
~PyIStream() {
210-
if (f) {
211-
fclose(f);
212-
}
213-
if (buf) {
214-
free(buf);
202+
~PyIStream()
203+
{
204+
FILE *f;
205+
stdio_filebuf<char> *buf;
206+
207+
if ((f = std::get<1>(buffers))) {
208+
fclose(f);
209+
}
210+
if ((buf = std::get<0>(buffers))) {
211+
free(buf);
212+
}
215213
}
216-
}
217214

218215
private:
219-
int fd = -1;
220-
FILE *f = nullptr;
221-
stdio_filebuf<char> *buf = nullptr;
216+
buffer_pair buffers;
217+
stdio_filebuf<char> *buf = nullptr;
222218
};

shell.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
with pkgs; mkShell {
55
buildInputs = [
66
swig
7-
clang
7+
clang_16
8+
clang-tools_16
89
python3Full
910
valgrind
1011
twine

0 commit comments

Comments
 (0)