diff --git a/CMakeLists.txt b/CMakeLists.txt index 15c1e44..a40dc91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,7 @@ project(file_read) set(CMAKE_CXX_STANDARD 23) -add_library(file_read STATIC file_read.cpp - file_deserialising.cpp +add_library(file_read STATIC file_deserialising.h buffer.cpp buffer.h) diff --git a/buffer.cpp b/buffer.cpp index 04651d0..fc35813 100644 --- a/buffer.cpp +++ b/buffer.cpp @@ -10,9 +10,9 @@ void buffer::write(char *data_in, int data_size) { throw std::runtime_error("Allocation failed"); } - std::memcpy(&data[size], data_in, data_size); - size += data_size; } + std::memcpy(&data[size], data_in, data_size); + size += data_size; } void buffer::remove(int offset, int remove_size) diff --git a/buffer.h b/buffer.h index a9e9d46..9d33a87 100644 --- a/buffer.h +++ b/buffer.h @@ -2,7 +2,7 @@ #include #include #include -#define BUFFER_SIZE 1092 +#define BUFFER_SIZE 1024 struct buffer { diff --git a/file_deserialising.cpp b/file_deserialising.cpp deleted file mode 100644 index ed812fc..0000000 --- a/file_deserialising.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "file_deserialising.h" - - -template -T read_type(char *data) -{ - T a; - - std::memcpy(&a, data, sizeof(T)); - - switch (sizeof(T)) - { - case 1: - break; - case 2: - a = be16toh(a); - break; - case 4: - a = be32toh(a); - break; - case 8: - a = be64toh(a); - break; - default: - std::println("This integer is not supported!"); - } - return a; -} - -template <> -float read_type(char *data) -{ - uint32_t num_as_uint32; - float num; - - memcpy(&num_as_uint32, data, sizeof(uint32_t)); - num_as_uint32 = be32toh(num_as_uint32); - memcpy(&num, &num_as_uint32, sizeof(float)); - - return num; -} - -template <> -double read_type(char *data) -{ - uint64_t num_as_uint64; - double num; - - memcpy(&num_as_uint64, data, sizeof(uint64_t)); - num_as_uint64 = be64toh(num_as_uint64); - memcpy(&num, &num_as_uint64, sizeof(double)); - - return num; -} - - -template constexpr void const_for_each_(std::integer_sequence, F&& func) -{ - (func(std::integral_constant{}), ...); -} - -template constexpr void const_for_(F&& func) -{ - if constexpr (N > 0) - const_for_each_(std::make_integer_sequence{}, std::forward(func)); -} \ No newline at end of file diff --git a/file_deserialising.h b/file_deserialising.h index 31c28b8..a27c562 100644 --- a/file_deserialising.h +++ b/file_deserialising.h @@ -2,8 +2,11 @@ #include #include #include +#include "buffer.h" #ifdef __APPLE__ #include +#define read_comp(size, ptr, t) const_for_([&](auto i){std::get(t) = read_var>::call(&ptr);}); + #define htobe16(x) OSSwapHostToBigInt16(x) #define htole16(x) OSSwapHostToLittleInt16(x) @@ -21,5 +24,91 @@ #define le64toh(x) OSSwapLittleToHostInt64(x) #endif -template constexpr void const_for_each_(std::integer_sequence, F&& func); -template constexpr void const_for_(F&& func); +struct parsing_buffer +{ + parsing_buffer(buffer &b) + :buf(b) + {} + buffer &buf; + char *point; + int consumed_size; +}; + +template +static T read_type(char *data) +{ + T a; + + std::memcpy(&a, data, sizeof(T)); + + switch (sizeof(T)) + { + case 1: + break; + case 2: + a = be16toh(a); + break; + case 4: + a = be32toh(a); + break; + case 8: + a = be64toh(a); + break; + default: + std::println("This integer is not supported!"); + } + return a; +} + +template <> +float read_type(char *data) +{ + uint32_t num_as_uint32; + float num; + + memcpy(&num_as_uint32, data, sizeof(uint32_t)); + num_as_uint32 = be32toh(num_as_uint32); + memcpy(&num, &num_as_uint32, sizeof(float)); + + return num; +} + +template <> +double read_type(char *data) +{ + uint64_t num_as_uint64; + double num; + + memcpy(&num_as_uint64, data, sizeof(uint64_t)); + num_as_uint64 = be64toh(num_as_uint64); + memcpy(&num, &num_as_uint64, sizeof(double)); + + return num; +} + + +template +struct read_var +{ + static T call(parsing_buffer* v) + { + if (sizeof(T) + v->consumed_size > v->buf.size) + return T{}; + T ret = read_type(v->point); + v->point += sizeof(T); + v->consumed_size += sizeof(T); + return ret; + } +}; + + +template constexpr void const_for_each_(std::integer_sequence, F&& func) +{ + (func(std::integral_constant{}), ...); +} + +template constexpr void const_for_(F&& func) +{ + if constexpr (N > 0) + const_for_each_(std::make_integer_sequence{}, std::forward(func)); +} diff --git a/file_read.cpp b/file_read.cpp deleted file mode 100644 index 33c3852..0000000 --- a/file_read.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "file_read.h" - -#include - -void hello() -{ - std::cout << "Hello, World!" << std::endl; -} \ No newline at end of file diff --git a/file_read.h b/file_read.h index af9bb7f..d27a599 100644 --- a/file_read.h +++ b/file_read.h @@ -1,3 +1,58 @@ #pragma once +#include "file_deserialising.h" +#include -void hello(); +class file_reader +{ + public: + file_reader(int file_fd) + :fd(file_fd) + { + buf.size = 0; + buf.allocated = 0; + buf.data = nullptr; + file_size = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + file_size_remaining = file_size; + } + + template + std::tuple read_from_tuple(std::tuple in) + { + constexpr std::size_t size_tuple = std::tuple_size_v; + int size = 0; + const_for_([&](auto i){size += sizeof(std::get(in));}); + if (size > buf.size) + { + int extra_size = 0; + if (size + BUFFER_SIZE <= file_size_remaining) + { + extra_size = BUFFER_SIZE; + } + else if (size > file_size_remaining) + { + extra_size = file_size_remaining - size; + } + char *new_read = (char *)calloc(size + extra_size, sizeof(char)); + size_t res = read(fd, new_read, size + extra_size); + if (res != size + extra_size) + { + free(new_read); + throw std::runtime_error("Read failed!"); + } + buf.write(new_read, size + extra_size); + file_size_remaining -= size + extra_size; + free(new_read); + } + parsing_buffer par_buf(buf); + par_buf.point = buf.data; + par_buf.consumed_size = 0; + read_comp(size_tuple, par_buf, in); + buf.remove(0, size); + return in; + } + buffer buf; + int fd; + off_t file_size; + off_t file_size_remaining; +};