mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05: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
Reference in a new issue