Skip to content

Commit f9c9a3f

Browse files
committed
Refactor binascii.rledecode_hqx()
Rewrite the code to handle the output buffer.
1 parent 1bfe930 commit f9c9a3f

1 file changed

Lines changed: 25 additions & 28 deletions

File tree

Modules/binascii.c

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
784784
{
785785
unsigned char *in_data, *out_data;
786786
unsigned char in_byte, in_repeat;
787-
Py_ssize_t in_len, out_len, out_len_left;
787+
Py_ssize_t in_len;
788788
_PyBytesWriter writer;
789789

790790
in_data = data->buf;
@@ -800,15 +800,12 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
800800
return PyErr_NoMemory();
801801

802802
/* Allocate a buffer of reasonable size. Resized when needed */
803-
out_len = in_len;
804-
out_data = _PyBytesWriter_Alloc(&writer, out_len);
803+
out_data = _PyBytesWriter_Alloc(&writer, in_len);
805804
if (out_data == NULL)
806805
return NULL;
807806

808807
/* Use overallocation */
809808
writer.overallocate = 1;
810-
out_len = writer.allocated;
811-
out_len_left = out_len;
812809

813810
/*
814811
** We need two macros here to get/put bytes and handle
@@ -823,24 +820,6 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
823820
b = *in_data++; \
824821
} while(0)
825822

826-
#define OUTBYTE(b) \
827-
do { \
828-
if ( --out_len_left < 0 ) { \
829-
if (in_len <= 0) { \
830-
/* We are done after this write, no need to \
831-
overallocate the buffer anymore */ \
832-
writer.overallocate = 0; \
833-
} \
834-
out_data = _PyBytesWriter_Resize(&writer, out_data, \
835-
writer.allocated + 1); \
836-
if (out_data == NULL) \
837-
goto error; \
838-
out_len_left = writer.allocated - out_len - 1; \
839-
out_len = writer.allocated; \
840-
} \
841-
*out_data++ = b; \
842-
} while(0)
843-
844823
/*
845824
** Handle first byte separately (since we have to get angry
846825
** in case of an orphaned RLE code).
@@ -849,35 +828,53 @@ binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data)
849828

850829
if (in_byte == RUNCHAR) {
851830
INBYTE(in_repeat);
831+
/* only 1 byte will be written, but 2 bytes were preallocated:
832+
substract 1 byte to prevent overallocation */
833+
writer.min_size--;
834+
852835
if (in_repeat != 0) {
853836
/* Note Error, not Incomplete (which is at the end
854837
** of the string only). This is a programmer error.
855838
*/
856839
PyErr_SetString(Error, "Orphaned RLE code at start");
857840
goto error;
858841
}
859-
OUTBYTE(RUNCHAR);
842+
*out_data++ = RUNCHAR;
860843
} else {
861-
OUTBYTE(in_byte);
844+
*out_data++ = in_byte;
862845
}
863846

864847
while( in_len > 0 ) {
865848
INBYTE(in_byte);
866849

867850
if (in_byte == RUNCHAR) {
868851
INBYTE(in_repeat);
852+
/* only 1 byte will be written, but 2 bytes were preallocated:
853+
substract 1 byte to prevent overallocation */
854+
writer.min_size--;
855+
869856
if ( in_repeat == 0 ) {
870857
/* Just an escaped RUNCHAR value */
871-
OUTBYTE(RUNCHAR);
858+
*out_data++ = RUNCHAR;
872859
} else {
873860
/* Pick up value and output a sequence of it */
874861
in_byte = out_data[-1];
862+
863+
/* enlarge the buffer if needed */
864+
if (in_repeat > 1) {
865+
/* -1 because we already preallocated 1 byte */
866+
out_data = _PyBytesWriter_Prepare(&writer, out_data,
867+
in_repeat - 1);
868+
if (out_data == NULL)
869+
goto error;
870+
}
871+
875872
while ( --in_repeat > 0 )
876-
OUTBYTE(in_byte);
873+
*out_data++ = in_byte;
877874
}
878875
} else {
879876
/* Normal byte */
880-
OUTBYTE(in_byte);
877+
*out_data++ = in_byte;
881878
}
882879
}
883880
return _PyBytesWriter_Finish(&writer, out_data);

0 commit comments

Comments
 (0)