[libcxx-commits] [libcxx] [libc++] Optimize filebuf::seekoff (PR #211788)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jul 28 03:47:53 PDT 2026
================
@@ -995,24 +995,80 @@ basic_filebuf<_CharT, _Traits>::seekoff(off_type __off, ios_base::seekdir __way,
std::__throw_bad_cast();
int __width = __cv_->encoding();
- if (__file_ == nullptr || (__width <= 0 && __off != 0) || sync())
+ if (__file_ == nullptr || (__width <= 0 && __off != 0))
return pos_type(off_type(-1));
- // __width > 0 || __off == 0
- int __whence;
+
+ auto __byte_off = __width <= 0 ? 0 : __width * __off;
+
+ int __whence = 0;
switch (__way) {
- case ios_base::beg:
- __whence = SEEK_SET;
- break;
- case ios_base::cur:
+ case ios::beg: {
+ if (__off < 0)
+ return pos_type(off_type(-1));
+
+ pos_type __success_pos = __off;
+ __success_pos.state(__st_);
+
+ if (__always_noconv_ && __cm_ & ios::in) {
+ off_type __file_pos = __ftell(__file_);
+ auto __buffer_base_pos = __file_pos - (this->egptr() - this->eback());
+
+ // If the new position is within the buffer we can just move the current read pointer
+ if (__off >= __buffer_base_pos && __off <= __file_pos) {
+ this->setg(this->eback(), this->eback() + (__off - __buffer_base_pos), this->egptr());
+ return __success_pos;
+ } else {
+ // Otherwise drop the buffer and seek to the requested position
+ this->setg(nullptr, nullptr, nullptr);
+ __cm_ = 0;
+ if (__fseek(__file_, __byte_off, SEEK_SET))
+ return pos_type(off_type(-1));
+ return __success_pos;
+ }
+ }
+
+ if (sync() || __fseek(__file_, __byte_off, SEEK_SET))
+ return pos_type(off_type(-1));
+ return __success_pos;
+ }
+ case ios::cur: {
+ // If the new position is within the buffer we can just move the current read pointer
+ if (__always_noconv_ && (__cm_ & ios::in)) {
+ if (__off < 0 ? this->gptr() - this->eback() <= __off : this->egptr() - this->gptr() >= __off) {
----------------
philnik777 wrote:
This is #212277.
https://github.com/llvm/llvm-project/pull/211788
More information about the libcxx-commits
mailing list