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.