[libc-commits] [libc] feat(filemode): implement class and helper functions to handle file modes for an opened file (PR #220906)

David Dada via libc-commits libc-commits at lists.llvm.org
Wed Sep 9 08:54:09 PDT 2026


https://github.com/obadafidii updated https://github.com/llvm/llvm-project/pull/220906

>From e3dc3a646ef6c422e75810881826e211aebb7a3b Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 3 Sep 2026 13:21:11 +0100
Subject: [PATCH 1/7] feat(filemode): implement class and helper functions to
 handle file modes for an opened file

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 125 ++++++++++++++++++++++++++++
 1 file changed, 125 insertions(+)
 create mode 100644 libc/src/__support/File/file_mode.h

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
new file mode 100644
index 0000000000000..6b837ea46f652
--- /dev/null
+++ b/libc/src/__support/File/file_mode.h
@@ -0,0 +1,125 @@
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
+#define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
+#include <cstdint>
+
+namespace LIBC_NAMESPACE_DECL {
+
+// FileMode class handles everything regarding the mode of the file, be it's opening mode or content type.
+class FileMode {
+public:
+  // FileMode constructor accepts the mode string as an argument.
+  // It performs validation against several rules and records the `file_mode` property to
+  // the specific mode.
+  explicit FileMode(const char *mode) : file_mode_(0) {
+    // First character in |mode| should be 'a', 'r' or 'w'.
+    if (*mode != 'a' && *mode != 'r' && *mode != 'w')
+      return;
+
+    // There should be exactly one main mode ('a', 'r' or 'w') character.
+    // If there are more than one main mode characters listed, then
+    // we will consider |mode| as incorrect and return 0;
+    int main_mode_count = 0;
+
+    for (; *mode != '\0'; ++mode) {
+      switch (*mode) {
+      case 'r':
+        file_mode_ |= static_cast<Mode>(OpenMode::READ);
+        ++main_mode_count;
+        break;
+      case 'w':
+        file_mode_ |= static_cast<Mode>(OpenMode::WRITE);
+        ++main_mode_count;
+        break;
+      case '+':
+        file_mode_ |= static_cast<Mode>(OpenMode::PLUS);
+        break;
+      case 'b':
+        file_mode_ |= static_cast<Mode>(ContentType::BINARY);
+        break;
+      case 'a':
+        file_mode_ |= static_cast<Mode>(OpenMode::APPEND);
+        ++main_mode_count;
+        break;
+      case 'x':
+        file_mode_ |= static_cast<Mode>(CreateType::EXCLUSIVE);
+        break;
+      default:
+        file_mode_ = 0;
+      }
+    }
+
+    if (main_mode_count != 1)
+      file_mode_ = 0;
+  }
+
+  // helper function to show if file allows writing
+  bool write_allowed() const {
+    return (file_mode_ & static_cast<Mode>(OpenMode::WRITE)) != 0;
+  }
+
+  // helper function to show if file allows reading
+  bool read_allowed() const {
+    return (file_mode_ & static_cast<Mode>(OpenMode::READ)) != 0;
+  }
+
+  // helper function to show if file allows appending
+  bool append_allowed() const {
+    return (file_mode_ & static_cast<Mode>(OpenMode::APPEND)) != 0;
+  }
+
+  // helper function to denote if the file is in binary format.
+  bool is_binary_format() const {
+    return (file_mode_ & static_cast<Mode>(ContentType::BINARY)) != 0;
+  }
+
+  // '+' means update is allowed
+  // TODO: ask michael if I need to give it a better name like "update_allowed" or just continue with the
+  // old convention.
+  bool is_plus() const {
+    return (file_mode_ & static_cast<Mode>(OpenMode::PLUS)) != 0;
+  }
+
+  // checks if a file was created for writing
+  bool is_exclusive_create() const {
+    return (file_mode_ & static_cast<Mode>(CreateType::EXCLUSIVE)) != 0;
+  }
+
+private:
+  // Mode is a generic or abstract mode bit for all kinds of modes
+  // (open-mode, 'content-mode', 'create-modes')
+  using Mode = uint32_t;
+
+  // Denotes the mode of the file.
+  //
+  // The three different types of flags below are to be used with '|' operator.
+  // Their values correspond to mutually exclusive bits in a 32-bit unsigned
+  // integer value. A flag set can include both READ and WRITE if the file
+  // is opened in update mode (ie. if the file was opened with a '+' the mode
+  // string.)
+  enum class OpenMode: Mode {
+    READ = 0x1,
+    WRITE = 0x2,
+    APPEND = 0x4,
+    PLUS = 0x8,
+  };
+
+  // Denotes a file opened in binary mode (which is specified by including
+  // the 'b' character in teh mode string.)
+  enum class ContentType: Mode {
+    BINARY = 0x10,
+  };
+
+  // Denotes a file to be created for writing.
+  enum class CreateType: Mode {
+    EXCLUSIVE = 0x100,
+  };
+
+  // This property tracks the mode for the particular file instance (i.e currently opened file)
+  int file_mode_;
+};
+
+
+}
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H

>From b0470fe313766fcb4fac92b63d41d39314a90f75 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 3 Sep 2026 14:08:49 +0100
Subject: [PATCH 2/7] feat(lint): lint file mode class to conform to standards

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 6b837ea46f652..707a448c5955d 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -5,12 +5,13 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-// FileMode class handles everything regarding the mode of the file, be it's opening mode or content type.
+// FileMode class handles everything regarding the mode of the file, be it's
+// opening mode or content type.
 class FileMode {
 public:
   // FileMode constructor accepts the mode string as an argument.
-  // It performs validation against several rules and records the `file_mode` property to
-  // the specific mode.
+  // It performs validation against several rules and records the `file_mode`
+  // property to the specific mode.
   explicit FileMode(const char *mode) : file_mode_(0) {
     // First character in |mode| should be 'a', 'r' or 'w'.
     if (*mode != 'a' && *mode != 'r' && *mode != 'w')
@@ -74,8 +75,8 @@ class FileMode {
   }
 
   // '+' means update is allowed
-  // TODO: ask michael if I need to give it a better name like "update_allowed" or just continue with the
-  // old convention.
+  // TODO: ask michael if I need to give it a better name like "update_allowed"
+  // or just continue with the old convention.
   bool is_plus() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::PLUS)) != 0;
   }
