@@ -114,87 +114,6 @@ autonumber_state_error(AutoNumberState state, int field_name_is_empty)
114114/*********** Output string management functions ****************/
115115/************************************************************************/
116116
117- typedef struct {
118- char * data ;
119- Py_UCS4 maxchar ;
120- unsigned int kind ;
121- Py_ssize_t pos , size ;
122- Py_ssize_t size_increment ;
123- } OutputString ;
124-
125- /* initialize an OutputString object, reserving size characters */
126- static int
127- output_initialize (OutputString * output , Py_ssize_t size )
128- {
129- output -> data = PyMem_Malloc (size );
130- if (output -> data == NULL ) {
131- PyErr_NoMemory ();
132- return 0 ;
133- }
134-
135- output -> maxchar = 127 ;
136- output -> kind = PyUnicode_1BYTE_KIND ;
137- output -> pos = 0 ;
138- output -> size = size ;
139- output -> size_increment = INITIAL_SIZE_INCREMENT ;
140-
141- return 1 ;
142- }
143-
144- /*
145- output_extend reallocates the output string buffer.
146- It returns a status: 0 for a failed reallocation,
147- 1 for success.
148- */
149-
150- static int
151- output_extend (OutputString * output , Py_ssize_t count )
152- {
153- Py_ssize_t maxlen = output -> size + count + output -> size_increment ;
154-
155- output -> data = PyMem_Realloc (output -> data , maxlen << (output -> kind - 1 ));
156- output -> size = maxlen ;
157- if (output -> data == 0 ) {
158- PyErr_NoMemory ();
159- return 0 ;
160- }
161- if (output -> size_increment < MAX_SIZE_INCREMENT )
162- output -> size_increment *= SIZE_MULTIPLIER ;
163- return 1 ;
164- }
165-
166- static int
167- output_widen (OutputString * output , Py_UCS4 maxchar )
168- {
169- int kind ;
170- void * data ;
171- Py_ssize_t i ;
172- if (maxchar <= output -> maxchar )
173- return 1 ;
174- if (maxchar < 256 ) {
175- output -> maxchar = 255 ;
176- return 1 ;
177- }
178- if (maxchar < 65536 ) {
179- output -> maxchar = 65535 ;
180- kind = 2 ;
181- }
182- else {
183- output -> maxchar = 1 <<21 ;
184- kind = 3 ;
185- }
186- data = PyMem_Malloc (output -> size << (kind - 1 ));
187- if (data == 0 )
188- return 0 ;
189- for (i = 0 ; i < output -> size ; i ++ )
190- PyUnicode_WRITE (kind , data , i ,
191- PyUnicode_READ (output -> kind , output -> data , i ));
192- PyMem_Free (output -> data );
193- output -> data = data ;
194- output -> kind = kind ;
195- return 1 ;
196- }
197-
198117/*
199118 output_data dumps characters into our output string
200119 buffer.
@@ -205,26 +124,17 @@ output_widen(OutputString *output, Py_UCS4 maxchar)
205124 1 for success.
206125*/
207126static int
208- output_data (OutputString * output , PyObject * s , Py_ssize_t start , Py_ssize_t end )
127+ output_data (_PyAccu * acc , PyObject * s , Py_ssize_t start , Py_ssize_t end )
209128{
210- Py_ssize_t i ;
211- int kind ;
212- if ((output -> pos + end - start > output -> size ) &&
213- !output_extend (output , end - start ))
129+ PyObject * substring ;
130+ int r ;
131+
132+ substring = PyUnicode_Substring (s , start , end );
133+ if (substring == NULL )
214134 return 0 ;
215- kind = PyUnicode_KIND (s );
216- if (PyUnicode_MAX_CHAR_VALUE (s ) > output -> maxchar ) {
217- Py_UCS4 maxchar = output -> maxchar ;
218- for (i = start ; i < end ; i ++ )
219- if (PyUnicode_READ (kind , PyUnicode_DATA (s ), i ) > maxchar )
220- maxchar = PyUnicode_READ (kind , PyUnicode_DATA (s ), i );
221- if (!output_widen (output , maxchar ))
222- return 0 ;
223- }
224- for (i = start ; i < end ; i ++ )
225- PyUnicode_WRITE (output -> kind , output -> data , output -> pos ++ ,
226- PyUnicode_READ (kind , PyUnicode_DATA (s ), i ));
227- return 1 ;
135+ r = _PyAccu_Accumulate (acc , substring );
136+ Py_DECREF (substring );
137+ return r == 0 ;
228138}
229139
230140/************************************************************************/
@@ -612,7 +522,7 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs,
612522 appends to the output.
613523*/
614524static int
615- render_field (PyObject * fieldobj , SubString * format_spec , OutputString * output )
525+ render_field (PyObject * fieldobj , SubString * format_spec , _PyAccu * acc )
616526{
617527 int ok = 0 ;
618528 PyObject * result = NULL ;
@@ -655,7 +565,7 @@ render_field(PyObject *fieldobj, SubString *format_spec, OutputString *output)
655565 goto done ;
656566
657567 assert (PyUnicode_Check (result ));
658- ok = output_data (output , result , 0 , PyUnicode_GET_LENGTH (result ));
568+ ok = output_data (acc , result , 0 , PyUnicode_GET_LENGTH (result ));
659569done :
660570 Py_XDECREF (format_spec_object );
661571 Py_XDECREF (result );
@@ -920,7 +830,7 @@ do_conversion(PyObject *obj, Py_UCS4 conversion)
920830static int
921831output_markup (SubString * field_name , SubString * format_spec ,
922832 int format_spec_needs_expanding , Py_UCS4 conversion ,
923- OutputString * output , PyObject * args , PyObject * kwargs ,
833+ _PyAccu * acc , PyObject * args , PyObject * kwargs ,
924834 int recursion_depth , AutoNumber * auto_number )
925835{
926836 PyObject * tmp = NULL ;
@@ -961,7 +871,7 @@ output_markup(SubString *field_name, SubString *format_spec,
961871 else
962872 actual_format_spec = format_spec ;
963873
964- if (render_field (fieldobj , actual_format_spec , output ) == 0 )
874+ if (render_field (fieldobj , actual_format_spec , acc ) == 0 )
965875 goto done ;
966876
967877 result = 1 ;
@@ -981,7 +891,7 @@ output_markup(SubString *field_name, SubString *format_spec,
981891*/
982892static int
983893do_markup (SubString * input , PyObject * args , PyObject * kwargs ,
984- OutputString * output , int recursion_depth , AutoNumber * auto_number )
894+ _PyAccu * acc , int recursion_depth , AutoNumber * auto_number )
985895{
986896 MarkupIterator iter ;
987897 int format_spec_needs_expanding ;
@@ -997,11 +907,11 @@ do_markup(SubString *input, PyObject *args, PyObject *kwargs,
997907 & field_name , & format_spec ,
998908 & conversion ,
999909 & format_spec_needs_expanding )) == 2 ) {
1000- if (!output_data (output , literal .str , literal .start , literal .end ))
910+ if (!output_data (acc , literal .str , literal .start , literal .end ))
1001911 return 0 ;
1002912 if (field_present )
1003913 if (!output_markup (& field_name , & format_spec ,
1004- format_spec_needs_expanding , conversion , output ,
914+ format_spec_needs_expanding , conversion , acc ,
1005915 args , kwargs , recursion_depth , auto_number ))
1006916 return 0 ;
1007917 }
@@ -1017,39 +927,25 @@ static PyObject *
1017927build_string (SubString * input , PyObject * args , PyObject * kwargs ,
1018928 int recursion_depth , AutoNumber * auto_number )
1019929{
1020- OutputString output ;
1021- PyObject * result = NULL ;
1022-
1023- output .data = NULL ; /* needed so cleanup code always works */
930+ _PyAccu acc ;
1024931
1025932 /* check the recursion level */
1026933 if (recursion_depth <= 0 ) {
1027934 PyErr_SetString (PyExc_ValueError ,
1028935 "Max string recursion exceeded" );
1029- goto done ;
936+ return NULL ;
1030937 }
1031938
1032- /* initial size is the length of the format string, plus the size
1033- increment. seems like a reasonable default */
1034- if (!output_initialize (& output ,
1035- input -> end - input -> start +
1036- INITIAL_SIZE_INCREMENT ))
1037- goto done ;
939+ if (_PyAccu_Init (& acc ))
940+ return NULL ;
1038941
1039- if (!do_markup (input , args , kwargs , & output , recursion_depth ,
942+ if (!do_markup (input , args , kwargs , & acc , recursion_depth ,
1040943 auto_number )) {
1041- goto done ;
944+ _PyAccu_Destroy (& acc );
945+ return NULL ;
1042946 }
1043947
1044- result = PyUnicode_New (output .pos , output .maxchar );
1045- if (!result )
1046- goto done ;
1047- memcpy (PyUnicode_DATA (result ), output .data , output .pos << (output .kind - 1 ));
1048-
1049- done :
1050- if (output .data )
1051- PyMem_Free (output .data );
1052- return result ;
948+ return _PyAccu_Finish (& acc );
1053949}
1054950
1055951/************************************************************************/
0 commit comments