Skip to content

Commit 8f69da3

Browse files
author
Arzaroth Lekva
committed
using Py_buffer to allow all type of data, instead just bytearray & add flag raw to unparse
1 parent 7f452da commit 8f69da3

File tree

4 files changed

+110
-81
lines changed

4 files changed

+110
-81
lines changed

rapidxml/c_ext/src/base_object.cpp

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,28 @@ static PyObject* rapidxml_BaseObject_richcmp(PyObject* obj1,
8686
}
8787

8888
static PyObject* rapidxml_BaseObject_getname(rapidxml_BaseObject* self,
89-
void* closure) {
89+
void* closure) {
90+
PyObject* res;
91+
9092
if (self->underlying_obj == NULL) {
91-
return Py_BuildValue("s", "");
93+
res = Py_BuildValue("s", "");
94+
} else {
95+
res = Py_BuildValue("s", self->underlying_obj->name());
96+
#if PY_MAJOR_VERSION >= 3
97+
if (res == NULL && PyErr_Occurred()) {
98+
res = Py_BuildValue("y",
99+
self->underlying_obj->name(),
100+
self->underlying_obj->name_size());
101+
}
102+
#endif
92103
}
93-
return Py_BuildValue("s", self->underlying_obj->name());
104+
return res;
94105
}
95106

