Sunday, December 15, 2024

basic_streambuf

Overview
Every IO stream class uses a basic_streambuf or its derived classes to read from or/and write to its target such as console, file or memory, etc

Details
This is a template based base for all stream buffer classes that handle files (basic_filebuf) and strings (basic_stringbuf).

Syntax
template<class CharT, class Traits = char_traits<CharT>> 
class basic_streambuf
where CharT can be char or wchar_t.

member types
NameDefinition
char_typechar,wchar_t
traits_typechar_traits<char_type>
int_typechar_traits<char_type>::int_type
pos_typechar_traits<char_type>::pos_type
off_typechar_traits<char_type>::off_type

The class basic_streambuf controls input and output to a character sequence.
It includes and provides access to
  • The controlled character sequence, also called the buffer, which may contain
    • input sequence (also called get area) for buffering the input operations
    • output sequence (also called put area) for buffering the output operations.
  • The associated character sequence, This may be an entity that is accessed through OS API (file, TCP socket, serial port, other character device), or it may be an object (string literal). It's called also called source (for input) or sink (for output).
The controlled character sequence represents a subsequence, or a "window" into the associated character sequence. Its state is described by three pointers:
  • The beginning pointer, always points at the lowest element of the buffer.
  • The next pointer, points at the element that is the next candidate for reading or writing.
  • The end pointer, points one past the end of the buffer.
For a input only stream, put area will be empty and for a output only streams, get area will be empty.

When the put area becomes full and a pending operation would cause it to overflow, the characters in that area are written out using the protected virtual function overflow(). Similarly, when the get area is emptied, a new set of characters is read in using the protected virtual function underflow(). In this way the actual reading and writing of characters is delegated to a derived class as necessary.
For example, a basic_filebuf has an implementation of overflow that writes characters out to a file, while a basic_stringbuf simply copies characters into a string whenever overflow is called.
Similarly, a basic_filebuf has an implementation of underflow that reads characters out from a file, while a basic_stringbuf simply copies characters from a string whenever overflow is called.

A Stream buffer objects keep internally, at least: 
  • A locale object, used for locale-dependent operations. 
  • A set of internal pointers to keep an input buffer: eback, gptr, egptr. 
  • A set of internal pointers to keep an output buffer: pbase, pptr, epptr.
The character representation and encoding in the controlled sequence may be different from the character representations in the associated sequence, in which case a codecvt locale facet is typically used to perform the conversion. Common examples are UTF-8 (or other multibyte) files accessed through wfstream objects: the controlled sequence consists of wchar_t characters, but the associated sequence consists of bytes.
The diagram below describes the entire setup.

The interface of basic_streambuf is divided into two parts - public and protected.
The public interface available to clients such as basic_istream and basic_ostream and its derived classes.The functions in the public interface internally call the protected functions.
The protected interface available to its derived such as basic_filebuf and basic_stringbuf. These functions implement the low level interface dealing with the hardware or the OS.
This post discusses only the public interface. Also in most cases, basic_streambuf implements no functionality. It's implemented in the derived classes.

