[libcxx-commits] [libcxx] [libc++] Optimize std::getline (PR #121346)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jan 29 08:07:05 PST 2025
================
@@ -1265,41 +1265,49 @@ _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm) {
ios_base::iostate __state = ios_base::goodbit;
typename basic_istream<_CharT, _Traits>::sentry __sen(__is, true);
- if (__sen) {
+ if (!__sen)
+ return __is;
# if _LIBCPP_HAS_EXCEPTIONS
- try {
+ try {
# endif
- __str.clear();
- streamsize __extr = 0;
- while (true) {
- typename _Traits::int_type __i = __is.rdbuf()->sbumpc();
- if (_Traits::eq_int_type(__i, _Traits::eof())) {
- __state |= ios_base::eofbit;
- break;
- }
- ++__extr;
- _CharT __ch = _Traits::to_char_type(__i);
- if (_Traits::eq(__ch, __dlm))
- break;
- __str.push_back(__ch);
- if (__str.size() == __str.max_size()) {
+ __str.clear();
+
+ auto& __buffer = *__is.rdbuf();
+
+ auto __next = __buffer.sgetc();
+ for (; !_Traits::eq_int_type(__next, _Traits::eof()); __next = __buffer.sgetc()) {
+ const auto* __first = __buffer.gptr();
+ const auto* __last = __buffer.egptr();
+ const auto* __match = _Traits::find(__first, __last - __first, __dlm);
+ if (__match) {
+ if (auto __cap = __str.max_size() - __str.size(); __cap <= static_cast<size_t>(__match - __first)) {
+ __str.append(__first, __cap);
+ __buffer.__gbump_ptrdiff(__cap);
__state |= ios_base::failbit;
break;
}
+ __str.append(__first, __match);
+ __buffer.__gbump_ptrdiff(__match - __first + 1);
+ break;
----------------
ldionne wrote:
```suggestion
if (auto __cap = __str.max_size() - __str.size(); __cap <= static_cast<size_t>(__match - __first)) {
__str.append(__first, __cap);
__buffer.__gbump_ptrdiff(__cap);
__state |= ios_base::failbit;
} else {
__str.append(__first, __match);
__buffer.__gbump_ptrdiff(__match - __first + 1); // drop the delimiter from the stream even if we don't read it into the string
}
break;
```
And in fact you could also invert the `if` logic to handle the happy case first, IMO that reads more naturally.
https://github.com/llvm/llvm-project/pull/121346
More information about the libcxx-commits
mailing list