This is what I found on libstdc++:
template<typename _CharT, typename _Traits> streamsize basic_streambuf<_CharT, _Traits>::xsgetn(char_type* __s, streamsize __n) { streamsize __ret = 0; while (__ret < __n) { const streamsize __buf_len = this->egptr() - this->gptr(); if (__buf_len) { const streamsize __remaining = __n - __ret; const streamsize __len = std::min(__buf_len, __remaining); traits_type::copy(__s, this->gptr(), __len); __ret += __len; __s += __len; this->__safe_gbump(__len); } if (__ret < __n) { const int_type __c = this->uflow(); if (!traits_type::eq_int_type(__c, traits_type::eof())) { traits_type::assign(*__s++, traits_type::to_char_type(__c)); ++__ret; } else break; } } return __ret; }
When the characters extracted are less than the number of characters requested, this function calls uflow()
to obtain more characters. If that function returns Traits::eof()
then it will simply return whether or not 0 characters were extracted. The result of the function call is picked up by the higher-level stream operations that have access to the stream state, and will set it accordingly.