1/* _PyUnicode_InsertThousandsGrouping() helper functions */ 2 3typedef struct { 4 const char *grouping; 5 char previous; 6 Py_ssize_t i; /* Where we're currently pointing in grouping. */ 7} GroupGenerator; 8 9 10static void 11GroupGenerator_init(GroupGenerator *self, const char *grouping) 12{ 13 self->grouping = grouping; 14 self->i = 0; 15 self->previous = 0; 16} 17 18 19/* Returns the next grouping, or 0 to signify end. */ 20static Py_ssize_t 21GroupGenerator_next(GroupGenerator *self) 22{ 23 /* Note that we don't really do much error checking here. If a 24 grouping string contains just CHAR_MAX, for example, then just 25 terminate the generator. That shouldn't happen, but at least we 26 fail gracefully. */ 27 switch (self->grouping[self->i]) { 28 case 0: 29 return self->previous; 30 case CHAR_MAX: 31 /* Stop the generator. */ 32 return 0; 33 default: { 34 char ch = self->grouping[self->i]; 35 self->previous = ch; 36 self->i++; 37 return (Py_ssize_t)ch; 38 } 39 } 40} 41 42 43/* Fill in some digits, leading zeros, and thousands separator. All 44 are optional, depending on when we're called. */ 45static void 46InsertThousandsGrouping_fill(_PyUnicodeWriter *writer, Py_ssize_t *buffer_pos, 47 PyObject *digits, Py_ssize_t *digits_pos, 48 Py_ssize_t n_chars, Py_ssize_t n_zeros, 49 PyObject *thousands_sep, Py_ssize_t thousands_sep_len, 50 Py_UCS4 *maxchar) 51{ 52 if (!writer) { 53 /* if maxchar > 127, maxchar is already set */ 54 if (*maxchar == 127 && thousands_sep) { 55 Py_UCS4 maxchar2 = PyUnicode_MAX_CHAR_VALUE(thousands_sep); 56 *maxchar = Py_MAX(*maxchar, maxchar2); 57 } 58 return; 59 } 60 61 if (thousands_sep) { 62 *buffer_pos -= thousands_sep_len; 63 64 /* Copy the thousands_sep chars into the buffer. */ 65 _PyUnicode_FastCopyCharacters(writer->buffer, *buffer_pos, 66 thousands_sep, 0, 67 thousands_sep_len); 68 } 69 70 *buffer_pos -= n_chars; 71 *digits_pos -= n_chars; 72 _PyUnicode_FastCopyCharacters(writer->buffer, *buffer_pos, 73 digits, *digits_pos, 74 n_chars); 75 76 if (n_zeros) { 77 *buffer_pos -= n_zeros; 78 enum PyUnicode_Kind kind = PyUnicode_KIND(writer->buffer); 79 void *data = PyUnicode_DATA(writer->buffer); 80 unicode_fill(kind, data, '0', *buffer_pos, n_zeros); 81 } 82} 83