From c80b23de8b70776e37f37e4b8fc2003c553448d6 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 1 Nov 2021 12:54:37 +0200 Subject: [PATCH] Add a class for loading raw bulk data --- source/rawdata.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++++ source/rawdata.h | 44 ++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 source/rawdata.cpp create mode 100644 source/rawdata.h diff --git a/source/rawdata.cpp b/source/rawdata.cpp new file mode 100644 index 0000000..7a90c9d --- /dev/null +++ b/source/rawdata.cpp @@ -0,0 +1,92 @@ +#include +#include +#include "collection.h" +#include "except.h" +#include "rawdata.h" + +using namespace std; + +namespace Msp { +namespace DataFile { + +RawData::~RawData() +{ + delete owned_data; + delete compressed; + if(in_owned) + delete in; +} + +void RawData::open_file(Collection &coll, const string &fn) +{ + if(in) + throw logic_error("input already exists"); + + RefPtr opened = coll.open_raw(fn); + if(!opened) + throw IO::file_not_found(fn); + + open_io(*opened, fn); + opened.release(); + in_owned = true; +} + +void RawData::open_io(IO::Base &i, const string &fn) +{ + if(in) + throw logic_error("input already exists"); + + char header[14]; + unsigned len = i.read(header, sizeof(header)); + if(len!=sizeof(header)) + throw data_error(fn, 0, "Missing header"); + if(header[0]!='M' || header[1]!='D' || header[2]!='R' || header[3]!=1) + throw data_error(fn, 0, "Bad header"); + + size = 0; + for(unsigned j=0; j<8; ++j) + size = (size<<8) | static_cast(header[4+j]); + + uint16_t flags = (static_cast(header[12])<<8) | static_cast(header[13]); + + src_name = fn; + in = &i; + if(flags&COMPRESSED) + compressed = new IO::ZlibCompressed(*in, IO::M_READ); +} + +void RawData::load() +{ + if(!in) + throw logic_error("no input"); + if(data) + throw logic_error("already loaded"); + + owned_data = new char[size]; + load_into(owned_data); +} + +void RawData::load_into(void *buffer) +{ + if(!in) + throw logic_error("no input"); + + data = static_cast(buffer); + + IO::Base *src = (compressed ? compressed : in); + size_t pos = 0; + while(posread(data+pos, size-pos); + if(!len) + throw data_error(src_name, 0, "Truncated data"); + pos += len; + } + + if(in_owned) + delete in; + in = nullptr; +} + +} // namespace DataFile +} // namespace Msp diff --git a/source/rawdata.h b/source/rawdata.h new file mode 100644 index 0000000..2db390b --- /dev/null +++ b/source/rawdata.h @@ -0,0 +1,44 @@ +#ifndef MSP_DATAFILE_RAWDATA_H_ +#define MSP_DATAFILE_RAWDATA_H_ + +#include +#include +#include + +namespace Msp { +namespace DataFile { + +class Collection; + +class RawData: public NonCopyable +{ +private: + enum Flags + { + COMPRESSED = 1 + }; + + std::string src_name; + IO::Base *in = nullptr; + bool in_owned = false; + IO::Base *compressed = nullptr; + std::size_t size = 0; + char *data = nullptr; + char *owned_data = nullptr; + +public: + ~RawData(); + + void open_file(Collection &, const std::string &); + void open_io(IO::Base &, const std::string &); + void load(); + void load_into(void *); + + std::size_t get_size() const { return size; } + const void *get_data() const { return data; } +}; + +} // namespace DataFile +} // namespace Msp + +#endif -- 2.43.0