Beatmup
chunkfile.h
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 #pragma once
20 #include "../exception.h"
21 #include "input_stream.h"
22 #include <fstream>
23 #include <map>
24 #include <vector>
25 #include <cstdint>
26 
27 
28 namespace Beatmup {
29  typedef uint32_t chunksize_t;
30 
31  /**
32  A key-value pair set storing pieces of arbitrary data (chunks) under string keys.
33  A chunk is a header and a piece of data packed in memory like this: (idLength[4], id[idLength], size[sizeof(chunksize_t)], data[size])
34  ChunkCollection defines an interface to retrieve chunks by their ids.
35  */
36  class ChunkCollection : public Object {
37  public:
38  /**
39  Opens the collection to read chunks from it.
40  */
41  virtual void open() = 0;
42 
43  /**
44  Closes the collection after a reading session.
45  */
46  virtual void close() = 0;
47 
48  /**
49  Returns the number of chunks available in the collection after it is opened.
50  */
51  virtual size_t size() const = 0;
52 
53  /**
54  Check if a specific chunk exists.
55  \param[in] id The chunk id
56  \return `true` if the chunk exists in the collection.
57  */
58  virtual bool chunkExists(const std::string& id) const = 0;
59 
60  /**
61  Retrieves size of a specific chunk.
62  \param[in] id The chunk id
63  \return size of the chunk in bytes, 0 if not found.
64  */
65  virtual chunksize_t chunkSize(const std::string& id) const = 0;
66 
67  /**
68  Reads a chunk.
69  The collection is expected to be opened.
70  \param[in] id Wanted chunk id.
71  \param[out] data A buffer to write out the wanted chunk content.
72  \param[in] limit The buffer capacity in bytes.
73  \return number of bytes written out to the buffer:
74  * if the chunk is found fits the buffer, the chunk size is returned;
75  * if the chunk is found and too big, \p limit is returned (number of bytes actually written);
76  * if no chunk found, 0 is returned.
77  */
78  virtual chunksize_t fetch(const std::string& id, void* data, const chunksize_t limit) = 0;
79 
80  /**
81  Saves the collection to a file.
82  \param[in] filename The name of the file to write chunks to
83  \param[in] append If `true`, writing to the end of the file (keeping the existing content). Rewriting the file otherwise.
84  */
85  virtual void save(const std::string& filename, bool append = false) = 0;
86 
87  /**
88  Reads a chunk and casts it into a given type.
89  \param[in] id The searched chunk id.
90  */
91  template<typename datatype> inline datatype read(const std::string& id) {
92  datatype result;
93 #ifdef BEATMUP_DEBUG
94  DebugAssertion::check(sizeof(result) == chunkSize(id),
95  "Cannot fit chunk " + id + " of " + std::to_string(chunkSize(id)) + " bytes into " + std::to_string(sizeof(result)) + " bytes");
96 #endif
97  fetch(id, &result, sizeof(result));
98  return result;
99  }
100 
101  /**
102  Reads a chunk into a vector of a specific type.
103  \param[in] id The searched chunk id.
104  */
105  template<typename datatype>
106  inline std::vector<datatype> readVector(const std::string& id) {
107 #ifdef BEATMUP_DEBUG
108  DebugAssertion::check(chunkSize(id) % sizeof(datatype) == 0,
109  "Cannot read chunk " + id + " of " + std::to_string(chunkSize(id)) + " bytes in a vector of elements"
110  " of " + std::to_string(sizeof(datatype)) + " bytes each");
111 #endif
112  std::vector<datatype> result;
113  result.resize(chunkSize(id) / sizeof(datatype));
114  fetch(id, static_cast<void*>(result.data()), result.size() * sizeof(datatype));
115  return result;
116  }
117 
118  };
119 
120  template<>
121  inline std::string ChunkCollection::read(const std::string& id) {
122  std::string result;
123  result.resize(chunkSize(id));
124  fetch(id, const_cast<char*>(result.data()), result.size());
125  return result;
126  }
127 
128  /**
129  Stream of chunks.
130  Implements ChunkCollection from a streamed source.
131  */
132  class ChunkStream : public ChunkCollection {
133  private:
134  typedef struct {
137  } ChunkDesc;
138 
139  std::map<std::string, ChunkDesc> map;
141 
142  protected:
144 
145  /**
146  Goes through the input stream to build the list of existing chunks.
147  Does not read the chunks content, only headers.
148  */
149  bool parse();
150 
151  public:
152  inline size_t size() const { return map.size(); }
153 
154  inline bool chunkExists(const std::string& id) const { return map.find(id) != map.end(); }
155 
156  chunksize_t chunkSize(const std::string& id) const;
157 
158  chunksize_t fetch(const std::string& id, void* data, const chunksize_t limit);
159 
160  void save(const std::string& filename, bool append = false);
161  };
162 
163  /**
164  File containing chunks.
165  The file is not loaded in memory, but is scanned when first opened to collect the information about available chunks.
166  */
167  class ChunkFile : public ChunkStream {
168  private:
169  const std::string filename;
171  public:
172  /**
173  Returns `true` if a given file is readable
174  */
175  static bool readable(const std::string& filename);
176 
177  /**
178  Creates a read-only chunk collection from a file.
179  \param[in] filename The file name / path
180  \param[in] openNow If `true`, the file is read right away. Otherwise it is done on open() call.
181  No information is available about chunks in the file until it is opened.
182  */
183  ChunkFile(const std::string& filename, bool openNow = true);
184  void open();
185  void close();
186  };
187 
188  /**
189  Writes chunks to a file
190  */
192  private:
193  std::fstream stream;
194  public:
195  ChunkFileWriter(const std::string& filename, bool append = false);
197 
198  void operator()(const std::string& id, const void* data, const chunksize_t size);
199 
200  template<typename datatype> void operator()(const std::string& id, datatype something) {
201  (*this)(id, &something, sizeof(something));
202  }
203  };
204 
205  /**
206  Simply a piece of binary data of a specific size.
207  A brick in ChunkCollection-based data sets.
208  No information is stored on the nature of the data: it is up to the application to interpret the chunk content.
209  */
210  class Chunk {
211  private:
212  size_t chunkSize;
213  void* data;
214  public:
215  /**
216  Makes an empty chunk.
217  */
218  inline Chunk(): chunkSize(0), data(nullptr) {}
219 
220  /**
221  Allocates a chunk of a given size.
222  \param[in] size Chunk size in bytes
223  */
224  Chunk(size_t size);
225 
226  /**
227  Reads a chunk from a collection.
228  \param[in] collection The collection to read from
229  \param[in] id The chunk id to find in the collection
230  */
231  Chunk(ChunkCollection& collection, const std::string& id);
232 
233  ~Chunk();
234 
235  inline Chunk(Chunk&& chunk): chunkSize(chunk.chunkSize), data(chunk.data) {
236  chunk.data = nullptr;
237  chunk.chunkSize = 0;
238  }
239 
240  inline Chunk& operator=(Chunk&& chunk) {
241  if (data)
242  free(data);
243  chunkSize = chunk.chunkSize;
244  data = chunk.data;
245  chunk.data = nullptr;
246  chunk.chunkSize = 0;
247  return *this;
248  }
249 
250  /**
251  Writes a chunk out to a file.
252  \param[in] file The file to write to
253  \param[in] id The chunk id
254  */
255  void writeTo(ChunkFileWriter& file, const std::string& id) const;
256 
257  inline size_t size() const { return chunkSize; }
258 
259  inline void* operator()() { return data; }
260  inline const void* operator()() const { return data; }
261 
262  inline operator bool() const { return data != nullptr; }
263 
264  template<typename datatype> inline datatype* ptr(size_t offset = 0) {
265  return (datatype*)(data) + offset;
266  }
267  template<typename datatype> inline const datatype* ptr(size_t offset = 0) const {
268  return (datatype*)(data) + offset;
269  }
270 
271  template<typename datatype> inline datatype at(size_t offset) const {
272  return ((datatype*)data)[offset];
273  }
274 
275  template<typename datatype> inline datatype& at(size_t offset) {
276  return ((datatype*)data)[offset];
277  }
278  };
279 }
A key-value pair set storing pieces of arbitrary data (chunks) under string keys.
Definition: chunkfile.h:36
virtual size_t size() const =0
Returns the number of chunks available in the collection after it is opened.
std::vector< datatype > readVector(const std::string &id)
Reads a chunk into a vector of a specific type.
Definition: chunkfile.h:106
virtual void save(const std::string &filename, bool append=false)=0
Saves the collection to a file.
virtual void close()=0
Closes the collection after a reading session.
virtual bool chunkExists(const std::string &id) const =0
Check if a specific chunk exists.
virtual chunksize_t chunkSize(const std::string &id) const =0
Retrieves size of a specific chunk.
virtual void open()=0
Opens the collection to read chunks from it.
virtual chunksize_t fetch(const std::string &id, void *data, const chunksize_t limit)=0
Reads a chunk.
datatype read(const std::string &id)
Reads a chunk and casts it into a given type.
Definition: chunkfile.h:91
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
void operator()(const std::string &id, datatype something)
Definition: chunkfile.h:200
ChunkFileWriter(const std::string &filename, bool append=false)
Definition: chunkfile.cpp:132
File containing chunks.
Definition: chunkfile.h:167
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
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
ChunkStream(InputStream &stream)
Definition: chunkfile.h:143
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 chunkExists(const std::string &id) const
Check if a specific chunk exists.
Definition: chunkfile.h:154
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
datatype & at(size_t offset)
Definition: chunkfile.h:275
datatype * ptr(size_t offset=0)
Definition: chunkfile.h:264
const void * operator()() const
Definition: chunkfile.h:260
datatype at(size_t offset) const
Definition: chunkfile.h:271
void writeTo(ChunkFileWriter &file, const std::string &id) const
Writes a chunk out to a file.
Definition: chunkfile.cpp:168
Chunk & operator=(Chunk &&chunk)
Definition: chunkfile.h:240
Chunk(Chunk &&chunk)
Definition: chunkfile.h:235
size_t size() const
Definition: chunkfile.h:257
const datatype * ptr(size_t offset=0) const
Definition: chunkfile.h:267
void * operator()()
Definition: chunkfile.h:259
size_t chunkSize
Definition: chunkfile.h:212
Chunk()
Makes an empty chunk.
Definition: chunkfile.h:218
InputStream reading from a file.
Definition: input_stream.h:54
Minimal input stream interface.
Definition: input_stream.h:27
Beatmup object base class
Definition: basic_types.h:67
uint32_t chunksize_t
Definition: chunkfile.h:29
std::string to_string(Beatmup::NNets::ActivationFunction function)
JNIEnv jlong jstring id
JNIEnv jstring jboolean openNow
JNIEnv jlong jstring filename
Beatmup::IntPoint result
JNIEnv jlong jstring jboolean append
jlong jobject size