std::basic_...f::underflow(3)

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

πŸ’– NAME πŸ’–

std::basic_streambuf::underflow β€” std::basic_streambuf::underflow (yes bestie, that's the whole name, no cap). This is the C++ Standard Libary manual page std::basic_...f::underflow(3), and we're about to make streams make sense πŸ’….


πŸ” Synopsis πŸ”

protected:
virtual int_type underflow();

Okay so what does it do? It ensures that at least one character is available in the input area by updating the pointers to the input area (if needed) and reading more data in from the input sequence (if applicable). It returns the value of that character (converted to int_type with Traits::to_int_type(c)) on success, or Traits::eof() on failure. Periodt.

The function may update gptr, egptr and eback pointers to define the location of newly loaded data (if any). On failure, the function ensures that either gptr() == nullptr or gptr() == egptr(). That's the vibe check 🫢.

The base class version of the function does nothing. The derived classes may override this function to allow updates to the get area in the case of exhaustion. Iconic override behavior, honestly ✨.


🧾 Parameters 🧾

(none) β€” literally no parameters, bestie. Not one. Zero. Nada πŸŽ€.


🎁 Return value 🎁

The value of the character pointed to by the get pointer after the call on success, or Traits::eof() otherwise 😭.

The base class version of the function returns traits::eof() β€” lowercase traits in the original, bestie, I'm not switching it up πŸ’€.


⚠️ Note ⚠️

Important vibe check: the public functions of std::streambuf call this function only if gptr() == nullptr or gptr() >= egptr(). Like, only then. No cap πŸ”₯.


πŸ’» Example πŸ’»

This example is lowkey iconic β€” it filters out zero bytes. Run this code:

// Run this code

#include <iostream>
#include <sstream>

class null_filter_buf : public std::streambuf
{
    std::streambuf* src;
    char ch; // single-byte buffer
protected:
    int underflow()
    {
        traits_type::int_type i;
        while ((i = src->sbumpc()) == '\0')
            ; // skip zeroes
        if (!traits_type::eq_int_type(i, traits_type::eof()))
        {
            ch = traits_type::to_char_type(i);
            setg(&ch, &ch, &ch+1); // make one read position available
        }
        return i;
    }
public:
    null_filter_buf(std::streambuf* buf) : src(buf)
    {
        setg(&ch, &ch + 1, &ch + 1); // buffer is initially full
    }
};

void filtered_read(std::istream& in)
{
    std::streambuf* orig = in.rdbuf();
    null_filter_buf buf(orig);
    in.rdbuf(&buf);
    for (char c; in.get(c);)
        std::cout << c;
    in.rdbuf(orig);
}

int main()
{
    char a[] = "This i\0s \0an e\0\0\0xample";
    std::istringstream in(std::string(std::begin(a), std::end(a)));
    filtered_read(in);
}

Output:

This is an example

Ate and left no crumbs πŸ“βœ¨.


πŸ‘€ See also πŸ‘€

  • uflow β€” reads characters from the associated input sequence to the get area and [virtual] advances the next pointer (virtual protected member function).
  • overflow β€” writes characters to the associated output sequence from the put area [virtual] (virtual protected member function).
  • underflow β€” reads from the associated file [virtual] (virtual protected member function of std::basic_filebuf<CharT,Traits>).
  • underflow β€” returns the next character available in the input sequence [virtual] (virtual protected member function of std::basic_stringbuf<CharT,Traits,Allocator>).
  • underflow β€” reads a character from the input sequence without advancing the next [virtual] pointer (virtual protected member function of std::strstreambuf).

source: http://cppreference.com Β· version/date: 2024.06.10 Β· page: std::basic_...f::underflow(3) β€” that's the tea, bestie, now go make those streams behave πŸ’–βœ¨

πŸ“¦ where this page comes from