Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2592cbc

Browse files
committed
Rewrite convert_to_string using std::string.
Then we don't have to worry about managing the buffer ourselves.
1 parent 0d7ebc1 commit 2592cbc

File tree

2 files changed

+31
-71
lines changed

2 files changed

+31
-71
lines changed

src/_path.h

Lines changed: 27 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <vector>
99
#include <cmath>
1010
#include <algorithm>
11+
#include <string>
1112

1213
#include "agg_conv_contour.h"
1314
#include "agg_conv_curve.h"
@@ -1044,40 +1045,11 @@ void quad2cubic(double x0, double y0,
10441045
outy[2] = y2;
10451046
}
10461047

1047-
char *__append_to_string(char *p, char **buffer, size_t *buffersize,
1048-
const char *content)
1049-
{
1050-
for (const char *i = content; *i; ++i) {
1051-
if (p < *buffer) {
1052-
/* This is just an internal error */
1053-
return NULL;
1054-
}
1055-
if ((size_t)(p - *buffer) >= *buffersize) {
1056-
char *newbuffer;
1057-
ptrdiff_t diff = p - *buffer;
1058-
*buffersize *= 2;
1059-
newbuffer = (char *)realloc(*buffer, *buffersize);
1060-
if (newbuffer == NULL) {
1061-
return NULL;
1062-
}
1063-
*buffer = newbuffer;
1064-
p = *buffer + diff;
1065-
}
10661048

1067-
*p++ = *i;
1068-
}
1069-
1070-
return p;
1071-
}
1072-
1073-
1074-
char *__add_number(double val, char format_code, int precision,
1075-
char **buffer, char *p, size_t *buffersize)
1049+
void __add_number(double val, char format_code, int precision,
1050+
std::string& buffer)
10761051
{
1077-
char *result;
1078-
1079-
char *str;
1080-
str = PyOS_double_to_string(val, format_code, precision, 0, NULL);
1052+
char *str = PyOS_double_to_string(val, format_code, precision, 0, NULL);
10811053

10821054
// Delete trailing zeros and decimal point
10831055
char *q = str;
@@ -1090,7 +1062,7 @@ char *__add_number(double val, char format_code, int precision,
10901062
// Rewind through all the zeros
10911063
}
10921064

1093-
// If the end is a decimal qoint, delete that too
1065+
// If the end is a decimal point, delete that too
10941066
if (q >= str && *q == '.') {
10951067
--q;
10961068
}
@@ -1099,13 +1071,13 @@ char *__add_number(double val, char format_code, int precision,
10991071
++q;
11001072
*q = 0;
11011073

1102-
if ((result = __append_to_string(p, buffer, buffersize, str)) == NULL) {
1074+
try {
1075+
buffer += str;
1076+
} catch (std::bad_alloc& e) {
11031077
PyMem_Free(str);
1104-
return NULL;
1078+
throw e;
11051079
}
11061080
PyMem_Free(str);
1107-
1108-
return result;
11091081
}
11101082

11111083

@@ -1114,12 +1086,10 @@ int __convert_to_string(PathIterator &path,
11141086
int precision,
11151087
char **codes,
11161088
bool postfix,
1117-
char **buffer,
1118-
size_t *buffersize)
1089+
std::string& buffer)
11191090
{
11201091
const char format_code = 'f';
11211092

1122-
char *p = *buffer;
11231093
double x[3];
11241094
double y[3];
11251095
double last_x = 0.0;
@@ -1131,7 +1101,7 @@ int __convert_to_string(PathIterator &path,
11311101

11321102
while ((code = path.vertex(&x[0], &y[0])) != agg::path_cmd_stop) {
11331103
if (code == 0x4f) {
1134-
if ((p = __append_to_string(p, buffer, buffersize, codes[4])) == NULL) return 1;
1104+
buffer += codes[4];
11351105
} else if (code < 5) {
11361106
size = sizes[code - 1];
11371107

@@ -1151,19 +1121,19 @@ int __convert_to_string(PathIterator &path,
11511121
}
11521122

11531123
if (!postfix) {
1154-
if ((p = __append_to_string(p, buffer, buffersize, codes[code - 1])) == NULL) return 1;
1155-
if ((p = __append_to_string(p, buffer, buffersize, " ")) == NULL) return 1;
1124+
buffer += codes[code - 1];
1125+
buffer += ' ';
11561126
}
11571127

11581128
for (int i = 0; i < size; ++i) {
1159-
if ((p = __add_number(x[i], format_code, precision, buffer, p, buffersize)) == NULL) return 1;
1160-
if ((p = __append_to_string(p, buffer, buffersize, " ")) == NULL) return 1;
1161-
if ((p = __add_number(y[i], format_code, precision, buffer, p, buffersize)) == NULL) return 1;
1162-
if ((p = __append_to_string(p, buffer, buffersize, " ")) == NULL) return 1;
1129+
__add_number(x[i], format_code, precision, buffer);
1130+
buffer += ' ';
1131+
__add_number(y[i], format_code, precision, buffer);
1132+
buffer += ' ';
11631133
}
11641134

11651135
if (postfix) {
1166-
if ((p = __append_to_string(p, buffer, buffersize, codes[code - 1])) == NULL) return 1;
1136+
buffer += codes[code - 1];
11671137
}
11681138

11691139
last_x = x[size - 1];
@@ -1173,11 +1143,9 @@ int __convert_to_string(PathIterator &path,
11731143
return 2;
11741144
}
11751145

1176-
if ((p = __append_to_string(p, buffer, buffersize, "\n")) == NULL) return 1;
1146+
buffer += '\n';
11771147
}
11781148

1179-
*buffersize = p - *buffer;
1180-
11811149
return 0;
11821150
}
11831151

@@ -1190,9 +1158,9 @@ int convert_to_string(PathIterator &path,
11901158
int precision,
11911159
char **codes,
11921160
bool postfix,
1193-
char **buffer,
1194-
size_t *buffersize)
1161+
std::string& buffer)
11951162
{
1163+
size_t buffersize;
11961164
typedef agg::conv_transform<py::PathIterator> transformed_path_t;
11971165
typedef PathNanRemover<transformed_path_t> nan_removal_t;
11981166
typedef PathClipper<nan_removal_t> clipped_t;
@@ -1207,26 +1175,23 @@ int convert_to_string(PathIterator &path,
12071175
clipped_t clipped(nan_removed, do_clip && !path.has_curves(), clip_rect);
12081176
simplify_t simplified(clipped, simplify, path.simplify_threshold());
12091177

1210-
*buffersize = path.total_vertices() * (precision + 5) * 4;
1211-
if (*buffersize == 0) {
1178+
buffersize = path.total_vertices() * (precision + 5) * 4;
1179+
if (buffersize == 0) {
12121180
return 0;
12131181
}
12141182

12151183
if (sketch_params.scale != 0.0) {
1216-
*buffersize *= 10;
1184+
buffersize *= 10;
12171185
}
12181186

1219-
*buffer = (char *)malloc(*buffersize);
1220-
if (*buffer == NULL) {
1221-
return 1;
1222-
}
1187+
buffer.reserve(buffersize);
12231188

12241189
if (sketch_params.scale == 0.0) {
1225-
return __convert_to_string(simplified, precision, codes, postfix, buffer, buffersize);
1190+
return __convert_to_string(simplified, precision, codes, postfix, buffer);
12261191
} else {
12271192
curve_t curve(simplified);
12281193
sketch_t sketch(curve, sketch_params.scale, sketch_params.length, sketch_params.randomness);
1229-
return __convert_to_string(sketch, precision, codes, postfix, buffer, buffersize);
1194+
return __convert_to_string(sketch, precision, codes, postfix, buffer);
12301195
}
12311196

12321197
}

src/_path_wrapper.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -683,8 +683,7 @@ static PyObject *Py_convert_to_string(PyObject *self, PyObject *args, PyObject *
683683
PyObject *codesobj;
684684
char *codes[5];
685685
bool postfix;
686-
char *buffer = NULL;
687-
size_t buffersize;
686+
std::string buffer;
688687
PyObject *result;
689688
int status;
690689

@@ -735,11 +734,9 @@ static PyObject *Py_convert_to_string(PyObject *self, PyObject *args, PyObject *
735734
CALL_CPP("convert_to_string",
736735
(status = convert_to_string(
737736
path, trans, cliprect, simplify, sketch,
738-
precision, codes, postfix, &buffer,
739-
&buffersize)));
737+
precision, codes, postfix, buffer)));
740738

741739
if (status) {
742-
free(buffer);
743740
if (status == 1) {
744741
PyErr_SetString(PyExc_MemoryError, "Memory error");
745742
} else if (status == 2) {
@@ -748,14 +745,12 @@ static PyObject *Py_convert_to_string(PyObject *self, PyObject *args, PyObject *
748745
return NULL;
749746
}
750747

751-
if (buffersize == 0) {
748+
if (buffer.size() == 0) {
752749
result = PyBytes_FromString("");
753750
} else {
754-
result = PyBytes_FromStringAndSize(buffer, buffersize);
751+
result = PyBytes_FromStringAndSize(buffer.c_str(), buffer.size());
755752
}
756753

757-
free(buffer);
758-
759754
return result;
760755
}
761756

0 commit comments

Comments
 (0)