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:
Andreas Kling 2019-03-17 15:54:43 +01:00
parent ef05d8cbf6
commit ce7017e1ec
Notes: sideshowbarker 2024-07-19 15:01:12 +09:00
6 changed files with 230 additions and 9 deletions

View file

@ -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
View 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
View 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
View 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
View 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;
};

View file

@ -7,6 +7,8 @@ SHAREDGRAPHICS_OBJS = \
../SharedGraphics/Color.o
LIBGUI_OBJS = \
GIODevice.o \
GFile.o \
GButton.o \
GCheckBox.o \
GEventLoop.o \