]> git.tdb.fi Git - libs/datafile.git/commitdiff
Add a class for loading raw bulk data
authorMikko Rasa <tdb@tdb.fi>
Mon, 1 Nov 2021 10:54:37 +0000 (12:54 +0200)
committerMikko Rasa <tdb@tdb.fi>
Mon, 1 Nov 2021 10:54:37 +0000 (12:54 +0200)
source/rawdata.cpp [new file with mode: 0644]
source/rawdata.h [new file with mode: 0644]

diff --git a/source/rawdata.cpp b/source/rawdata.cpp
new file mode 100644 (file)
index 0000000..7a90c9d
--- /dev/null
@@ -0,0 +1,92 @@
+#include <stdexcept>
+#include <msp/io/zlibcompressed.h>
+#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<IO::Base> 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<unsigned char>(header[4+j]);
+
+       uint16_t flags = (static_cast<unsigned char>(header[12])<<8) | static_cast<unsigned char>(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<char *>(buffer);
+
+       IO::Base *src = (compressed ? compressed : in);
+       size_t pos = 0;
+       while(pos<size)
+       {
+               size_t len = src->read(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 (file)
index 0000000..2db390b
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef MSP_DATAFILE_RAWDATA_H_
+#define MSP_DATAFILE_RAWDATA_H_
+
+#include <string>
+#include <msp/core/noncopyable.h>
+#include <msp/io/base.h>
+
+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