96107
static int rapidxml_BaseObject_setname(rapidxml_BaseObject* self,
97108
PyObject* arg,
98109
void* closure) {
99-
const char* name;
110+
Py_buffer name;
100111

101112
if (self->underlying_obj == NULL || self->document == NULL) {
102113
PyErr_SetString(rapidxml_RapidXmlError,
@@ -105,39 +116,39 @@ static int rapidxml_BaseObject_setname(rapidxml_BaseObject* self,
105116
}
106117
if (arg == NULL) {
107118
PyErr_SetString(PyExc_TypeError,
108-
"name attribute must not be null");
109-
return -1;
110-
}
111-
if (!
112-
#if PY_MAJOR_VERSION >= 3
113-
PyUnicode_Check(arg)
114-
#else
115-
PyString_Check(arg)
116-
#endif
117-
) {
118-
PyErr_SetString(PyExc_TypeError,
119-
"name attribute must be a string");
119+
"Cannot delete name");
120120
return -1;
121121
}
122-
if (!PyArg_Parse(arg, "s", &name)) {
122+
if (!PyArg_Parse(arg, "s*", &name)) {
123123
return -1;
124124
}
125-
self->underlying_obj->name(self->document->allocate_string(name));
125+
self->underlying_obj->name(self->document->allocate_string(static_cast<const char*>(name.buf)));
126126
return 0;
127127
}
128128

129129
static PyObject* rapidxml_BaseObject_getvalue(rapidxml_BaseObject* self,
130130
void* closure) {
131+
PyObject* res;
132+
131133
if (self->underlying_obj == NULL) {
132-
return Py_BuildValue("s", "");
134+
res = Py_BuildValue("s", "");
135+
} else {
136+
res = Py_BuildValue("s", self->underlying_obj->value());
137+
#if PY_MAJOR_VERSION >= 3
138+
if (res == NULL && PyErr_Occurred()) {
139+
res = Py_BuildValue("y",
140+
self->underlying_obj->value(),
141+
self->underlying_obj->value_size());
142+
}
143+
#endif
133144
}
134-
return Py_BuildValue("s", self->underlying_obj->value());
145+
return res;
135146
}
136147

137148
static int rapidxml_BaseObject_setvalue(rapidxml_BaseObject* self,
138149
PyObject* arg,
139150
void* closure) {
140-
const char* value;
151+
Py_buffer value;
141152

142153
if (self->underlying_obj == NULL || self->document == NULL) {
143154
PyErr_SetString(rapidxml_RapidXmlError,
@@ -146,24 +157,13 @@ static int rapidxml_BaseObject_setvalue(rapidxml_BaseObject* self,
146157
}
147158
if (arg == NULL) {
148159
PyErr_SetString(PyExc_TypeError,
149-
"value attribute must not be null");
150-
return -1;
151-
}
152-
if (!
153-
#if PY_MAJOR_VERSION >= 3
154-
PyUnicode_Check(arg)
155-
#else
156-
PyString_Check(arg)
157-
#endif
158-
) {
159-
PyErr_SetString(PyExc_TypeError,
160-
"value attribute must be a string");
160+
"Cannot delete value");
161161
return -1;
162162
}
163-
if (!PyArg_Parse(arg, "s", &value)) {
163+
if (!PyArg_Parse(arg, "s*", &value)) {
164164
return -1;
165165
}
166-
self->underlying_obj->value(self->document->allocate_string(value));
166+
self->underlying_obj->value(self->document->allocate_string(static_cast<const char*>(value.buf)));
167167
return 0;
168168
}
169169

rapidxml/c_ext/src/common.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@ int _parse_args_for_name(PyObject* args,
1717
PyObject* kwds,
1818
const char** name) {
1919
char kw_name[] = "name";
20+
Py_buffer buf = {0};
2021

2122
static char* kwlist[] = {kw_name, NULL};
22-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist,
23-
name)) {
23+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s*", kwlist,
24+
&buf)) {
2425
return false;
2526
}
27+
if (buf.buf) {
28+
*name = static_cast<const char*>(buf.buf);
29+
}
2630
return true;
2731
}
2832

rapidxml/c_ext/src/document_object.cpp

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,42 +23,23 @@ static void rapidxml_DocumentObject_dealloc(rapidxml_DocumentObject* self) {
2323
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
2424
}
2525

26-
static PyObject* rapidxml_DocumentObject_parse(rapidxml_DocumentObject* self,
27-
PyObject* args,
28-
PyObject* kwds) {
29-
const char* text = NULL;
30-
PyObject* text_obj = NULL;
31-
PyObject* from_file_obj = NULL;
32-
char kw_text[] = "text";
33-
char kw_from_file[] = "from_file";
26+
static int _parse(rapidxml_DocumentObject* self,
27+
Py_buffer* text_buff,
28+
bool from_file) {
29+
const char* text;
3430
std::vector<char> text_vector;
3531

36-
static char* kwlist[] = {kw_text, kw_from_file, NULL};
37-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
38-
&text_obj, &from_file_obj)) {
39-
return NULL;
40-
}
41-
42-
if ((from_file_obj != NULL) && PyObject_IsTrue(from_file_obj)) {
43-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O", kwlist,
44-
&text, &from_file_obj)) {
45-
return NULL;
46-
}
32+
text = static_cast<const char*>(text_buff->buf);
33+
if (from_file) {
4734
std::ifstream f(text, std::ios::binary);
4835
if (f.fail()) {
4936
PyErr_SetString(rapidxml_RapidXmlError, strerror(errno));
50-
return NULL;
37+
return 0;
5138
}
5239
text_vector = std::vector<char>((std::istreambuf_iterator<char>(f)),
5340
std::istreambuf_iterator<char>());
5441
text_vector.push_back(0);
5542
text = &text_vector[0];
56-
} else {
57-
if (!PyByteArray_Check(text_obj)) {
58-
PyErr_SetString(PyExc_TypeError, "argument 1 must be bytearray");
59-
return NULL;
60-
}
61-
text = PyByteArray_AsString(text_obj);
6243
}
6344
try {
6445
self->base.base.document->clear();
@@ -67,6 +48,27 @@ static PyObject* rapidxml_DocumentObject_parse(rapidxml_DocumentObject* self,
6748
(self->base.base.document->allocate_string(text));
6849
} catch (rapidxml::parse_error &e) {
6950
PyErr_SetString(rapidxml_RapidXmlError, e.what());
51+
return 0;
52+
}
53+
return 1;
54+
}
55+
56+
static PyObject* rapidxml_DocumentObject_parse(rapidxml_DocumentObject* self,
57+
PyObject* args,
58+
PyObject* kwds) {
59+
Py_buffer text_buff;
60+
PyObject* from_file_obj = NULL;
61+
char kw_text[] = "text";
62+
char kw_from_file[] = "from_file";
63+
64+
static char* kwlist[] = {kw_text, kw_from_file, NULL};
65+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s*|O", kwlist,
66+
&text_buff, &from_file_obj)) {
67+
return NULL;
68+
}
69+
70+
if (!_parse(self, &text_buff,
71+
(from_file_obj != NULL) && PyObject_IsTrue(from_file_obj))) {
7072
return NULL;
7173
}
7274
Py_INCREF(Py_None);
@@ -76,7 +78,7 @@ static PyObject* rapidxml_DocumentObject_parse(rapidxml_DocumentObject* self,
7678
static int rapidxml_DocumentObject_init(rapidxml_DocumentObject* self,
7779
PyObject* args,
7880
PyObject* kwds) {
79-
PyObject* text_obj = NULL;
81+
Py_buffer text_buff = {0};
8082
PyObject* from_file_obj = NULL;
8183
char kw_text[] = "text";
8284
char kw_from_file[] = "from_file";
@@ -85,62 +87,70 @@ static int rapidxml_DocumentObject_init(rapidxml_DocumentObject* self,
8587
return -1;
8688
}
8789
static char* kwlist[] = {kw_text, kw_from_file, NULL};
88-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist,
89-
&text_obj, &from_file_obj)) {
90+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s*O", kwlist,
91+
&text_buff, &from_file_obj)) {
9092
return -1;
9193
}
9294
self->base.base.underlying_obj = new rapidxml::xml_document<>();
9395
self->base.base.document = static_cast<rapidxml::xml_document<>*>(self->base.base.underlying_obj);
94-
if (text_obj && PyObject_IsTrue(text_obj)) {
95-
rapidxml_DocumentObject_parse(self, args, kwds);
96+
if (text_buff.buf) {
97+
return _parse(self, &text_buff, (from_file_obj != NULL) && PyObject_IsTrue(from_file_obj)) - 1;
9698
}
9799
return 0;
98100
}
99101

