--- /dev/null
+#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
--- /dev/null
+#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