OutIter utf16_to_multi_byte()

in src/Windows/libraries/multi_byte/include/m/multi_byte/convert.h [214:267]


        OutIter utf16_to_multi_byte(code_page                                              cp,
                                    std::basic_string_view<Utf16CharT, CharTraitsT> const& in,
                                    OutIter                                                it)
        {
            std::array<char, BufferSize> buffer;
            auto                         input_cursor{in.data()};
            auto                         chars_left{in.size()};

            while (chars_left != 0)
            {
                std::size_t chars_to_convert{(std::min)(chars_left, buffer.size())};

                // mbcs -> Utf16 cannot (proof separate, as long as chars
                // above U+FFFF aren't encoded in single byte form in the
                // source) expand in terms of count, so we assume that
                // failures are either fundamentally bad encodings or
                // that we ran out of output buffer. We will assume out of
                // output buffer and trim down conversion length until
                // we get a successful conversion or zero length.
                //
                // If we hit zero length, we will assume it was a bad
                // encoding, because it must have been. Otherwise we have
                // to make the interface with try_acp_to_utf16()
                // significantly more complicated.
                //

                for (;;)
                {
                    // This should probably be converted to use std::size_t
                    // indices and .substr() or such that way the type
                    // wouldn't have to be named here.
                    auto const view = std::basic_string_view<Utf16CharT, CharTraitsT>(
                        input_cursor, chars_to_convert);
                    auto span = m::make_span(buffer);

                    if (windows::is_success(try_utf16_to_multi_byte(cp, view, span)))
                    {
                        it = std::ranges::copy(span, it).out;

                        chars_left -= chars_to_convert;
                        input_cursor += chars_to_convert;

                        break;
                    }

                    chars_to_convert--;

                    if (chars_to_convert == 0)
                        throw std::runtime_error("invalid UTF-16 character data");
                }
            }

            return it;
        }