summaryrefslogtreecommitdiff
path: root/euler/source/euler/stream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'euler/source/euler/stream.cpp')
-rw-r--r--euler/source/euler/stream.cpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/euler/source/euler/stream.cpp b/euler/source/euler/stream.cpp
new file mode 100644
index 0000000..950f3c5
--- /dev/null
+++ b/euler/source/euler/stream.cpp
@@ -0,0 +1,151 @@
+#include <euler/stream.hpp>
+#include <cstring>
+
+namespace euler {
+
+ stream::~stream() {}
+
+ void file_stream::write_buffer() {
+ if (__euler_write_to_stream(handle, buffer_size, buffer)
+ != __EULER_SR_SUCCESS)
+ good = false;//TODO: more precise error reporting
+ else
+ buffer_dirty = false;
+ }
+
+ file_stream::file_stream(
+ __euler_stream_handle handle, bool is_readable, bool is_writable,
+ bool clear, bool seek_to_end)
+
+ : handle(handle), is_readable(is_readable), is_writable(is_writable),
+ buffer(0), good(true) {
+
+ if (clear) {
+ if (__euler_set_stream_length(handle, 0) != __EULER_SR_SUCCESS) {
+ good = false;
+ return;
+ }
+ length = 0;
+ }
+
+ else if (__euler_get_stream_length(handle, length) != __EULER_SR_SUCCESS) {
+ good = false;
+ return;
+ }
+
+ if (seek_to_end) {
+ if (__euler_seek_stream(handle, __EULER_SF_END, 0)
+ != __EULER_SR_SUCCESS) {
+ good = false;
+ return;
+ }
+ offset = length;
+ }
+
+ else
+ offset = 0;
+
+ }
+
+ file_stream::~file_stream() {
+ if (buffer) {
+ if (buffer_dirty)
+ write_buffer();
+ delete[] buffer;
+ }
+ __euler_close_stream(handle);
+ }
+
+ bool file_stream::try_read(void *into, uint64_t bytes) {
+
+ if (bytes == 0)
+ return true;
+
+ if (offset + bytes > length)
+ return false;
+
+ if (buffer) {
+ uint64_t start = offset > buffer_offset ? offset : buffer_offset;
+ uint64_t end = offset + bytes < buffer_offset + buffer_size
+ ? offset + bytes : buffer_offset + buffer_size;
+ if (end > start) {
+
+ uint64_t real_end = offset + bytes;
+
+ std::memcpy(
+ (uint8_t *)into + start - offset, buffer + start - buffer_offset,
+ end - start);
+ if (start != offset)
+ if (!try_read(into, start - offset))
+ return false;
+
+ if (end != real_end) {
+ if (!try_seek(__EULER_SF_BEGINNING, end))
+ return false;
+ if (!try_read((uint8_t *)into + end, real_end - end))
+ return false;
+ }
+
+ else if (offset != real_end)
+ if (!try_seek(__EULER_SF_BEGINNING, real_end))
+ return false;
+
+ return true;
+
+ }
+ }
+
+ if (buffer_dirty) {
+ write_buffer();
+ if (!good)
+ return false;
+ }
+
+ //1024 is arbitrary
+ buffer_size = length - offset < 1024 ? length - offset : 1024;
+
+ if (buffer != 0)
+ delete[] buffer;
+
+ buffer = new uint8_t[buffer_size];
+ buffer_dirty = false;
+ buffer_offset = offset;
+
+ if (__euler_read_from_stream(handle, buffer_size, buffer)
+ != __EULER_SR_SUCCESS) {
+ delete[] buffer;
+ buffer = 0;
+ return false;
+ }
+
+ uint64_t read_this_buffer = buffer_size < bytes ? buffer_size : bytes;
+ std::memcpy(into, buffer, read_this_buffer);
+ offset += read_this_buffer;
+
+ if (read_this_buffer == bytes)
+ return true;
+
+ return try_read(
+ (uint8_t *)into + read_this_buffer, bytes - read_this_buffer);
+
+ }
+
+ bool file_stream::try_seek(__euler_seek_from from, int64_t offset) {
+ if (__euler_seek_stream(handle, from, offset) != __EULER_SR_SUCCESS)
+ return false;
+ switch (from) {
+ case __EULER_SF_BEGINNING:
+ this->offset = offset;
+ return true;
+ case __EULER_SF_END:
+ this->offset = length + offset;
+ return true;
+ case __EULER_SF_CURRENT_POSITION:
+ this->offset += offset;
+ return true;
+ default:
+ return false;
+ }
+ }
+
+}