Get Area
NameDescription
streamsize in_avail()Returns the number of characters available in the get area. If eof is reached returns -1.
If the (gptr < egptr), the function returns the number of characters directly available at the get pointer before the end pointer or (egptr()-gptr()).
If (gptr == nullptr) or (gptr == egptr), The function calls showmanyc() to obtain the number of characters expected to be available after an underflow.
int_type snextc() 
Advances the current position of the controlled input sequence to the next character, and returns that next character. The function calls sbumpc() to advance the input sequence. If eof is reached, Traits::eof() is returned.
Otherwise sgetc() is called in order to read the character.
    int_type sbumpc()Returns the character at the current position of the controlled input sequence, and advances the position indicator to the next character.
    Internally, the function calls the uflow() if there are no read positions available at the get pointer (gptr). Otherwise, the function returns the character at the gptr directly.
    int_type sgetc()Returns the character at the current position of the controlled input sequence, without modifying the current position.
    Internally, the function calls the underflow() if there are no read positions available at the get pointer (gptr). Otherwise, the function returns the character at the gptr directly.
    streamsize sgetn (char_type* s, streamsize n)
    Reads n characters from the input sequence and stores them into a character array pointed to by s.
    Calls xsgetn(s, count) of the most derived class. The characters are read as if by repeated calls to sbumpc(). That is, if less than count characters are immediately available,
    the function calls uflow() to provide more until Traits::eof() is returned.
    Example
        ifstream file;
        file.open("/usr/share/dict/words");
        if (!file) 
            return 1;
    
    /* file contents
    A
    AA
    AAA
    AA's
    AB
    ABC
    ABC's
    ABCs
    ABM
    ABM'
    ....
    */        
        streambuf* pbuf = file.rdbuf();
        
        //in_avail
        //985084
        auto sz = pbuf->in_avail();
    
        char buf[40];
        //buf:"A\nAA\nAAA\nAA's\nAB\nABC\nABC's\nABC"
        pbuf->sgetn(buf,40);
        buf[30] = 0;
    
        //sgetc
        //c:s
        auto c = static_cast<char>(pbuf->sbumpc());
        
        //sgetc
        //c:\n
        c = static_cast<char>(pbuf->sgetc());
    
        //snextc
        //c:A
        c = static_cast<char>(pbuf->snextc());


    Put Area
    NameDescription
    int_type sputc
    (char_type ch)
    The character c is stored at the current position of the controlled output sequence, and then advances the position indicator to the next character.

    Internally, the function calls the overflow() if there are no write positions available at the put pointer (pptr).
    In case of success, the character ch is returned, as a value of type int.
    Otherwise, it returns the end-of-file value (EOF) to signal a failure.

    Example
        ostringstream oss;
      //c:a
      auto c = static_cast<char>(oss.rdbuf()->sputc('a'));
    streamsize  sputn
    (char* s, streamsize n)
    Writes characters from the array pointed to by s into the controlled output sequence.
    Internally calls  xsputn(s, n) of the most derived class.
    The characters are written as if by repeated calls to sputc(). Writing stops when either count characters are written or a call to sputc() would have returned Traits::eof().
    The number of characters successfully written.

    Example
        ostringstream oss;
        string s {"The quick brown fox"};
        //n:19
        auto n = oss.rdbuf()->sputn(s.data(),s.length());
    int_type sungetc()
    Decrease current position
    Attempts to move the current position indicator of the controlled input sequence back one position to the character that precedes the current one, making the character at that position available once again for the next input operation.

    Internally, the function calls pbackfail() if the get pointer (gptr == eback).

    Returns the value of the new current character of the controlled input sequence, as a value of type int.
    The function returns the end-of-file value (EOF) on failure.

    Example
    istringstream src ("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    
    //ch:A
    auto ch = static_cast<char>(src.rdbuf()->sbumpc());
        
    //ch:A
    ch = static_cast<char>(src.rdbuf()->sungetc());
    int_type  sputbackc
    (char_type ch )
    Puts back a character back to the get area.
    Attempts to move the current position indicator of the controlled input sequence back to the character that precedes the current one.

    Internally, the function calls pbackfail if either there are no putback positions available at the get pointer (gptr), or if c does not match the character right before the current get position. 

    The value of the character put back, as a value of type int.
    The function returns the end-of-file value (EOF) on failure.

    Example
    istringstream src ("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    
    //ch:A
    auto ch = static_cast<char>(src.rdbuf()->sbumpc());
    //ch:A
    ch = static_cast<char>(src.rdbuf()->sputbackc('A'));

    Positioning
    NameDescription
    basic_streambuf* pubsetbuf 
    (char* s, streamsize n)
    Sets up the buffer s of size n for reading or writing. Calls setbuf (s,n) of the most derived classes. Example
        int cnt = 0;
        std::ifstream file;
        char buf[1024 * 10 + 1];
     
        file.rdbuf()->pubsetbuf(buf, sizeof buf);
     
        file.open("/usr/share/dict/words");
     
        for (std::string line; getline(file, line);)
            ++cnt;
        
        //prints:104334
        std::cout << cnt << endl; 
    pos_type pubseekoff (off_type off, ios_base::seekdir dir, ios_base::openmode which = ios_base::in | ios_base::out)
    Sets the position indicator of the input and/or output sequence indicated by which, relative to dir by some other position indicated by off. Calls seekoff(off, dir, which) of the most derived classes.

    Example
        std::ifstream file;
        file.open("/usr/share/dict/words");
        if (file) 
        {
            streambuf* pbuf = file.rdbuf();
            //size:985084 
            long size = pbuf->pubseekoff(0,file.end);
        }
    pos_type pubseekpos (off_type off, ios_base::openmode which = ios_base::in | ios_base::out)Sets the position indicator of the input and/or output sequence indicated by which, to absolute position indicated by off.
    Calls seekpos(off, which) of the most derived classes.
    Returns the new position value of the modified position pointer.

    Example
        std::ifstream file;
        file.open("/usr/share/dict/words");
        if (!file) 
            return 1;
        
        streambuf* pbuf = file.rdbuf();
        char buffer[11];
        // change position to the 10th character
    
        //p:10
        auto p = pbuf->pubseekpos(10);
    // read 10 characters pbuf->sgetn (buffer,10); // append null character to string buffer[10]=0; /* prints A's AB ABC */ cout << buffer << endl;
    int pubsync()
    Synchronizes the controlled character sequence (the buffers) with the associated character
    sequence. Calls sync() of the most derived class For output streams, this typically results in writing the contents of the put area into the
    associated sequence, i.e. flushing of the output buffer. For input streams, this typically
    empties the get area and forces a re-read from the associated sequence to pick up recent
    changes.

    Example
    /*prints
    First line
    Second line
    */
        std::streambuf * pbuf = cout.rdbuf();
    
        pbuf->sputn ("First line\n",11);
        pbuf->pubsync();
        pbuf->sputn ("Second line\n",12);


    Locale
    NameDescription
    locale pubimbue
    (const locale& loc)
    Associates loc to the stream buffer.
    Calls imbue(loc) of the most derived class
    Returns the locale object associated to the stream buffer before the call.
    locale getlocale()Returns the locale object currently associated to the stream buffer. Returns the locale set by the last pubimbue() call. If never called, returns the current global locale.





    No comments:

    Post a Comment