[libcxx-commits] [libcxx] [libc++] Refactors fstream open. (PR #76617)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jan 8 11:37:35 PST 2024


================
@@ -282,6 +285,25 @@ private:
   void __write_mode();
 
   _LIBCPP_EXPORTED_FROM_ABI friend FILE* __get_ostream_file(ostream&);
+
+  // There are multiple (__)open function, they use different C-API open
+  // function.  After that call these functions behave the same. This function
+  // does that part and determines the final return value.
+  _LIBCPP_HIDE_FROM_ABI basic_filebuf* __open_common_part(ios_base::openmode __mode) {
----------------
ldionne wrote:

I would suggest something like this instead:

```
template <class _OpenFunc>
basic_filebuf* __do_open(_OpenFunc __f, ios_base::openmode __mode) {
  __file_ = __f();
  if (__file_ == nullptr)
    return nullptr;
  __om_ = __mode;

  if (__mode & ios_base::ate) {
    if (fseek(__file_, 0, SEEK_END)) {
      fclose(__file_);
      __file_ = nullptr;
      return nullptr;
    }
  }

  return this;
}
```

Then, you could call it as:

```
template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
  if (__file_)
    return nullptr;
  const char* __mdstr = __make_mdstring(__mode);
  if (!__mdstr)
    return nullptr;
  
  return __do_open([&]{ return fopen(__s, __mdstr); }, __mode);
}
```

As-is, `__open_common_part` seems like a really macro-y way to reuse code, since `__open_common_part` doesn't really do anything on its own. It's really just a way to stamp out the same repetitive code without having to write it multiple times, but for example I'd have difficulty saying exactly what `__open_common_part` does appart from reading its implementation.

https://github.com/llvm/llvm-project/pull/76617


More information about the libcxx-commits mailing list