Beatmup
chunkfile.cpp
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2019, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "chunkfile.h"
20 
21 using namespace Beatmup;
22 
23 typedef uint32_t id_size_t; //!< chunk id length type
24 
25 namespace Beatmup {
26  class ChunkIdTooLong : public Exception {
27  public:
28  ChunkIdTooLong(const std::string& id) :
29  Exception("Chunk id exceeds max allowed length (255 chars): %s", id.c_str()) {}
30 
31  static void check(const std::string& id) {
32  if (id.size() > 255)
33  throw ChunkIdTooLong(id);
34  }
35  };
36 }
37 
38 
40  map.clear();
41  if (!stream.seek(0))
42  return false;
43 
44  size_t pos = 0;
45  id_size_t idLength;
46  while (stream(&idLength, sizeof(id_size_t))) {
47  // read id
48  std::string id(idLength, 0);
49  if (!stream(&id[0], idLength))
50  return false;
51  pos += idLength + sizeof(id_size_t);
52 
53  // read length
54  ChunkDesc chunkDesc;
55  if (!stream(&chunkDesc.size, sizeof(chunksize_t)))
56  return false;
57  pos += sizeof(chunksize_t);
58 
59  // read content
60  chunkDesc.pos = pos;
61  map[id] = chunkDesc;
62  pos += chunkDesc.size;
63  if (!stream.seek(pos))
64  return false;
65  }
66  return true;
67 }
68 
69 
70 chunksize_t ChunkStream::chunkSize(const std::string& id) const {
71  const auto& chunk = map.find(id);
72  return chunk == map.end() ? 0 : chunk->second.size;
73 }
74 
75 
76 chunksize_t ChunkStream::fetch(const std::string& id, void* data, const chunksize_t limit) {
77 #ifdef BEATMUP_DEBUG
79 #endif
80 
81  const auto& chunk = map.find(id);
82  if (chunk == map.end())
83  return 0;
84 
85  if (!stream.seek(chunk->second.pos))
86  throw RuntimeError("Cannot seek for chunk " + id);
87 
88  const chunksize_t size = chunk->second.size < limit ? chunk->second.size : limit;
89  if (!stream(data, size))
90  throw RuntimeError("Cannot read chunk " + id);
91 
92  return size;
93 }
94 
95 
96 void ChunkStream::save(const std::string& filename, bool append) {
98  for (auto it : map) {
99  Chunk chunk(*this, it.first);
100  writer(it.first, chunk(), chunk.size());
101  }
102 }
103 
104 
105 bool ChunkFile::readable(const std::string& filename) {
106  std::ifstream stream(filename, std::fstream::in | std::fstream::binary);
107  return stream.good();
108 }
109 
110 
111 ChunkFile::ChunkFile(const std::string& filename, bool openNow) :
112  ChunkStream(stream),
114 {
115  if (openNow)
116  open();
117 }
118 
119 
121  stream.open(filename.c_str());
122  stream.clear();
123  parse();
124  stream.clear();
125 }
126 
128  stream.close();
129 }
130 
131 
133  stream(filename, std::ios::binary | (append ? std::ios::out | std::ios::app | std::ios::ate : std::ios::out))
134 {
135  if (!stream.good())
136  throw IOError(filename, "Cannot write to file");
137 }
138 
139 
141 
142 
143 void ChunkFileWriter::operator()(const std::string& id, const void* data, const chunksize_t size) {
145  id_size_t idLen = (char)id.size();
146  stream.write((char*)&idLen, sizeof(idLen));
147  stream.write(&id[0], idLen);
148  stream.write((char*)&size, sizeof(size));
149  stream.write((char*)data, size);
150 }
151 
152 
153 Chunk::Chunk(size_t size) : chunkSize(size) {
154  data = malloc(size);
155 }
156 
157 
158 Chunk::Chunk(ChunkCollection& collection, const std::string& id):
159  Chunk(collection.chunkSize(id))
160 {
161 #ifdef BEATMUP_DEBUG
162  DebugAssertion::check(collection.chunkExists(id), "Chunk not found: " + id);
163 #endif
164  collection.fetch(id, data, chunkSize);
165 }
166 
167 
168 void Chunk::writeTo(ChunkFileWriter& file, const std::string& id) const {
169  file(id, data, chunkSize);
170 }
171 
172 
174  free(data);
175 }
uint32_t id_size_t
chunk id length type
Definition: chunkfile.cpp:23
A key-value pair set storing pieces of arbitrary data (chunks) under string keys.
Definition: chunkfile.h:36
virtual bool chunkExists(const std::string &id) const =0
Check if a specific chunk exists.
virtual chunksize_t fetch(const std::string &id, void *data, const chunksize_t limit)=0
Reads a chunk.
Writes chunks to a file.
Definition: chunkfile.h:191
void operator()(const std::string &id, const void *data, const chunksize_t size)
Definition: chunkfile.cpp:143
ChunkFileWriter(const std::string &filename, bool append=false)
Definition: chunkfile.cpp:132
void open()
Opens the collection to read chunks from it.
Definition: chunkfile.cpp:120
static bool readable(const std::string &filename)
Returns true if a given file is readable.
Definition: chunkfile.cpp:105
FileInputStream stream
Definition: chunkfile.h:170
void close()
Closes the collection after a reading session.
Definition: chunkfile.cpp:127
ChunkFile(const std::string &filename, bool openNow=true)
Creates a read-only chunk collection from a file.
Definition: chunkfile.cpp:111
const std::string filename
Definition: chunkfile.h:169
ChunkIdTooLong(const std::string &id)
Definition: chunkfile.cpp:28
static void check(const std::string &id)
Definition: chunkfile.cpp:31
Stream of chunks.
Definition: chunkfile.h:132
void save(const std::string &filename, bool append=false)
Saves the collection to a file.
Definition: chunkfile.cpp:96
InputStream & stream
Definition: chunkfile.h:140
std::map< std::string, ChunkDesc > map
Definition: chunkfile.h:139
size_t size() const
Returns the number of chunks available in the collection after it is opened.
Definition: chunkfile.h:152
bool parse()
Goes through the input stream to build the list of existing chunks.
Definition: chunkfile.cpp:39
chunksize_t chunkSize(const std::string &id) const
Retrieves size of a specific chunk.
Definition: chunkfile.cpp:70
chunksize_t fetch(const std::string &id, void *data, const chunksize_t limit)
Reads a chunk.
Definition: chunkfile.cpp:76
Simply a piece of binary data of a specific size.
Definition: chunkfile.h:210
void writeTo(ChunkFileWriter &file, const std::string &id) const
Writes a chunk out to a file.
Definition: chunkfile.cpp:168
size_t size() const
Definition: chunkfile.h:257
size_t chunkSize
Definition: chunkfile.h:212
Chunk()
Makes an empty chunk.
Definition: chunkfile.h:218
Base class for all exceptions.
Definition: exception.h:37
void open(const char *filename)
virtual bool seek(msize pos)=0
Moves the read pointer to a given position in the stream.
uint32_t chunksize_t
Definition: chunkfile.h:29
Definition: geometry.h:721
JNIEnv jlong jstring id
JNIEnv jstring jboolean openNow
JNIEnv jlong jstring filename
JNIEnv jlong jstring jboolean append
JNIEnv jlong jint out
jlong jobject size