]> git.tdb.fi Git - libs/datafile.git/blobdiff - source/rawdata.cpp
Add a class for loading raw bulk data
[libs/datafile.git] / source / rawdata.cpp
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