]> git.tdb.fi Git - libs/datafile.git/blob - source/rawdata.cpp
Add a class for loading raw bulk data
[libs/datafile.git] / source / rawdata.cpp
1 #include <stdexcept>
2 #include <msp/io/zlibcompressed.h>
3 #include "collection.h"
4 #include "except.h"
5 #include "rawdata.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace DataFile {
11
12 RawData::~RawData()
13 {
14         delete owned_data;
15         delete compressed;
16         if(in_owned)
17                 delete in;
18 }
19
20 void RawData::open_file(Collection &coll, const string &fn)
21 {
22         if(in)
23                 throw logic_error("input already exists");
24
25         RefPtr<IO::Base> opened = coll.open_raw(fn);
26         if(!opened)
27                 throw IO::file_not_found(fn);
28
29         open_io(*opened, fn);
30         opened.release();
31         in_owned = true;
32 }
33
34 void RawData::open_io(IO::Base &i, const string &fn)
35 {
36         if(in)
37                 throw logic_error("input already exists");
38
39         char header[14];
40         unsigned len = i.read(header, sizeof(header));
41         if(len!=sizeof(header))
42                 throw data_error(fn, 0, "Missing header");
43         if(header[0]!='M' || header[1]!='D' || header[2]!='R' || header[3]!=1)
44                 throw data_error(fn, 0, "Bad header");
45
46         size = 0;
47         for(unsigned j=0; j<8; ++j)
48                 size = (size<<8) | static_cast<unsigned char>(header[4+j]);
49
50         uint16_t flags = (static_cast<unsigned char>(header[12])<<8) | static_cast<unsigned char>(header[13]);
51
52         src_name = fn;
53         in = &i;
54         if(flags&COMPRESSED)
55                 compressed = new IO::ZlibCompressed(*in, IO::M_READ);
56 }
57
58 void RawData::load()
59 {
60         if(!in)
61                 throw logic_error("no input");
62         if(data)
63                 throw logic_error("already loaded");
64
65         owned_data = new char[size];
66         load_into(owned_data);
67 }
68
69 void RawData::load_into(void *buffer)
70 {
71         if(!in)
72                 throw logic_error("no input");
73
74         data = static_cast<char *>(buffer);
75
76         IO::Base *src = (compressed ? compressed : in);
77         size_t pos = 0;
78         while(pos<size)
79         {
80                 size_t len = src->read(data+pos, size-pos);
81                 if(!len)
82                         throw data_error(src_name, 0, "Truncated data");
83                 pos += len;
84         }
85
86         if(in_owned)
87                 delete in;
88         in = nullptr;
89 }
90
91 } // namespace DataFile
92 } // namespace Msp