std::codecv...h,do_length(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… std::codecvt::length, do_length β€” C++ Standard Library realness (that's the manual name bestie, we're in <locale> land)

Ok so picture this: you're bicultural. You speak ExternT on the street and InternT at home. This page is about the ✨translator✨ and specifically about asking it, "hey, how many bytes of the outside-world string would you eat to give me N inside-world characters?" That's it. That's the vibe check. No conversion actually happens, it's a preview. Iconic behavior honestly.


✨ NAME ✨

std::codecvt::length, do_length β€” literally just std::codecvt::length, do_length. Yes the name is the name, we're not doing extra credit here πŸŽ€


🌸 Synopsis 🌸

Defined in header <locale>
public:

int length( StateT& state, const ExternT* from, const ExternT* from_end,        (1)
            std::size_t max ) const;
protected:

virtual int do_length( StateT& state, const ExternT* from, const ExternT*       (2)
from_end,
                       std::size_t max ) const;
  1. The public member function. It just calls do_length on the most derived class. Middle management energy, but make it fashion πŸ’…
  2. The protected virtual one, the actual main character. Here's what she does: she attempts to convert the ExternT characters sitting in the character array defined by [from, from_end), starting from the initial conversion state state, into at most max InternT characters β€” and then returns the number of ExternT characters that such a conversion would consume 🌈

And (this part matters, so pay attention) it modifies state as if by executing do_in(state, from, from_end, from, to, to + max, to) for some imaginary [to, to + max) output buffer. Imaginary. Like her imaginary boyfriend. The buffer isn't real but the state change absolutely is πŸ’€


πŸ‘‘ Return value πŸ‘‘

The number of ExternT characters that would be consumed if converted by do_in(), stopping at whichever of these hits first:

  • all from_end - from characters got consumed,
  • max InternT characters got produced,
  • or a conversion error occurred 😭

And the non-converting specialization, std::codecvt<char, char, std::mbstate_t>? She doesn't convert anything, she just returns std::min(max, from_end - from) and honestly good for her, zero notes, no stress 🌸


πŸ¦‹ Example πŸ¦‹

// Run this code

#include <iostream>
#include <locale>
#include <string>

int main()
{
    using facet_type = std::codecvt<char16_t, char, std::mbstate_t>;

    // narrow multibyte encoding
    std::string s = "z\u00df\u6c34\U0001d10b"; // or u8"zΓŸζ°΄π„‹"
              // or "\x7a\xc3\x9f\xe6\xb0\xb4\xf0\x9d\x84\x8b"

    std::setlocale(LC_ALL, "en_US.UTF-8");
    facet_type const& codecvt_facet =
std::use_facet<facet_type>(std::locale());
    std::mbstate_t mb = std::mbstate_t();
    std::cout << "Only the first "
              << codecvt_facet.length(mb, s.data(), s.data() +
s.size(), 2)
              << " bytes out of " << s.size() << " would be consumed"
                 " to produce the first 2 characters\n";
}

Output:

Only the first 3 bytes out of 10 would be consumed to produce the first 2 characters

See how she said 3 bytes out of 10 for 2 characters? Multibyte encoding said "not today, one byte per character is a myth" 🧚✨


🌟 Defect reports 🌟

So these behavior-changing defect reports got applied retroactively to previously published C++ standards. Time travel but make it committee πŸ•°οΈ

  • LWG 75 β€” applied to C++98. Behavior as published: the effect on state was not specified. Correct behavior: specified πŸ’–
  • LWG 305 β€” applied to C++98. Behavior as published: std::codecvt<wchar_t, char, std::mbstate_t>::do_length was required to return std::min(max, from_end - from). Correct behavior: not required πŸ”₯

🫢 See also 🫢

  • do_in β€” converts a string from ExternT to InternT, such as when reading from file. [virtual] (virtual protected member function) πŸŽ€

And that's the page bestie! No cap, you now understand a facet that most people avoid for their whole careers. Go off πŸ‘‘

Sign-off time: this lil masterpiece lives at http://cppreference.com, dated 2024.06.10, and yes the footer also says std::codecv...h,do_length(3) because tradition is tradition πŸ’œ

πŸ“¦ where this page comes from