libebml_ng
ebmlLazyLoad.h
Go to the documentation of this file.
1 #ifndef EBML_NG_LAZYLOAD_BASE_H
2 #define EBML_NG_LAZYLOAD_BASE_H
3 
4 #include <map>
5 #include <string>
6 #include <mutex>
7 #include <shared_mutex>
8 
9 #include "../base/ebmlMasterElementType.h"
10 #include "../base/ebmlMasterElement.h"
11 #include "childElemHelper_t.h"
12 #include "children_m.h"
13 #include "status.h"
14 #include "prepared_insert_t.h"
15 #include "prepared_multiinsert_t.h"
16 #include "prepared_move_t.h"
17 #include "prepared_remove_t.h"
18 #include "prepared_resize_t.h"
19 #include "prepared_fallocate_t.h"
20 #include "locks.h"
21 #include "../../ebmlVoid.h"
22 #include "../../repr.h"
23 
24 #define EN_IF_INST(T, R) std::enable_if_t<!std::is_same<ebmlElement, T>::value && std::is_base_of<ebmlElement, std::decay_t<T>>::value, R>
25 #define EN_IF_CLS(T, R) std::enable_if_t<std::is_base_of<ebmlElementType, std::decay_t<T>>::value, R>
26 #define EN_IFN_INST(T, R) std::enable_if_t<!std::is_base_of<ebmlElement, std::decay_t<T>>::value, R>
27 #define EN_IFN_CLS(T, R) std::enable_if_t<!std::is_base_of<ebmlElementType, std::decay_t<T>>::value, R>
28 #define KEY_ARGS typename K, typename H = std::hash<K>, typename E = std::equal_to<K>
29 
30 namespace ebml {
31  typedef std::pair<ebmlElement_sp, seekData_t*> elem_seek_pair;
32 
34 
47  protected:
48  const childElemHelper_t* _childHelper = &childHelper;
49  public:
50  ebmlLazyLoadType(const char*, const std::wstring&, const childTypeSpecArg_l&);
51  ebmlLazyLoadType(ebmlID_t, const std::wstring&, const childTypeSpecArg_l&);
52  ebmlLazyLoadType(const char*, const std::wstring&, const childTypeSpecArg_l&, const seekHelper_t*);
53  ebmlLazyLoadType(ebmlID_t, const std::wstring&, const childTypeSpecArg_l&, const seekHelper_t*);
54 
55  ebmlLazyLoadType(const char*, const std::wstring&, const childTypeSpecArg_l&, const childElemHelper_t*);
56  ebmlLazyLoadType(ebmlID_t, const std::wstring&, const childTypeSpecArg_l&, const childElemHelper_t*);
57  ebmlLazyLoadType(const char*, const std::wstring&, const childTypeSpecArg_l&, const seekHelper_t*, const childElemHelper_t*);
58  ebmlLazyLoadType(ebmlID_t, const std::wstring&, const childTypeSpecArg_l&, const seekHelper_t*, const childElemHelper_t*);
59 
60  friend class ebmlSchema;
61  friend class ebmlLazyLoad;
62  };
63 
65 
88 
89  protected:
90  mutable std::shared_mutex _mutex;
92  ioBase* _file_raw = nullptr;
93  size_t _dataSize;
94 
95  /* Children management members */
97  std::unordered_map<
98  ebmlID_t,
99  std::map<off_t, seekData_t*>
101  std::unordered_map<ebmlID_t, std::unique_ptr<seekMapBase>> _children_by_key;
102 
104 
105  ebmlLazyLoad(const ebmlLazyLoadType *, ioBase&, off_t, vintWidth_t, size_t);
106  ebmlLazyLoad(const ebmlLazyLoadType *, ioBase&, off_t, vintWidth_t, size_t, const ebmlElement_l&);
107 
108  ebmlLazyLoad(const ebmlLazyLoadType *, ebmlLazyLoad&, off_t, vintWidth_t, size_t);
109  ebmlLazyLoad(const ebmlLazyLoadType *, ebmlLazyLoad&, off_t, vintWidth_t, size_t, const ebmlElement_l&);
110 
111  size_t _initNew(ioBase&, off_t, vintWidth_t, size_t);
112 
113  public:
114  const children_m& seeksByOffset() const;
115  const std::unordered_map<
116  ebmlID_t,
117  std::map<off_t, seekData_t*>
118  >& seeksByEBMLID() const;
119  const std::unordered_map<ebmlID_t, std::unique_ptr<seekMapBase>>& seeksByKey() const;
120  ioBase& file() const;
121 
122  /* SYNCHRONIZATIOn*/
123  public:
124  readLock_t getRLock() const;
125  readLock_t getRLock(const readLock_t&) const;
126 
127  writeLock_t getWLock() const;
128  writeLock_t getWLock(const readLock_t&) const;
129  writeLock_t getWLock(const writeLock_t&) const;
130 
131  writeLock_t getGlobalLock() const;
132 
133  private:
134  void _verifyLock(const writeLock_t& lock) const;
135 
136  /* TODO: Find another place in the declaration for this member*/
137  public:
138  off_t endOfData() const;
139 
140  /* RETRIEVAL */
141  public:
142  inline ebml::ptr<ebmlElement> get(off_t);
143  inline ebml::ptr<ebmlElement> get(off_t, const readLock_t&);
144  inline ebml::ptr<ebmlElement> get(off_t, const writeLock_t&);
145 
146  private:
147  ebml::ptr<ebmlElement> _get(off_t);
148 
149  public:
150  template<typename T> inline ebml::ptr<T> get(off_t);
151  template<typename T> inline ebml::ptr<T> get(off_t, const readLock_t&);
152  template<typename T> inline ebml::ptr<T> get(off_t, const writeLock_t&);
153 
154  private:
155  template<typename T> inline ebml::ptr<T> _get(off_t);
156 
157  public:
158  inline ebml::ptr<ebmlElement> get(ebmlID_t, size_t);
159  inline ebml::ptr<ebmlElement> get(ebmlID_t, size_t, const readLock_t&);
160  inline ebml::ptr<ebmlElement> get(ebmlID_t, size_t, const writeLock_t&);
161 
162  private:
163  ebml::ptr<ebmlElement> _get(ebmlID_t, size_t);
164 
165  public:
166  template<typename T> ebml::ptr<T> get(ebmlID_t, size_t);
167  template<typename T> ebml::ptr<T> get(ebmlID_t, size_t, const readLock_t&);
168  template<typename T> ebml::ptr<T> get(ebmlID_t, size_t, const writeLock_t&);
169 
170  private:
171  template<typename T> ebml::ptr<T> _get(ebmlID_t, size_t);
172 
173  public:
185  template<KEY_ARGS> EN_IFN_INST(K, ebml::ptr<ebmlElement>) getByKey(ebmlID_t, const K&);
186  template<KEY_ARGS> EN_IFN_INST(K, ebml::ptr<ebmlElement>) getByKey(ebmlID_t, const K&, const readLock_t&);
187  template<KEY_ARGS> EN_IFN_INST(K, ebml::ptr<ebmlElement>) getByKey(ebmlID_t, const K&, const writeLock_t&);
188 
189  private:
190  template<KEY_ARGS> EN_IFN_INST(K, ebml::ptr<ebmlElement>) _getByKey(ebmlID_t, const K&);
191 
192  public:
193  template<typename T, KEY_ARGS> EN_IF_INST(T, ebml::ptr<T>) getByKey(ebmlID_t, const K&);
194  template<typename T, KEY_ARGS> EN_IF_INST(T, ebml::ptr<T>) getByKey(ebmlID_t, const K&, const readLock_t&);
195  template<typename T, KEY_ARGS> EN_IF_INST(T, ebml::ptr<T>) getByKey(ebmlID_t, const K&, const writeLock_t&);
196 
197  private:
198  template<typename T, KEY_ARGS> EN_IF_INST(T, ebml::ptr<T>) _getByKey(ebmlID_t, const K&);
199 
200  public:
201  inline ebml::ptr<const ebmlElement> cget(off_t) const;
202  inline ebml::ptr<const ebmlElement> cget(off_t, const readLock_t&) const;
203  inline ebml::ptr<const ebmlElement> cget(off_t, const writeLock_t&) const;
204 
205  private:
206  ebml::ptr<const ebmlElement> _cget(off_t) const;
207 
208  public:
209  template<typename T> ebml::ptr<T> cget(off_t) const;
210  template<typename T> ebml::ptr<T> cget(off_t, const readLock_t&) const;
211  template<typename T> ebml::ptr<T> cget(off_t, const writeLock_t&) const;
212 
213  private:
214  template<typename T> ebml::ptr<T> _cget(off_t) const;
215 
216  public:
217  inline ebml::ptr<const ebmlElement> cget(ebmlID_t, size_t) const;
218  inline ebml::ptr<const ebmlElement> cget(ebmlID_t, size_t, const readLock_t&) const;
219  inline ebml::ptr<const ebmlElement> cget(ebmlID_t, size_t, const writeLock_t&) const;
220 
221  private:
222  ebml::ptr<const ebmlElement> _cget(ebmlID_t, size_t) const;
223 
224  public:
225  template<typename T> ebml::ptr<T> cget(ebmlID_t, size_t) const;
226  template<typename T> ebml::ptr<T> cget(ebmlID_t, size_t, const readLock_t&) const;
227  template<typename T> ebml::ptr<T> cget(ebmlID_t, size_t, const writeLock_t&) const;
228 
229  private:
230  template<typename T> ebml::ptr<T> _cget(ebmlID_t, size_t) const;
231 
232  public:
233  template<KEY_ARGS> EN_IFN_INST(K, ebml::ptr<const ebmlElement>) cgetByKey(ebmlID_t, const K&) const;
234  template<KEY_ARGS> EN_IFN_INST(K, ebml::ptr<const ebmlElement>) cgetByKey(ebmlID_t, const K&, const readLock_t&) const;
235  template<KEY_ARGS> EN_IFN_INST(K, ebml::ptr<const ebmlElement>) cgetByKey(ebmlID_t, const K&, const writeLock_t&) const;
236 
237  private:
238  template<KEY_ARGS> EN_IFN_INST(K, ebml::ptr<const ebmlElement>) _cgetByKey(ebmlID_t, const K&) const;
239 
240  public:
241  template<typename T, KEY_ARGS> EN_IF_INST(T, ebml::ptr<T>) cgetByKey(ebmlID_t, const K&) const;
242  template<typename T, KEY_ARGS> EN_IF_INST(T, ebml::ptr<T>) cgetByKey(ebmlID_t, const K&, const readLock_t&) const;
243  template<typename T, KEY_ARGS> EN_IF_INST(T, ebml::ptr<T>) cgetByKey(ebmlID_t, const K&, const writeLock_t&) const;
244 
245  private:
246  template<typename T, KEY_ARGS> EN_IF_INST(T, ebml::ptr<T>) _cgetByKey(ebmlID_t, const K&) const;
247 
248  /* INSERTION */
249 
250  public:
251  status_t<prepared_insert_t> canInsert(off_t, sizetree_t&&, const writeLock_t&);
252  status_t<prepared_multiinsert_t> canInsert(off_t, std::vector<sizetree_t>&&, const writeLock_t&);
253 
254  private:
255  status_t<prepared_insert_t> _canInsert(off_t, sizetree_t&&);
256  status_t<prepared_multiinsert_t> _canInsert(off_t, std::vector<sizetree_t>&&);
257 
258  // Insertion functions
259 
260  // Insert single ebmlElement instance
261  public:
262  inline status_t<prepared_insert_t> canInsert(off_t, const ebml::ptr<ebmlElement>&, const writeLock_t&);
263 
264  inline seekData_t* insert(off_t, const ebml::ptr<ebmlElement>&);
265  inline seekData_t* insert(off_t, const ebml::ptr<ebmlElement>&, const readLock_t&);
266  inline seekData_t* insert(off_t, const ebml::ptr<ebmlElement>&, const writeLock_t&);
267  inline seekData_t* insert(off_t, const ebml::ptr<ebmlElement>&, const writeLock_t&, const status_t<prepared_insert_t>&);
268 
269  private:
270  status_t<prepared_insert_t> _canInsert(off_t, const ebml::ptr<ebmlElement>&);
271 
272  inline seekData_t* _insert(off_t, const ebml::ptr<ebmlElement>&);
273  seekData_t* _insert(off_t, const ebml::ptr<ebmlElement>&, const status_t<prepared_insert_t>&);
274 
275  // Insert multiple ebmlElement instances
276  public:
277  status_t<prepared_multiinsert_t> canInsert(off_t, const ebmlElement_l&, const writeLock_t&);
278 
279  std::vector<seekData_t*> insert(off_t, const ebmlElement_l&);
280  std::vector<seekData_t*> insert(off_t, const ebmlElement_l&, const readLock_t&);
281  std::vector<seekData_t*> insert(off_t, const ebmlElement_l&, const writeLock_t&);
282  std::vector<seekData_t*> insert(off_t, const ebmlElement_l&, const writeLock_t&, const status_t<prepared_multiinsert_t>&);
283 
284  private:
285  status_t<prepared_multiinsert_t> _canInsert(off_t, const ebmlElement_l&);
286  std::vector<seekData_t*> _insert(off_t, const ebmlElement_l& children, const status_t<prepared_multiinsert_t>&);
287 
288  // Insert data from std::string (WARNING: The only validation check is to check the ebmlID and data size. Use responsibly!)
289  public:
290  // TODO: Support multiple elements in single string.
291  status_t<prepared_insert_t> canInsert(off_t, const std::string&, const writeLock_t&);
292 
293  seekData_t* insert(off_t, const std::string&);
294  seekData_t* insert(off_t, const std::string&, const readLock_t&);
295  seekData_t* insert(off_t, const std::string&, const writeLock_t&);
296  seekData_t* insert(off_t, const std::string&, const writeLock_t&, const status_t<prepared_insert_t>&);
297 
298  private:
299  status_t<prepared_insert_t> _canInsert(off_t, const std::string&);
300  inline seekData_t* _insert(off_t, const std::string&, const status_t<prepared_insert_t>&);
301 
302  // Insert data from const char* (WARNING: The only validation check is to check the ebmlID and data size. Use responsibly!)
303  public:
304  inline status_t<prepared_insert_t> canInsert(off_t, const char*, const writeLock_t&);
305 
306  inline seekData_t* insert(off_t, const char* data);
307  inline seekData_t* insert(off_t, const char* data, const readLock_t&);
308  inline seekData_t* insert(off_t, const char* data, const writeLock_t&);
309  inline seekData_t* insert(off_t, const char* data, const writeLock_t&, const status_t<prepared_insert_t>&);
310 
311  private:
312  inline status_t<prepared_insert_t> _canInsert(off_t, const char*);
313  seekData_t* _insert(off_t, const char* data, const status_t<prepared_insert_t>&);
314 
315  public:
316  template<typename T, typename... Args> inline EN_IF_CLS(T, elem_seek_pair) insert(off_t, const T& cls, Args&&...);
317  template<typename T, typename... Args> inline EN_IF_CLS(T, elem_seek_pair) insert(off_t, const readLock_t&, const T& cls, Args&&...);
329  template<typename T, typename... Args> inline EN_IF_CLS(T, elem_seek_pair) insert(off_t, const writeLock_t&, const T& cls, Args&&...);
330  template<typename T, typename... Args> inline EN_IF_CLS(T, elem_seek_pair) insert(off_t, const writeLock_t&, const status_t<prepared_insert_t>&, const T& cls, Args&&...);
331 
332  private:
333  template<typename T, typename... Args>
334  inline std::enable_if_t<std::is_base_of<ebmlLazyLoadType, T>::value, std::pair<ebmlElement_sp, seekData_t*>> _insert(off_t offset, const T& cls, vintWidth_t sizeWidth, size_t dataSize, Args... args);
335 
336  template<typename T, typename... Args>
337  inline std::enable_if_t<!std::is_base_of<ebmlLazyLoadType, T>::value && std::is_base_of<ebmlElementType, T>::value, std::pair<ebmlElement_sp, seekData_t*>>_insert(off_t, const T& cls, Args...);
338 
339  /* MOVING */
340 
341  public:
342  status_t<prepared_move_t> canMove(off_t, off_t, const writeLock_t&);
343  void move(off_t, off_t);
344  void move(off_t, off_t, const readLock_t&);
345  void move(off_t, off_t, const writeLock_t&);
346  void move(off_t, off_t, const writeLock_t&, const status_t<prepared_move_t>&);
347 
348  private:
349  status_t<prepared_move_t> _canMove(off_t, off_t);
350  void _move(off_t, off_t, const status_t<prepared_move_t>&);
351 
352  /* RESIZING */
353 
354  public:
355  inline bool sizeSupported(size_t size, const writeLock_t&);
356  inline status_t<prepared_resize_t> canResize(size_t, const writeLock_t&);
357  inline void resize(size_t size);
358  inline void resize(size_t size, const readLock_t&);
359  inline void resize(size_t size, const writeLock_t&);
360  inline void resize(size_t size, const writeLock_t&, const status_t<prepared_resize_t>&);
361 
362  private:
363  inline bool _sizeSupported(size_t size);
364  status_t<prepared_resize_t> _canResize(size_t);
365  inline void _resize(size_t size);
366  void _resize(size_t size, const status_t<prepared_resize_t>&);
367 
368  /* REMOVAL */
369 
370  public:
371  // prepared_remove_t prepareRemove(off_t, off_t, const writeLock_t&);
372  inline status_t<prepared_remove_t> canRemove(off_t, const writeLock_t&);
373  inline void remove(off_t offset);
374  inline void remove(off_t offset, const readLock_t&);
375  inline void remove(off_t offset, const writeLock_t&);
376  inline void remove(off_t offset, const status_t<prepared_remove_t>&, const writeLock_t&);
377  // void remove(off_t offset, const writeLock_t&, const prepared_remove_t&);
378 
379  private:
380  status_t<prepared_remove_t> _canRemove(off_t);
381  inline void _remove(off_t offset);
382  void _remove(off_t offset, const status_t<prepared_remove_t>&);
383 
384  /* BLOCK BOUNDARY SEARCHING */
385 
386  public:
387  off_t findBoundary(off_t offset);
388  off_t findBoundary(off_t offset, const readLock_t&);
389  off_t findBoundary(off_t offset, const writeLock_t&);
390 
391  private:
392  off_t _findBoundary(off_t offset);
393 
394  public:
395  off_t rfindBoundary(off_t offset);
396  off_t rfindBoundary(off_t offset, const readLock_t&);
397  off_t rfindBoundary(off_t offset, const writeLock_t&);
398 
399  private:
400  off_t _rfindBoundary(off_t offset);
401 
402  /* CHILD NAVIGATION*/
403 
404  public:
405  seekData_t* firstChild();
406  seekData_t* firstChild(const readLock_t&);
407  seekData_t* firstChild(const writeLock_t&);
408 
409  private:
410  seekData_t* _firstChild();
411 
412  public:
413  seekData_t* lastChild();
414  seekData_t* lastChild(const readLock_t&);
415  seekData_t* lastChild(const writeLock_t&);
416 
417  private:
418  seekData_t* _lastChild();
419 
420  public:
421  seekData_t* nextChild(off_t offset);
422  seekData_t* nextChild(off_t offset, const readLock_t&);
423  seekData_t* nextChild(off_t offset, const writeLock_t&);
424 
425  private:
426  seekData_t* _nextChild(off_t offset);
427 
428  public:
429  seekData_t* prevChild(off_t offset);
430  seekData_t* prevChild(off_t offset, const readLock_t&);
431  seekData_t* prevChild(off_t offset, const writeLock_t&);
432 
433  private:
434  seekData_t* _prevChild(off_t offset);
435 
436  /* SPACE MANAGEMENT */
437 
438  off_t findFree(off_t offset, size_t size, const writeLock_t&);
439  off_t rfindFree(off_t offset, size_t size, const writeLock_t&);
440 
441  // status_t<prepared_insert_t> canResizeChild(const seekData_t&, size_t size);
442  // status_t<prepared_insert_t> canResizeChild(ebmlElement* child, size_t size);
443 
444 #if HAS_FALLOCATE
445  // Range insertion functions
446  public:
447  inline status_t<prepared_fallocate_t> canInsertRange(off_t offset, size_t size, const writeLock_t&);
448  inline void insertRange(off_t offset, size_t size);
449  inline void insertRange(off_t offset, size_t size, const readLock_t&);
450  inline void insertRange(off_t offset, size_t size, const writeLock_t&);
451  inline void insertRange(off_t offset, size_t size, const status_t<prepared_fallocate_t>&, const writeLock_t&);
452 
453  private:
454  status_t<prepared_fallocate_t> _canInsertRange(off_t offset, size_t size);
455  inline void _insertRange(off_t offset, size_t size);
456  void _insertRange(off_t offset, size_t size, const status_t<prepared_fallocate_t>&);
457 
458  // Range collapse functions
459  public:
460  inline status_t<prepared_fallocate_t> canCollapseRange(off_t offset, size_t size, const writeLock_t&);
461  inline void collapseRange(off_t offset, size_t size);
462  inline void collapseRange(off_t offset, size_t size, const readLock_t&);
463  inline void collapseRange(off_t offset, size_t size, const writeLock_t&);
464  inline void collapseRange(off_t offset, size_t size, const status_t<prepared_fallocate_t>&, const writeLock_t&);
465 
466  private:
467  status_t<prepared_fallocate_t> _canCollapseRange(off_t offset, size_t size);
468  inline void _collapseRange(off_t offset, size_t size);
469  void _collapseRange(off_t offset, size_t size, const status_t<prepared_fallocate_t>&);
470 
471  // Hole punching functions
472  public:
473  inline status_t<prepared_fallocate_t> canPunchHole(off_t offset, size_t size, const writeLock_t&);
474  inline void punchHole(off_t offset, size_t size);
475  inline void punchHole(off_t offset, size_t size, const readLock_t&);
476  inline void punchHole(off_t offset, size_t size, const writeLock_t&);
477  inline void punchHole(off_t offset, size_t size, const status_t<prepared_fallocate_t>&, const writeLock_t&);
478 
479  private:
480  status_t<prepared_fallocate_t> _canPunchHole(off_t offset, size_t size);
481  inline void _punchHole(off_t offset, size_t size);
482  void _punchHole(off_t offset, size_t size, const status_t<prepared_fallocate_t>&);
483 #endif
484 
485  public:
486  // Members from ebmlElement
487  std::wstring minirepr() const override;
488  size_t dataSize() const override;
489 
490  // Child navigation functions
491  seekData_t* _firstChildSeek() const;
492  seekData_t* _lastChildSeek() const;
493  seekData_t* _prevChildSeek(off_t offset, bool strict=true) const;
494  seekData_t* _nextChildSeek(off_t offset, bool strict=true) const;
495 
496  std::pair<children_m::iterator, children_m::iterator> _find(off_t offset, bool left=true);
497  children_m::iterator _findNext(off_t offset, bool strict=true);
498  children_m::iterator _findPrev(off_t offset, bool strict=true);
499  // std::pair<seekData_t*, seekData_t*> _adjacentChildSeeks(off_t, bool left=true) const;
500 
501  // Space management functions
502  off_t _findFree(off_t offset, size_t size);
503  off_t _rfindFree(off_t offset, size_t size);
504 
505  prepared_resize_t _canResizeChild(off_t, size_t size);
506  prepared_resize_t _canResizeChild(const seekData_t&, size_t size);
507 
508  protected:
509  void _handleParseFile(const parseFile&) override;
510  void _handleSeekData(std::unique_ptr<seekData_t>&&);
511  virtual void _handleSeekData(std::unique_ptr<seekData_t>&&, const children_m::iterator&);
512  void _addChild(const ebmlElement_sp&) override;
513  void _addChild(ebmlElement_sp&&) override;
514 
515  ebmlMasterElement::_iterator* _begin() override;
516  ebmlMasterElement::_iterator* _end() override;
517  ebmlMasterElement::_const_iterator* _cbegin() const override;
518  ebmlMasterElement::_const_iterator* _cend() const override;
519 
520  ebml::ptr<ebmlElement> _read_elem(seekData_t& seekData);
521  ebml::ptr<const ebmlElement> _read_elem(seekData_t& seekData) const;
522 
523  friend class ebmlLazyLoadType;
524  friend class seekData_t;
525  };
526 
527  template<SEEKMAPDEFAULTS>
528  class ebmlLazyLoadSeekHelper : public seekHelperByEBMLID<K, H, E, A> {
529  public:
530  seekData_t* makeSeekData(ebmlElement& elem) const = 0;
531  seekData_t* makeSeekData(const ebmlElement& elem) const = 0;
532  // seekData_t* makeSeekData(ebmlElement& elem, ebmlElement& child) const = 0;
533  seekData_t* makeSeekData(const ebmlElement& elem, const ebmlElement& child) const;
534  };
535 
537  auto lock = getRLock();
538  return _get(offset);
539  }
540 
541  inline ebml::ptr<ebmlElement> ebmlLazyLoad::get(off_t offset, const readLock_t& lock) {
542  auto newlocks = getRLock(lock);
543  return _get(offset);
544  }
545 
546  inline ebml::ptr<ebmlElement> ebmlLazyLoad::get(off_t offset, const writeLock_t& lock) {
547  _verifyLock(lock);
548  return _get(offset);
549  }
550 
551  template<typename T> inline ebml::ptr<T> ebmlLazyLoad::get(off_t offset) {
552  auto lock = getRLock();
553  return _get<T>(offset);
554  }
555 
556  template<typename T> inline ebml::ptr<T> ebmlLazyLoad::get(off_t offset, const readLock_t& lock) {
557  auto newlocks = getRLock(lock);
558  return _get<T>(offset);
559  }
560 
561  template<typename T> inline ebml::ptr<T> ebmlLazyLoad::get(off_t offset, const writeLock_t& lock) {
562  _verifyLock(lock);
563  return _get<T>(offset);
564  }
565 
566  template<typename T> inline ebml::ptr<T> ebmlLazyLoad::_get(off_t offset) {
567  return ebml_dynamic_pointer_cast<T>(_get(offset));
568  }
569 
570  inline ebml::ptr<ebmlElement> ebmlLazyLoad::get(ebmlID_t ebmlID, size_t index) {
571  auto lock = getRLock();
572  return _get(ebmlID, index);
573  }
574 
575  inline ebml::ptr<ebmlElement> ebmlLazyLoad::get(ebmlID_t ebmlID, size_t index, const readLock_t& lock) {
576  auto newlocks = getRLock(lock);
577  return _get(ebmlID, index);
578  }
579 
580  inline ebml::ptr<ebmlElement> ebmlLazyLoad::get(ebmlID_t ebmlID, size_t index, const writeLock_t& lock) {
581  _verifyLock(lock);
582  return _get(ebmlID, index);
583  }
584 
586  auto lock = getRLock();
587  return _cget(offset);
588  }
589 
590  inline ebml::ptr<const ebmlElement> ebmlLazyLoad::cget(off_t offset, const readLock_t& lock) const {
591  auto newlocks = getRLock(lock);
592  return _cget(offset);
593  }
594 
595  inline ebml::ptr<const ebmlElement> ebmlLazyLoad::cget(off_t offset, const writeLock_t& lock) const {
596  _verifyLock(lock);
597  return _cget(offset);
598  }
599 
600  template<typename T> inline ebml::ptr<T> ebmlLazyLoad::cget(off_t offset) const {
601  auto lock = getRLock();
602  return _cget<T>(offset);
603  }
604 
605  template<typename T> inline ebml::ptr<T> ebmlLazyLoad::cget(off_t offset, const readLock_t& lock) const {
606  auto newlocks = getRLock(lock);
607  return _cget<T>(offset);
608  }
609 
610  template<typename T> inline ebml::ptr<T> ebmlLazyLoad::cget(off_t offset, const writeLock_t& lock) const {
611  _verifyLock(lock);
612  return _cget<T>(offset);
613  }
614 
615  template<typename T> inline ebml::ptr<T> ebmlLazyLoad::_cget(off_t offset) const {
616  return ebml_dynamic_pointer_cast<T>(_cget(offset));
617  }
618 
619  inline ebml::ptr<const ebmlElement> ebmlLazyLoad::cget(ebmlID_t ebmlID, size_t index) const {
620  auto lock = getRLock();
621  return _cget(ebmlID, index);
622  }
623 
624  inline ebml::ptr<const ebmlElement> ebmlLazyLoad::cget(ebmlID_t ebmlID, size_t index, const readLock_t& lock) const {
625  auto newlocks = getRLock(lock);
626  return _cget(ebmlID, index);
627  }
628 
629  inline ebml::ptr<const ebmlElement> ebmlLazyLoad::cget(ebmlID_t ebmlID, size_t index, const writeLock_t& lock) const {
630  _verifyLock(lock);
631  return _cget(ebmlID, index);
632  }
633 
634  template<typename K, typename H, typename E>
636  auto lock = getRLock();
637  return _getByKey<K, H, E>(ebmlID, key);
638  }
639 
640  template<typename K, typename H, typename E>
641  inline EN_IFN_INST(K, ebml::ptr<ebmlElement>) ebmlLazyLoad::getByKey(ebmlID_t ebmlID, const K& key, const readLock_t& rlock) {
642  auto lock = getRLock(rlock);
643  return _getByKey<K, H, E>(ebmlID, key);
644  }
645 
646  template<typename K, typename H, typename E>
647  inline EN_IFN_INST(K, ebml::ptr<ebmlElement>) ebmlLazyLoad::getByKey(ebmlID_t ebmlID, const K& key, const writeLock_t& wlock) {
648  _verifyLock(wlock);
649  return _getByKey<K, H, E>(ebmlID, key);
650  }
651 
652  template<typename K, typename H, typename E>
653  EN_IFN_INST(K, ebml::ptr<ebmlElement>) ebmlLazyLoad::_getByKey(ebmlID_t ebmlID, const K& key) {
654  if (this->_children_by_key.count(ebmlID) == 0) {
655  std::string errmsg = "element not found with ebmlID ";
656  errmsg += std::to_string(ebmlID);
657  errmsg += " and key ";
658  errmsg += pack(ebml::repr(key));
659  throw ebmlDecodeError(errmsg, DECODE_ERR_DEFAULT, -1);
660  }
661 
662  auto& seekmap = this->_children_by_key.at(ebmlID)->withKeyType<K, H, E>();
663 
664  if (seekmap.count(key) == 0) {
665  std::string errmsg = "element not found with ebmlID ";
666  errmsg += std::to_string(ebmlID);
667  errmsg += " and key ";
668  errmsg += pack(ebml::repr(key));
669  throw ebmlDecodeError(errmsg, DECODE_ERR_DEFAULT, -1);
670  }
671 
672  auto seekData = seekmap.at(key);
673 
674  return seekData->get();
675  }
676 
677  template<typename T, typename K, typename H, typename E>
678  inline EN_IF_INST(T, ebml::ptr<T>) ebmlLazyLoad::getByKey(ebmlID_t ebmlID, const K& key) {
679  auto lock = getRLock();
680  return _getByKey<T, K, H, E>(ebmlID, key);
681  }
682 
683  template<typename T, typename K, typename H, typename E>
684  inline EN_IF_INST(T, ebml::ptr<T>)ebmlLazyLoad::_getByKey(ebmlID_t ebmlID, const K& key) {
685  return ebml_dynamic_pointer_cast<T>(this->_getByKey<K, H, E>(ebmlID, key));
686  }
687 
689  _verifyLock(lock);
690  return _canInsert(offset, elem_p);
691  }
692 
693  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const ebml::ptr<ebmlElement>& elem_p) {
694  auto lock = getWLock();
695  return _insert(offset, elem_p);
696  }
697 
698  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const ebml::ptr<ebmlElement>& elem_p, const readLock_t& lock) {
699  auto _lock = getWLock(lock);
700  return _insert(offset, elem_p);
701  }
702 
703  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const ebml::ptr<ebmlElement>& elem_p, const writeLock_t& lock) {
704  _verifyLock(lock);
705  return _insert(offset, elem_p);
706  }
707 
708  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const ebml::ptr<ebmlElement>& elem_p, const writeLock_t& lock, const status_t<prepared_insert_t>& prepared) {
709  _verifyLock(lock);
710  return _insert(offset, elem_p, prepared);
711  }
712 
713  inline seekData_t* ebmlLazyLoad::_insert(off_t offset, const ebml::ptr<ebmlElement>& elem_p) {
714  auto prepared = _canInsert(offset, elem_p);
715  return _insert(offset, elem_p, prepared);
716  }
717 
718  // Insert from std::string
719 
720  inline status_t<prepared_insert_t> ebmlLazyLoad::canInsert(off_t offset, const std::string& data, const writeLock_t& lock) {
721  _verifyLock(lock);
722  return _canInsert(offset, data);
723  }
724 
725  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const std::string& data) {
726  auto lock = getWLock();
727  auto prepared = _canInsert(offset, data);
728  return _insert(offset, data, prepared);
729  }
730 
731  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const std::string& data, const readLock_t& lock) {
732  auto _lock = getWLock(lock);
733  auto prepared = _canInsert(offset, data);
734  return _insert(offset, data, prepared);
735  }
736 
737  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const std::string& data, const writeLock_t& lock) {
738  _verifyLock(lock);
739  auto prepared = _canInsert(offset, data);
740  return _insert(offset, data, prepared);
741  }
742 
743  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const std::string& data, const writeLock_t& lock, const status_t<prepared_insert_t>& status) {
744  _verifyLock(lock);
745  return _insert(offset, data, status );
746  }
747 
748  inline seekData_t* ebmlLazyLoad::_insert(off_t offset, const std::string& data, const status_t<prepared_insert_t>& status) {
749  return _insert(offset, data.data(), status);
750  }
751 
752  // Insert from const char*
753 
754  inline status_t<prepared_insert_t> ebmlLazyLoad::canInsert(off_t offset, const char* data, const writeLock_t& lock) {
755  _verifyLock(lock);
756  return _canInsert(offset, data);
757  }
758 
759  inline status_t<prepared_insert_t> ebmlLazyLoad::_canInsert(off_t offset, const char* data) {
760  auto parsed = parseString(data, UNKNOWN);
761  auto sizetree = sizetree_t(parsed.ebmlIDWidth, parsed.sizeWidth, parsed.dataSize);
762  return _canInsert(offset, std::move(sizetree));
763  }
764 
765  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const char* data) {
766  auto lock = getWLock();
767  auto prepared = _canInsert(offset, data);
768  return _insert(offset, data, prepared);
769  }
770 
771  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const char* data, const readLock_t& lock) {
772  auto _lock = getWLock(lock);
773  auto prepared = _canInsert(offset, data);
774  return _insert(offset, data, prepared);
775  }
776 
777  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const char* data, const writeLock_t& lock) {
778  _verifyLock(lock);
779  auto prepared = _canInsert(offset, data);
780  return _insert(offset, data, prepared);
781  }
782 
783  inline seekData_t* ebmlLazyLoad::insert(off_t offset, const char* data, const writeLock_t& lock, const status_t<prepared_insert_t>& status) {
784  _verifyLock(lock);
785  return _insert(offset, data, status );
786  }
787 
789  _verifyLock(wlock);
790  return _canRemove(offset);
791  }
792 
793  inline void ebmlLazyLoad::remove(off_t offset) {
794  auto lock = getWLock();
795  _remove(offset);
796  }
797 
798  inline void ebmlLazyLoad::remove(off_t offset, const readLock_t& rlock) {
799  auto lock = getWLock(rlock);
800  _remove(offset);
801  }
802 
803  inline void ebmlLazyLoad::remove(off_t offset, const writeLock_t& wlock) {
804  _verifyLock(wlock);
805  _remove(offset);
806  }
807 
808  inline void ebmlLazyLoad::remove(off_t offset, const status_t<prepared_remove_t>& status, const writeLock_t& wlock) {
809  _verifyLock(wlock);
810  _remove(offset, status);
811  }
812 
813  inline void ebmlLazyLoad::_remove(off_t offset) {
814  auto status = _canRemove(offset);
815  _remove(offset, status);
816  }
817 
818  inline bool ebmlLazyLoad::sizeSupported(size_t size, const writeLock_t& lock) {
819  _verifyLock(lock);
820  return _sizeSupported(size);
821  }
822 
823  inline bool ebmlLazyLoad::_sizeSupported(size_t size) {
824  if (size == UNKNOWN) {
825  return true;
826  }
827 
828  return widthAsVint(size) <= this->_sizeWidth;
829  }
830 
831  inline void ebmlLazyLoad::resize(size_t size) {
832  auto lock = getWLock();
833  _resize(size);
834  }
835 
836  inline void ebmlLazyLoad::resize(size_t size, const readLock_t& rlock) {
837  auto lock = getWLock(rlock);
838  _resize(size);
839  }
840 
841  inline void ebmlLazyLoad::_resize(size_t size) {
842  auto status = _canResize(size);
843  _resize(size, status);
844  }
845 
846  template<typename T, typename... Args>
847  inline EN_IF_CLS(T, elem_seek_pair) ebmlLazyLoad::insert(off_t offset, const T& cls, Args&&... args) {
848  auto lock = getWLock();
849  return _insert(offset, cls, args...);
850  }
851 
852  template<typename T, typename... Args>
853  inline EN_IF_CLS(T, elem_seek_pair) ebmlLazyLoad::insert(off_t offset, const readLock_t& rlock, const T& cls, Args&&... args) {
854  auto lock = getWLock(rlock);
855  return _insert(offset, cls, args...);
856  }
857 
858  template<typename T, typename... Args>
859  inline EN_IF_CLS(T, elem_seek_pair) ebmlLazyLoad::insert(off_t offset, const writeLock_t& wlock, const T& cls, Args&&... args) {
860  _verifyLock(wlock);
861  return _insert(offset, cls, args...);
862  }
863 
864  template<typename T, typename... Args>
865  inline std::enable_if_t<std::is_base_of<ebmlLazyLoadType, T>::value, std::pair<ebmlElement_sp, seekData_t*>>
866  ebmlLazyLoad::_insert(off_t offset, const T& cls, vintWidth_t sizeWidth, size_t dataSize, Args... args) {
868  auto query = _canInsert(offset, std::move(sizetree));
869  auto& data = query.data();
870 
871  if (!query) {
872  auto elem = ebml_static_pointer_cast<const ebmlElement>(sp());
873  query.throw_exc(elem);
874  // ebmlInsertionError exc = query;
875  // throw exc;
876  }
877 
878  auto& f = file();
879  auto poffset = this->dataOffsetInFile();
880 
881  if (data.prev.endOffset < offset) {
882  Void.writeVoid(f, poffset + data.prev.endOffset, offset - data.prev.endOffset);
883  }
884 
885  auto elem = ebml_static_pointer_cast<ebmlElement>(cls(*this, offset, sizeWidth, dataSize, args...));
886  // this->_attachChild(elem);
887  // elem->_offsetInParent = offset;
888 
889  if (data.extent.endOffset < data.next) {
890  Void.writeVoid(f, poffset + data.extent.endOffset, data.next - data.extent.endOffset);
891  }
892 
893  seekData_t* seekData = elem->makeSeekData();
894  auto seekData_up = std::unique_ptr<seekData_t>(seekData);
895  this->_handleSeekData(std::move(seekData_up));
896  return {std::move(elem), seekData};
897  }
898 
899  template<typename T, typename... Args>
900  inline std::enable_if_t<!std::is_base_of<ebmlLazyLoadType, T>::value && std::is_base_of<ebmlElementType, T>::value, std::pair<ebmlElement_sp, seekData_t*>>
901  ebmlLazyLoad::_insert(off_t offset, const T& cls, Args... args) {
902  auto elem = ebml_static_pointer_cast<ebmlElement>(cls(args...));
903  status_t<prepared_insert_t> status = _canInsert(offset, elem);
904  auto seek = _insert(offset, elem, status);
905  return {std::move(elem), seek};
906  }
907 
908  // template<typename T>
909  // inline EN_IF_CLS(T, elem_seek_pair) ebmlLazyLoad::insert(off_t offset, const ebml::ptr<T>& child) {
910  // return this->insert(offset, ebml_static_pointer_cast<ebmlElement>(child));
911  // }
912  //
913  // template<typename T>
914  // inline std::enable_if_t<!std::is_base_of<ebmlLazyLoad, T>::value && std::is_base_of<ebmlElement, T>::value, seekData_t*>
915  // ebmlLazyLoad::_insert(off_t offset, const ebml::ptr<T>& child) {
916  // return this->_insert(offset, ebml_static_pointer_cast<ebmlElement>(child));
917  // }
918 }
919 
920 #endif
Helper class for creating and initializing seek data.
Definition: seekdata.h:195
T & data(const ebmlElement_sp &elem)
std::enable_if_t<!std::is_base_of< ebmlElement, std::decay_t< K > >::value, ebml::ptr< ebmlElement > > getByKey(ebmlID_t, const K &)
Gets a child element based on a user-defined key.
Definition: ebmlLazyLoad.h:635
friend class ebmlSchema
Definition: ebmlLazyLoad.h:60
ebml_shared_ptr< T > ebml_dynamic_pointer_cast(const ebml_shared_ptr< U > &)
Definition: ptrs.h:676
std::list< childTypeSpecArg_t > childTypeSpecArg_l
Alias for a list of child type specification arguments.
Definition: childTypeSpec.h:39
Definition: childElemHelper_t.h:22
size_t size(const std::string &value)
Definition: binary.h:8
ebmlElement(const ebmlElementType *)
Protected constructor.
Definition: ebmlElement.cpp:22
#define EN_IF_INST(T, R)
Definition: ebmlLazyLoad.h:24
seekData_t * makeSeekData(ebmlElement &elem) const =0
std::unordered_map< ebmlID_t, std::map< off_t, seekData_t * > > _children_by_ebmlID
Definition: ebmlLazyLoad.h:100
Definition: ebmlMasterElement.h:269
Represents a parsed EBML string segment.
Definition: string.h:37
status_t< prepared_remove_t > canRemove(off_t, const writeLock_t &)
Definition: ebmlLazyLoad.h:788
Represents parsed seek data extracted from an EBML element.
Definition: seekdata.h:39
sizetree_t sizetree() const
Generates the size tree for the element hierarchy.
Definition: ebmlMasterElement.cpp:90
Definition: locks.h:13
Represents a parsed EBML file segment.
Definition: io.h:32
Definition: prepared.h:133
#define DECODE_ERR_DEFAULT
Definition: exceptions.h:13
ebmlID_t ebmlID
EBML ID associated with this element type.
Definition: ebmlElementType.h:129
Definition: status.h:14
seekData_t * insert(off_t, const ebml::ptr< ebmlElement > &)
Definition: ebmlLazyLoad.h:693
ioBase & file() const
Definition: ebmlLazyLoad.cpp:109
Definition: basictypes.h:40
A drop-in replacement for std::shared_ptr tailored for EBML objects.
Definition: ptrs.h:27
const ebmlLazyLoadType & cls() const
Returns a reference to the associated element class.
std::unordered_map< ebmlID_t, std::unique_ptr< seekMapBase > > _children_by_key
Definition: ebmlLazyLoad.h:101
children_m _children_by_offset
Definition: ebmlLazyLoad.h:96
A template class representing a lazy-loading EBML master element.
Definition: ebmlLazyLoad.h:46
writeLock_t getWLock() const
Definition: ebmlLazyLoad.cpp:228
Definition: ebmlMasterElement.h:324
unsigned char widthAsVint(unsigned long long n)
Computes the minimal width (in bytes) required to encode an unsigned long long as a vint...
Definition: vint.h:51
const size_t UNKNOWN
Special constant representing an unknown or maximum value.
Definition: vint.cpp:15
off_t dataOffsetInFile() const
Definition: ebmlElement.cpp:182
std::wstring repr(const std::string &str)
Definition: repr.cpp:36
unsigned char writeVoid(char *, size_t) const
Definition: ebmlVoid.cpp:16
ebmlVoidType Void
Definition: ebmlVoid.cpp:127
Represents an EBML Master Element with on-disk, transactional child management.
Definition: ebmlLazyLoad.h:85
readLock_t getRLock() const
Definition: ebmlLazyLoad.cpp:161
friend class ebmlLazyLoad
Definition: ebmlLazyLoad.h:61
uint64_t ebmlID_t
Definition: ebmlID_t.h:7
bool sizeSupported(size_t size, const writeLock_t &)
Definition: ebmlLazyLoad.h:818
size_t dataSize() const override
Definition: ebmlLazyLoad.cpp:119
Structure representing the size tree for an EBML master element.
Definition: sizetree_t.h:15
uint8_t vintWidth_t
Definition: ebmlID_t.h:8
ebml::ptr< const ebmlElement > cget(off_t) const
Definition: ebmlLazyLoad.h:585
vintWidth_t _sizeWidth
Definition: ebmlElement.h:224
Definition: ebmlLazyLoad.h:528
ebml_shared_ptr< T > ebml_static_pointer_cast(const ebml_shared_ptr< U > &)
Definition: ptrs.h:731
void remove(off_t offset)
Definition: ebmlLazyLoad.h:793
std::pair< ebmlElement_sp, seekData_t * > elem_seek_pair
Definition: ebmlLazyLoad.h:31
std::shared_mutex _mutex
Definition: ebmlLazyLoad.h:90
void resize(size_t size)
Definition: ebmlLazyLoad.h:831
status_t< prepared_insert_t > canInsert(off_t, sizetree_t &&, const writeLock_t &)
Definition: ebmlLazyLoad.cpp:483
Abstract base class for EBML Element instances.
Definition: ebmlElement.h:79
ioBase_sp _file
Definition: ebmlLazyLoad.h:91
size_t pack(const std::string &value, size_t size, char *dest)
Definition: binary.h:12
unsigned char sizeWidth() const
Definition: ebmlElement.cpp:230
size_t _dataSize
Definition: ebmlLazyLoad.h:93
void _handleSeekData(std::unique_ptr< seekData_t > &&)
Definition: ebmlLazyLoad.cpp:145
Templated helper class for EBML elements that search for key data within child elements.
Definition: seekdata.h:220
#define EN_IF_CLS(T, R)
Definition: ebmlLazyLoad.h:25
ebml::ptr< ebmlElement > get(off_t)
Definition: ebmlLazyLoad.h:536
Base class for file-like IO operations.
Definition: io.h:22
Definition: exceptions.h:46
#define EN_IFN_INST(T, R)
Definition: ebmlLazyLoad.h:26
std::map< off_t, std::unique_ptr< seekData_t > > children_m
Definition: children_m.h:10
std::vector< ebmlElement_sp > ebmlElement_l
Definition: c_ebmlElement_l.h:9
childElemHelper_t childHelper
Definition: childElemHelper_t.cpp:27
Definition: locks.h:27
friend class seekData_t
Definition: ebmlLazyLoad.h:524
ebmlID_t ebmlID() const
Retrieve the EBML ID of the element.
Definition: ebmlElement.cpp:268