17db96d56Sopenharmony_ci/* _PyUnicode_InsertThousandsGrouping() helper functions */
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_citypedef struct {
47db96d56Sopenharmony_ci    const char *grouping;
57db96d56Sopenharmony_ci    char previous;
67db96d56Sopenharmony_ci    Py_ssize_t i; /* Where we're currently pointing in grouping. */
77db96d56Sopenharmony_ci} GroupGenerator;
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_cistatic void
117db96d56Sopenharmony_ciGroupGenerator_init(GroupGenerator *self, const char *grouping)
127db96d56Sopenharmony_ci{
137db96d56Sopenharmony_ci    self->grouping = grouping;
147db96d56Sopenharmony_ci    self->i = 0;
157db96d56Sopenharmony_ci    self->previous = 0;
167db96d56Sopenharmony_ci}
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_ci/* Returns the next grouping, or 0 to signify end. */
207db96d56Sopenharmony_cistatic Py_ssize_t
217db96d56Sopenharmony_ciGroupGenerator_next(GroupGenerator *self)
227db96d56Sopenharmony_ci{
237db96d56Sopenharmony_ci    /* Note that we don't really do much error checking here. If a
247db96d56Sopenharmony_ci       grouping string contains just CHAR_MAX, for example, then just
257db96d56Sopenharmony_ci       terminate the generator. That shouldn't happen, but at least we
267db96d56Sopenharmony_ci       fail gracefully. */
277db96d56Sopenharmony_ci    switch (self->grouping[self->i]) {
287db96d56Sopenharmony_ci    case 0:
297db96d56Sopenharmony_ci        return self->previous;
307db96d56Sopenharmony_ci    case CHAR_MAX:
317db96d56Sopenharmony_ci        /* Stop the generator. */
327db96d56Sopenharmony_ci        return 0;
337db96d56Sopenharmony_ci    default: {
347db96d56Sopenharmony_ci        char ch = self->grouping[self->i];
357db96d56Sopenharmony_ci        self->previous = ch;
367db96d56Sopenharmony_ci        self->i++;
377db96d56Sopenharmony_ci        return (Py_ssize_t)ch;
387db96d56Sopenharmony_ci    }
397db96d56Sopenharmony_ci    }
407db96d56Sopenharmony_ci}
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ci/* Fill in some digits, leading zeros, and thousands separator. All
447db96d56Sopenharmony_ci   are optional, depending on when we're called. */
457db96d56Sopenharmony_cistatic void
467db96d56Sopenharmony_ciInsertThousandsGrouping_fill(_PyUnicodeWriter *writer, Py_ssize_t *buffer_pos,
477db96d56Sopenharmony_ci                             PyObject *digits, Py_ssize_t *digits_pos,
487db96d56Sopenharmony_ci                             Py_ssize_t n_chars, Py_ssize_t n_zeros,
497db96d56Sopenharmony_ci                             PyObject *thousands_sep, Py_ssize_t thousands_sep_len,
507db96d56Sopenharmony_ci                             Py_UCS4 *maxchar)
517db96d56Sopenharmony_ci{
527db96d56Sopenharmony_ci    if (!writer) {
537db96d56Sopenharmony_ci        /* if maxchar > 127, maxchar is already set */
547db96d56Sopenharmony_ci        if (*maxchar == 127 && thousands_sep) {
557db96d56Sopenharmony_ci            Py_UCS4 maxchar2 = PyUnicode_MAX_CHAR_VALUE(thousands_sep);
567db96d56Sopenharmony_ci            *maxchar = Py_MAX(*maxchar, maxchar2);
577db96d56Sopenharmony_ci        }
587db96d56Sopenharmony_ci        return;
597db96d56Sopenharmony_ci    }
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci    if (thousands_sep) {
627db96d56Sopenharmony_ci        *buffer_pos -= thousands_sep_len;
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci        /* Copy the thousands_sep chars into the buffer. */
657db96d56Sopenharmony_ci        _PyUnicode_FastCopyCharacters(writer->buffer, *buffer_pos,
667db96d56Sopenharmony_ci                                      thousands_sep, 0,
677db96d56Sopenharmony_ci                                      thousands_sep_len);
687db96d56Sopenharmony_ci    }
697db96d56Sopenharmony_ci
707db96d56Sopenharmony_ci    *buffer_pos -= n_chars;
717db96d56Sopenharmony_ci    *digits_pos -= n_chars;
727db96d56Sopenharmony_ci    _PyUnicode_FastCopyCharacters(writer->buffer, *buffer_pos,
737db96d56Sopenharmony_ci                                  digits, *digits_pos,
747db96d56Sopenharmony_ci                                  n_chars);
757db96d56Sopenharmony_ci
767db96d56Sopenharmony_ci    if (n_zeros) {
777db96d56Sopenharmony_ci        *buffer_pos -= n_zeros;
787db96d56Sopenharmony_ci        enum PyUnicode_Kind kind = PyUnicode_KIND(writer->buffer);
797db96d56Sopenharmony_ci        void *data = PyUnicode_DATA(writer->buffer);
807db96d56Sopenharmony_ci        unicode_fill(kind, data, '0', *buffer_pos, n_zeros);
817db96d56Sopenharmony_ci    }
827db96d56Sopenharmony_ci}
83