@@ -97,7 +98,7 @@ class FileMode {
   // integer value. A flag set can include both READ and WRITE if the file
   // is opened in update mode (ie. if the file was opened with a '+' the mode
   // string.)
-  enum class OpenMode: Mode {
+  enum class OpenMode : Mode {
     READ = 0x1,
     WRITE = 0x2,
     APPEND = 0x4,
@@ -106,20 +107,20 @@ class FileMode {
 
   // Denotes a file opened in binary mode (which is specified by including
   // the 'b' character in teh mode string.)
-  enum class ContentType: Mode {
+  enum class ContentType : Mode {
     BINARY = 0x10,
   };
 
   // Denotes a file to be created for writing.
-  enum class CreateType: Mode {
+  enum class CreateType : Mode {
     EXCLUSIVE = 0x100,
   };
 
-  // This property tracks the mode for the particular file instance (i.e currently opened file)
+  // This property tracks the mode for the particular file instance (i.e
+  // currently opened file)
   int file_mode_;
 };
 
-
-}
+} // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H

>From d208bddb974f3c55dcbcc35a17523eaccff20c79 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 14:31:48 +0100
Subject: [PATCH 3/7] feat(file_mode): update write_allowed and read_allowed
 method to use new api

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file.h | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h
index 67879e6c9933e..08f8b93b8f215 100644
--- a/libc/src/__support/File/file.h
+++ b/libc/src/__support/File/file.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_FILE_FILE_H
 #define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_H
 
+#include "file_mode.h"
 #include "hdr/stdint_proxy.h"
 #include "hdr/stdio_macros.h"
 #include "hdr/types/off_t.h"
@@ -122,8 +123,12 @@ class File {
   bool own_buf;
 
   // The mode in which the file was opened.
+  //TODO: old way of doing things
+  // clean up when totally done with pr
   ModeFlags mode;
 
+  FileMode file_mode;
+
   // Current read or write pointer.
   size_t pos;
 
@@ -155,14 +160,13 @@ class File {
 
 protected:
   constexpr bool write_allowed() const {
-    return mode & (static_cast<ModeFlags>(OpenMode::WRITE) |
-                   static_cast<ModeFlags>(OpenMode::APPEND) |
-                   static_cast<ModeFlags>(OpenMode::PLUS));
+    return file_mode.write_allowed() ||
+        file_mode.append_allowed() ||
+          file_mode.is_plus(); //TODO: if micheal agrees for me to convert it change it here
   }
 
   constexpr bool read_allowed() const {
-    return mode & (static_cast<ModeFlags>(OpenMode::READ) |
-                   static_cast<ModeFlags>(OpenMode::PLUS));
+    return file_mode.read_allowed() || file_mode.is_plus();
   }
 
   void reset_stream_state_unlocked(ModeFlags new_mode) {

>From 91f4a23232fb9d2992a69286e74241002513c86e Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 16:47:57 +0100
Subject: [PATCH 4/7] feat: add method to check validity of a file mode

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 707a448c5955d..92647decd2e76 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -1,7 +1,8 @@
 
 #ifndef LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
 #define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
-#include <cstdint>
+
+#include "hdr/stdint_proxy.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
@@ -54,6 +55,8 @@ class FileMode {
       file_mode_ = 0;
   }
 
+  bool is_valid() const { return file_mode_ != 0; }
+
   // helper function to show if file allows writing
   bool write_allowed() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::WRITE)) != 0;

>From 86ef8ab5c1b9efc429df6ce9e9dfedb2bfa822e9 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 16:49:02 +0100
Subject: [PATCH 5/7] add config header for namespace resolution

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 92647decd2e76..e7f46d6172833 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -3,6 +3,7 @@
 #define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
 
 #include "hdr/stdint_proxy.h"
+#include "src/__support/macros/config.h"
 
 namespace LIBC_NAMESPACE_DECL {
 

>From e97d27a9e2d28d37a0e75790be6b4820e5f0d27e Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 16:50:49 +0100
Subject: [PATCH 6/7] feat: make FileMode constructor a constexpr

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index e7f46d6172833..88ca0f5a2aa21 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -14,7 +14,7 @@ class FileMode {
   // FileMode constructor accepts the mode string as an argument.
   // It performs validation against several rules and records the `file_mode`
   // property to the specific mode.
-  explicit FileMode(const char *mode) : file_mode_(0) {
+  constexpr FileMode(const char *mode) : file_mode_(0) {
     // First character in |mode| should be 'a', 'r' or 'w'.
     if (*mode != 'a' && *mode != 'r' && *mode != 'w')
       return;

>From 85003b267932ad24be42eff1f569321c7854944d Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 16:53:22 +0100
Subject: [PATCH 7/7] feat(file.h): refactor File class to use FileMode to
 handle mode related operations

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file.h | 50 ++++++----------------------------
 1 file changed, 8 insertions(+), 42 deletions(-)

diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h
index 6e06e0d6d28bd..a0ea9b7e9d156 100644
--- a/libc/src/__support/File/file.h
+++ b/libc/src/__support/File/file.h
@@ -68,31 +68,6 @@ class File {
   using SeekFunc = ErrorOr<off_t>(File *, off_t, int);
   using CloseFunc = int(File *);
 
-  using ModeFlags = uint32_t;
-
-  // The three different types of flags below are to be used with '|' operator.
-  // Their values correspond to mutually exclusive bits in a 32-bit unsigned
-  // integer value. A flag set can include both READ and WRITE if the file
-  // is opened in update mode (ie. if the file was opened with a '+' the mode
-  // string.)
-  enum class OpenMode : ModeFlags {
-    READ = 0x1,
-    WRITE = 0x2,
-    APPEND = 0x4,
-    PLUS = 0x8,
-  };
-
-  // Denotes a file opened in binary mode (which is specified by including
-  // the 'b' character in teh mode string.)
-  enum class ContentType : ModeFlags {
-    BINARY = 0x10,
-  };
-
-  // Denotes a file to be created for writing.
-  enum class CreateType : ModeFlags {
-    EXCLUSIVE = 0x100,
-  };
-
   // This is a convenience RAII class to lock and unlock file objects.
   class FileLock {
     File *file;
@@ -135,12 +110,7 @@ class File {
   // free-ed when close method is called on the stream.
   bool own_buf;
 
-  // The mode in which the file was opened.
-  //TODO: old way of doing things
-  // clean up when totally done with pr
-  ModeFlags mode;
-
-  FileMode file_mode;
+  FileMode mode;
 
   // Current read or write pointer.
   size_t pos;
@@ -160,16 +130,16 @@ class File {
 
 protected:
   constexpr bool write_allowed() const {
-    return file_mode.write_allowed() ||
-        file_mode.append_allowed() ||
-          file_mode.is_plus(); //TODO: if micheal agrees for me to convert it change it here
+    return mode.write_allowed() || mode.append_allowed() ||
+           mode.is_plus(); // TODO: if micheal agrees for me to convert it
+                           // change it here
   }
 
   constexpr bool read_allowed() const {
-    return file_mode.read_allowed() || file_mode.is_plus();
+    return mode.read_allowed() || mode.is_plus();
   }
 
-  void reset_stream_state_unlocked(ModeFlags new_mode) {
+  void reset_stream_state_unlocked(FileMode new_mode) {
     mode = new_mode;
     pos = 0;
     prev_op = FileOp::NONE;
@@ -191,12 +161,12 @@ class File {
   // the set_buffer method and allocate a buffer.
   constexpr File(WriteFunc *wf, ReadFunc *rf, SeekFunc *sf, CloseFunc *cf,
                  uint8_t *buffer, size_t buffer_size, int buffer_mode,
-                 bool owned, ModeFlags modeflags)
+                 bool owned, FileMode mode)
       : platform_write(wf), platform_read(rf), platform_seek(sf),
         platform_close(cf), mutex(/*timed=*/false, /*recursive=*/false,
                                   /*robust=*/false, /*pshared=*/false),
         ungetc_buf{}, buf(buffer), bufsize(buffer_size), bufmode(buffer_mode),
-        own_buf(owned), mode(modeflags), pos(0), prev_op(FileOp::NONE),
+        own_buf(owned), mode(mode), pos(0), prev_op(FileOp::NONE),
         read_limit(0), eof(false), err(false),
         orientation(Orientation::UNORIENTED), mbstate(), prev(nullptr),
         next(nullptr) {
@@ -356,10 +326,6 @@ class File {
     return try_set_orientation_unlocked(o);
   }
 
-  // Returns an bit map of flags corresponding to enumerations of
-  // OpenMode, ContentType and CreateType.
-  static ModeFlags mode_flags(const char *mode);
-
 private:
   FileIOResult write_unlocked_impl(const void *data, size_t len);
   FileIOResult read_unlocked_impl(void *data, size_t len);



More information about the libc-commits mailing list