100102
static PyObject* rapidxml_DocumentObject_allocate_node(rapidxml_DocumentObject* self,
101103
PyObject* args,
102104
PyObject* kwds) {
103-
const char* name = NULL;
104-
const char* value = NULL;
105+
const char* name;
106+
Py_buffer name_buff = {0};
107+
const char* value;
108+
Py_buffer value_buff = {0};
105109
char kw_name[] = "name";
106110
char kw_value[] = "value";
107111
rapidxml::xml_node<>* node;
108112

109113
static char* kwlist[] = {kw_name, kw_value, NULL};
110-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ss", kwlist,
111-
&name, &value)) {
114+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s*s*", kwlist,
115+
&name_buff, &value_buff)) {
112116
Py_INCREF(Py_None);
113117
return Py_None;
114118
}
119+
name = static_cast<const char*>(name_buff.buf);
115120
if (name) {
116121
name = self->base.base.document->allocate_string(name);
117122
}
123+
value = static_cast<const char*>(value_buff.buf);
118124
if (value) {
119125
value = self->base.base.document->allocate_string(value);
120126
}
121127
node = self->base.base.document->allocate_node(rapidxml::node_element, name, value);
122128
return _bind_result(reinterpret_cast<rapidxml_BaseObject*>(self),
123129
node, &rapidxml_NodeType);
124130
}
125-
131+
#include <iostream>
126132
static PyObject* rapidxml_DocumentObject_allocate_attribute(rapidxml_DocumentObject* self,
127133
PyObject* args,
128134
PyObject* kwds) {
129-
const char* name = NULL;
130-
const char* value = NULL;
135+
const char* name;
136+
Py_buffer name_buff = {0};
137+
const char* value;
138+
Py_buffer value_buff = {0};
131139
char kw_name[] = "name";
132140
char kw_value[] = "value";
133141
rapidxml::xml_attribute<>* attribute;
134142

135143
static char* kwlist[] = {kw_name, kw_value, NULL};
136-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ss", kwlist,
137-
&name, &value)) {
144+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s*s*", kwlist,
145+
&name_buff, &value_buff)) {
138146
Py_INCREF(Py_None);
139147
return Py_None;
140148
}
149+
name = static_cast<const char*>(name_buff.buf);
141150
if (name) {
142151
name = self->base.base.document->allocate_string(name);
143152
}
153+
value = static_cast<const char*>(value_buff.buf);
144154
if (value) {
145155
value = self->base.base.document->allocate_string(value);
146156
}

rapidxml/c_ext/src/node_object.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,17 +405,32 @@ static PyObject* rapidxml_NodeObject_unparse(rapidxml_NodeObject* self,
405405
PyObject* args,
406406
PyObject* kwds) {
407407
PyObject* pretty_obj = NULL;
408+
PyObject* raw_obj = NULL;
409+
PyObject* res;
408410
std::string xml;
409411
char kw_pretty[] = "pretty";
412+
char kw_raw[] = "raw";
410413

411-
static char* kwlist[] = {kw_pretty, NULL};
412-
PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &pretty_obj);
414+
static char* kwlist[] = {kw_pretty, kw_raw, NULL};
415+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist,
416+
&pretty_obj, &raw_obj)) {
417+
return NULL;
418+
}
413419

414420
rapidxml::print(std::back_inserter(xml),
415421
*(static_cast<rapidxml::xml_node<>*>(self->base.underlying_obj)),
416422
((pretty_obj == NULL) || PyObject_Not(pretty_obj))
417423
? rapidxml::print_no_indenting : 0);
418-
return Py_BuildValue("s", xml.c_str());
424+
if ((raw_obj == NULL) || PyObject_Not(raw_obj)
425+
#if PY_MAJOR_VERSION < 3
426+
|| true
427+
#endif
428+
) {
429+
res = Py_BuildValue("s", xml.c_str());
430+
} else {
431+
res = Py_BuildValue("y", xml.c_str(), xml.length());
432+
}
433+
return res;
419434
}
420435

421436
static PyObject* rapidxml_NodeObject___str__(rapidxml_NodeObject* self) {
@@ -432,7 +447,7 @@ static PyObject* rapidxml_NodeObject___repr__(rapidxml_NodeObject* self) {
432447
PyObject* args;
433448
PyObject* res;
434449

435-
args = Py_BuildValue("(O)", Py_False);
450+
args = Py_BuildValue("()");
436451
res = rapidxml_NodeObject_unparse(self, args, NULL);
437452
Py_DECREF(args);
438453
return res;

0 commit comments

Comments
 (0)