summaryrefslogtreecommitdiff
path: root/Modules
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-10-14 15:20:07 +0200
committerVictor Stinner <victor.stinner@gmail.com>2015-10-14 15:20:07 +0200
commitf0f6bd726242c16d09a68ff78a2012f792c3f8c9 (patch)
treed7222d27b5d9c582e90fedc0838d397b3c7b1f79 /Modules
parent710596f4ade3ac43ec90bf4f741a2da46c1b7640 (diff)
downloadcpython-f0f6bd726242c16d09a68ff78a2012f792c3f8c9.tar.gz
Refactor binascii.rledecode_hqx()
Rewrite the code to handle the output buffer.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/binascii.c53
1 files changed, 25 insertions, 28 deletions
diff --git a/Modules/binascii.c b/Modules/binascii.c
index a1070b7f86..ccd81faf94 100644
--- a/Modules/binascii.c
+++ b/Modules/binascii.c
@@ -784,7 +784,7 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
{
unsigned char *in_data, *out_data;
unsigned char in_byte, in_repeat;
- Py_ssize_t in_len, out_len, out_len_left;
+ Py_ssize_t in_len;
_PyBytesWriter writer;
in_data = data->buf;
@@ -800,15 +800,12 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
return PyErr_NoMemory();
/* Allocate a buffer of reasonable size. Resized when needed */
- out_len = in_len;
- out_data = _PyBytesWriter_Alloc(&writer, out_len);
+ out_data = _PyBytesWriter_Alloc(&writer, in_len);
if (out_data == NULL)
return NULL;
/* Use overallocation */
writer.overallocate = 1;
- out_len = writer.allocated;
- out_len_left = out_len;
/*
** We need two macros here to get/put bytes and handle
@@ -823,24 +820,6 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
b = *in_data++; \
} while(0)
-#define OUTBYTE(b) \
- do { \
- if ( --out_len_left < 0 ) { \
- if (in_len <= 0) { \
- /* We are done after this write, no need to \
- overallocate the buffer anymore */ \
- writer.overallocate = 0; \
- } \
- out_data = _PyBytesWriter_Resize(&writer, out_data, \
- writer.allocated + 1); \
- if (out_data == NULL) \
- goto error; \
- out_len_left = writer.allocated - out_len - 1; \
- out_len = writer.allocated; \
- } \
- *out_data++ = b; \
- } while(0)
-
/*
** Handle first byte separately (since we have to get angry
** in case of an orphaned RLE code).
@@ -849,6 +828,10 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
+ /* only 1 byte will be written, but 2 bytes were preallocated:
+ substract 1 byte to prevent overallocation */
+ writer.min_size--;
+
if (in_repeat != 0) {
/* Note Error, not Incomplete (which is at the end
** of the string only). This is a programmer error.
@@ -856,9 +839,9 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
PyErr_SetString(Error, "Orphaned RLE code at start");
goto error;
}
- OUTBYTE(RUNCHAR);
+ *out_data++ = RUNCHAR;
} else {
- OUTBYTE(in_byte);
+ *out_data++ = in_byte;
}
while( in_len > 0 ) {
@@ -866,18 +849,32 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
+ /* only 1 byte will be written, but 2 bytes were preallocated:
+ substract 1 byte to prevent overallocation */
+ writer.min_size--;
+
if ( in_repeat == 0 ) {
/* Just an escaped RUNCHAR value */
- OUTBYTE(RUNCHAR);
+ *out_data++ = RUNCHAR;
} else {
/* Pick up value and output a sequence of it */
in_byte = out_data[-1];
+
+ /* enlarge the buffer if needed */
+ if (in_repeat > 1) {
+ /* -1 because we already preallocated 1 byte */
+ out_data = _PyBytesWriter_Prepare(&writer, out_data,
+ in_repeat - 1);
+ if (out_data == NULL)
+ goto error;
+ }
+
while ( --in_repeat > 0 )
- OUTBYTE(in_byte);
+ *out_data++ = in_byte;
}
} else {
/* Normal byte */
- OUTBYTE(in_byte);
+ *out_data++ = in_byte;
}
}
return _PyBytesWriter_Finish(&writer, out_data);