summaryrefslogtreecommitdiff
path: root/LibGUI/GIODevice.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-03-17 15:54:43 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-03-17 15:54:43 +0100
commitce7017e1ec46e00d3a36308f4ce951f03d5c9624 (patch)
tree41ddeae5752e3445bc328d45e862ebcfbe684d6c /LibGUI/GIODevice.cpp
parentef05d8cbf6ac5e378d3d9205ef095de754f6a8d2 (diff)
downloadserenity-ce7017e1ec46e00d3a36308f4ce951f03d5c9624.zip
LibGUI: Add GFile and base class GIODevice.
Working with the LibC API's is tedious, so let's add some comfy C++ API's.
Diffstat (limited to 'LibGUI/GIODevice.cpp')
-rw-r--r--LibGUI/GIODevice.cpp89
1 files changed, 89 insertions, 0 deletions
diff --git a/LibGUI/GIODevice.cpp b/LibGUI/GIODevice.cpp
new file mode 100644
index 0000000000..d62d36622f
--- /dev/null
+++ b/LibGUI/GIODevice.cpp
@@ -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;
+}