mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:42:43 +00:00 
			
		
		
		
	LibGUI: Add GFile and base class GIODevice.
Working with the LibC API's is tedious, so let's add some comfy C++ API's.
This commit is contained in:
		
							parent
							
								
									ef05d8cbf6
								
							
						
					
					
						commit
						ce7017e1ec
					
				
					 6 changed files with 230 additions and 9 deletions
				
			
		|  | @ -1,4 +1,5 @@ | |||
| #include "ProcessTableModel.h" | ||||
| #include <LibGUI/GFile.h> | ||||
| #include <fcntl.h> | ||||
| #include <stdio.h> | ||||
| #include <pwd.h> | ||||
|  | @ -121,10 +122,11 @@ GVariant ProcessTableModel::data(const GModelIndex& index, Role role) const | |||
| 
 | ||||
| void ProcessTableModel::update() | ||||
| { | ||||
|     FILE* fp = fopen("/proc/all", "r"); | ||||
|     if (!fp) { | ||||
|         perror("failed to open /proc/all"); | ||||
|     GFile file("/proc/all"); | ||||
|     if (!file.open(GIODevice::ReadOnly)) { | ||||
|         fprintf(stderr, "ProcessManager: Failed to open /proc/all: %s\n", file.error_string()); | ||||
|         exit(1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     unsigned last_sum_nsched = 0; | ||||
|  | @ -134,11 +136,10 @@ void ProcessTableModel::update() | |||
|     HashTable<pid_t> live_pids; | ||||
|     unsigned sum_nsched = 0; | ||||
|     for (;;) { | ||||
|         char buf[BUFSIZ]; | ||||
|         char* ptr = fgets(buf, sizeof(buf), fp); | ||||
|         if (!ptr) | ||||
|         auto line = file.read_line(1024); | ||||
|         if (line.is_empty()) | ||||
|             break; | ||||
|         auto parts = String(buf, Chomp).split(','); | ||||
|         auto parts = String((const char*)line.pointer(), line.size() - 1, Chomp).split(','); | ||||
|         if (parts.size() < 17) | ||||
|             break; | ||||
|         bool ok; | ||||
|  | @ -178,8 +179,6 @@ void ProcessTableModel::update() | |||
| 
 | ||||
|         live_pids.set(pid); | ||||
|     } | ||||
|     int rc = fclose(fp); | ||||
|     ASSERT(rc == 0); | ||||
| 
 | ||||
|     m_pids.clear(); | ||||
|     Vector<pid_t> pids_to_remove; | ||||
|  |  | |||
							
								
								
									
										56
									
								
								LibGUI/GFile.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								LibGUI/GFile.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | |||
| #include <LibGUI/GFile.h> | ||||
| #include <unistd.h> | ||||
| #include <fcntl.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| GFile::GFile(const String& filename) | ||||
|     : m_filename(filename) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| GFile::~GFile() | ||||
| { | ||||
|     if (mode() != NotOpen) | ||||
|         close(); | ||||
| } | ||||
| 
 | ||||
| bool GFile::open(GIODevice::OpenMode mode) | ||||
| { | ||||
|     int flags = 0; | ||||
|     if ((mode & GIODevice::ReadWrite) == GIODevice::ReadWrite) { | ||||
|         flags |= O_RDWR | O_CREAT; | ||||
|     } else if (mode & GIODevice::ReadOnly) { | ||||
|         flags |= O_RDONLY; | ||||
|     } else if (mode & GIODevice::WriteOnly) { | ||||
|         flags |= O_WRONLY | O_CREAT; | ||||
|     } | ||||
|     if (mode & GIODevice::Append) | ||||
|         flags |= O_APPEND; | ||||
|     if (mode & GIODevice::Truncate) | ||||
|         flags |= O_TRUNC; | ||||
|     if (mode & GIODevice::MustBeNew) | ||||
|         flags |= O_EXCL; | ||||
|     int fd = ::open(m_filename.characters(), flags, 0666); | ||||
|     if (fd < 0) { | ||||
|         set_error(errno); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     set_fd(fd); | ||||
|     set_mode(mode); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool GFile::close() | ||||
| { | ||||
|     if (fd() < 0 || mode() == NotOpen) | ||||
|         return false; | ||||
|     int rc = ::close(fd()); | ||||
|     if (rc < 0) { | ||||
|         set_error(rc); | ||||
|         return false; | ||||
|     } | ||||
|     set_fd(-1); | ||||
|     set_mode(GIODevice::NotOpen); | ||||
|     return true; | ||||
| } | ||||
							
								
								
									
										22
									
								
								LibGUI/GFile.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								LibGUI/GFile.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <LibGUI/GIODevice.h> | ||||
| #include <AK/AKString.h> | ||||
| 
 | ||||
| class GFile final : public GIODevice { | ||||
| public: | ||||
|     GFile() { } | ||||
|     explicit GFile(const String&); | ||||
|     virtual ~GFile() override; | ||||
| 
 | ||||
|     String filename() const { return m_filename; } | ||||
|     void set_filename(const String& filename) { m_filename = filename; } | ||||
| 
 | ||||
|     virtual bool open(GIODevice::OpenMode) override; | ||||
|     virtual bool close() override; | ||||
| 
 | ||||
|     virtual const char* class_name() const override { return "GFile"; } | ||||
| 
 | ||||
| private: | ||||
|     String m_filename; | ||||
| }; | ||||
							
								
								
									
										89
									
								
								LibGUI/GIODevice.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								LibGUI/GIODevice.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | |||
| #include <LibGUI/GIODevice.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| GIODevice::GIODevice(GObject* parent) | ||||
|     : GObject(parent) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| GIODevice::~GIODevice() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| const char* GIODevice::error_string() const | ||||
| { | ||||
|     return strerror(m_error); | ||||
| } | ||||
| 
 | ||||
| ByteBuffer GIODevice::read(int max_size) | ||||
| { | ||||
|     if (m_fd < 0) | ||||
|         return { }; | ||||
|     if (!max_size) | ||||
|         return { }; | ||||
|     auto buffer = ByteBuffer::create_uninitialized(max_size); | ||||
|     auto* buffer_ptr = (char*)buffer.pointer(); | ||||
|     int remaining_buffer_space = buffer.size(); | ||||
|     if (!m_buffered_data.is_empty()) { | ||||
|         int taken_from_buffered = min(remaining_buffer_space, m_buffered_data.size()); | ||||
|         memcpy(buffer_ptr, m_buffered_data.data(), taken_from_buffered); | ||||
|         Vector<byte> new_buffered_data; | ||||
|         new_buffered_data.append(m_buffered_data.data() + taken_from_buffered, m_buffered_data.size() - taken_from_buffered); | ||||
|         m_buffered_data = move(new_buffered_data); | ||||
|         remaining_buffer_space -= taken_from_buffered; | ||||
|         buffer_ptr += taken_from_buffered; | ||||
|     } | ||||
|     if (!remaining_buffer_space) | ||||
|         return buffer; | ||||
|     int nread = ::read(m_fd, buffer_ptr, remaining_buffer_space); | ||||
|     if (nread < 0) { | ||||
|         set_error(errno); | ||||
|         return { }; | ||||
|     } | ||||
|     buffer.trim(nread); | ||||
|     return buffer; | ||||
| } | ||||
| 
 | ||||
| ByteBuffer GIODevice::read_line(int max_size) | ||||
| { | ||||
|     if (m_fd < 0) | ||||
|         return { }; | ||||
|     if (!max_size) | ||||
|         return { }; | ||||
|     auto line = ByteBuffer::create_uninitialized(max_size); | ||||
|     int line_index = 0; | ||||
|     while (line_index < line.size()) { | ||||
|         if (line_index >= m_buffered_data.size()) { | ||||
|             if (!populate_read_buffer()) | ||||
|                 return { }; | ||||
|         } | ||||
|         byte ch = m_buffered_data[line_index]; | ||||
|         line[line_index++] = ch; | ||||
|         if (ch == '\n') { | ||||
|             Vector<byte> new_buffered_data; | ||||
|             new_buffered_data.append(m_buffered_data.data() + line_index, m_buffered_data.size() - line_index); | ||||
|             m_buffered_data = move(new_buffered_data); | ||||
|             line.trim(line_index); | ||||
|             return line; | ||||
|         } | ||||
|     } | ||||
|     return { }; | ||||
| } | ||||
| 
 | ||||
| bool GIODevice::populate_read_buffer() | ||||
| { | ||||
|     if (m_fd < 0) | ||||
|         return false; | ||||
|     auto buffer = ByteBuffer::create_uninitialized(1024); | ||||
|     int nread = ::read(m_fd, buffer.pointer(), buffer.size()); | ||||
|     if (nread < 0) { | ||||
|         set_error(errno); | ||||
|         return false; | ||||
|     } | ||||
|     if (nread == 0) { | ||||
|         set_eof(true); | ||||
|         return false; | ||||
|     } | ||||
|     m_buffered_data.append(buffer.pointer(), buffer.size()); | ||||
|     return true; | ||||
| } | ||||
							
								
								
									
										53
									
								
								LibGUI/GIODevice.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								LibGUI/GIODevice.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <LibGUI/GObject.h> | ||||
| #include <AK/ByteBuffer.h> | ||||
| 
 | ||||
| class GIODevice : public GObject { | ||||
| public: | ||||
|     enum OpenMode { | ||||
|         NotOpen      = 0, | ||||
|         ReadOnly     = 1, | ||||
|         WriteOnly    = 2, | ||||
|         ReadWrite    = 3, | ||||
|         Append       = 4, | ||||
|         Truncate     = 8, | ||||
|         MustBeNew    = 16, | ||||
|     }; | ||||
| 
 | ||||
|     virtual ~GIODevice() override; | ||||
| 
 | ||||
|     int fd() const { return m_fd; } | ||||
|     unsigned mode() const { return m_mode; } | ||||
|     bool eof() const { return m_eof; } | ||||
| 
 | ||||
|     int error() const { return m_error; } | ||||
|     const char* error_string() const; | ||||
| 
 | ||||
|     bool has_error() const { return m_error != 0; } | ||||
| 
 | ||||
|     ByteBuffer read(int max_size); | ||||
|     ByteBuffer read_line(int max_size); | ||||
| 
 | ||||
|     virtual bool open(GIODevice::OpenMode) = 0; | ||||
|     virtual bool close() = 0; | ||||
| 
 | ||||
|     virtual const char* class_name() const override { return "GIODevice"; } | ||||
| 
 | ||||
| protected: | ||||
|     explicit GIODevice(GObject* parent = nullptr); | ||||
| 
 | ||||
|     void set_fd(int fd) { m_fd = fd; } | ||||
|     void set_mode(OpenMode mode) { m_mode = mode; } | ||||
|     void set_error(int error) { m_error = error; } | ||||
|     void set_eof(bool eof) { m_eof = eof; } | ||||
| 
 | ||||
| private: | ||||
|     bool populate_read_buffer(); | ||||
| 
 | ||||
|     int m_fd { -1 }; | ||||
|     int m_error { 0 }; | ||||
|     bool m_eof { false }; | ||||
|     OpenMode m_mode { NotOpen }; | ||||
|     Vector<byte> m_buffered_data; | ||||
| }; | ||||
|  | @ -7,6 +7,8 @@ SHAREDGRAPHICS_OBJS = \ | |||
|     ../SharedGraphics/Color.o | ||||
| 
 | ||||
| LIBGUI_OBJS = \
 | ||||
|     GIODevice.o \
 | ||||
|     GFile.o \
 | ||||
|     GButton.o \
 | ||||
|     GCheckBox.o \
 | ||||
|     GEventLoop.o \
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling