adtf_file_library  0.13.2
fileringbuffer.h
Go to the documentation of this file.
1 
17 #ifndef DISK_RING_BUFFER_H
18 #define DISK_RING_BUFFER_H
19 
20 #include <a_util/memory.h>
21 
22 namespace utils5ext
23 {
24 
39 template <typename ADDITIONAL_DATA = uint8_t, uint8_t alignment = 1>
41 {
42  public:
46  struct Item
47  {
48  Item(): file_pos(-1), size(0) {}
50  size_t size;
51  ADDITIONAL_DATA additional;
52  };
53 
58  {
59  public:
66  virtual void onDrop(const Item& dropped_item, const Item& next_item) = 0;
67  };
68 
72  struct ItemPiece
73  {
74  const void* data;
75  size_t data_size;
76  };
77 
79  typedef std::deque<Item> Items;
81  typedef typename Items::const_iterator const_iterator;
82 
83  private:
84  Items _items;
85  File* _file;
86  FilePos _start_offset;
87  FilePos _current_pos;
88  FileSize _current_size;
89  FileSize _max_size;
90  bool _bookkeeping;
91  DropCallback* _callback;
92  a_util::memory::MemoryBuffer _alignment_buffer;
93  Item _rear_item;
94 
95  public:
104  FileRingBuffer(File* file, FilePos start_offset = 0,
105  FileSize max_size = 0, DropCallback* drop_callback = nullptr) :
106  _file(file),
107  _start_offset(start_offset),
108  _current_size(0),
109  _max_size(max_size),
110  _bookkeeping(true),
111  _callback(drop_callback)
112  {
113  file->setFilePos(start_offset, File::fp_begin);
114  _current_pos = start_offset;
115 
116 #ifdef WIN32
117  __pragma(warning(push))
118  __pragma(warning(disable:4127))
119 #endif
120  if (alignment > 1)
121  {
122  _alignment_buffer.allocate(alignment - 1);
123  utils5ext::memZero(_alignment_buffer.getPtr(), _alignment_buffer.getSize());
124  }
125 #ifdef WIN32
126  __pragma(warning(pop))
127 #endif
129  }
130 
136  {
137  return _current_size;
138  }
139 
144  {
145  if (!_bookkeeping)
146  {
147  throw std::runtime_error("history already started wrapping around");
148  }
149 
150  _max_size = _current_size;
151  }
152 
160  void startAppending(Item* rear_data_item = nullptr, Item* last_data_item = nullptr)
161  {
162  if (!_bookkeeping)
163  {
164  throw std::runtime_error("already appending");
165  }
166 
167  _max_size = 0;
168  _file->setFilePos(0, File::fp_end);
169  _current_pos = _file->getFilePos();
170  _bookkeeping = false;
171 
172  if (_rear_item.file_pos == -1 && !_items.empty())
173  {
174  // we never wrapped around.
175  _rear_item = _items.back();
176  }
177 
178  if (rear_data_item)
179  {
180  *rear_data_item = _rear_item;
181  }
182 
183  if (last_data_item)
184  {
185  if (!_items.empty())
186  {
187  *last_data_item = _items.back();
188  }
189  else
190  {
191  *last_data_item = Item();
192  }
193  }
194  }
195 
203  void appendItem(const void* data, size_t data_size,
204  const ADDITIONAL_DATA& additional, FilePos* file_pos = nullptr)
205  {
206  ItemPiece item;
207  item.data = data;
208  item.dataSize = data_size;
209  appendItem(&item, 1, additional, file_pos);
210  }
211 
219  void appendItem(const ItemPiece* pieces, size_t count,
220  const ADDITIONAL_DATA& additional, FilePos* file_pos = nullptr)
221  {
222  size_t data_size = 0;
223  for (size_t piece = 0; piece < count; ++piece)
224  {
225  data_size += pieces[piece].data_size;
226  }
227 
228  if (_max_size && !_items.empty())
229  {
230  if (_current_pos + static_cast<FileSize>(data_size) > _max_size)
231  {
232  // in this case we need to wrap around
233  _file->truncate(_current_pos);
234  _current_size = _current_pos;
235 
236  _rear_item = _items.back();
237 
238  //we need remove all items following this postion
239  while (_items.front().file_pos >= _current_pos)
240  {
241  popFront();
242  }
243 
244  _current_pos = _items.front().file_pos; // this should be equal to the data offset
245  _file->setFilePos(_current_pos, File::fp_begin);
246  }
247  }
248 
249  if (file_pos)
250  {
251  *file_pos = _current_pos;
252  }
253 
254  FilePos write_pos = _current_pos;
255 
256  for (size_t piece = 0; piece < count; ++piece)
257  {
258  _file->writeAll(pieces[piece].data, static_cast<int>(pieces[piece].data_size));
259  }
260 
261  _current_pos += data_size;
262 
264 
265  if (_current_pos > _current_size)
266  {
267  _current_size = _current_pos;
268  }
269 
270  if (_bookkeeping)
271  {
272  Item item;
273  item.file_pos = write_pos;
274  item.size = data_size;
275  item.additional = additional;
276 
277  _items.push_back(item);
278 
279  FilePos start = item.file_pos;
280  FilePos end = _current_pos;
281 
282  while (_items.size() > 1 &&
283  _items.front().file_pos >= start &&
284  _items.front().file_pos < end)
285  {
286  popFront();
287  }
288 
289  if (_rear_item.file_pos != -1)
290  {
291  // we did wrap around at least once
292  // check if this item did overwrite the current rear item
293  if (_rear_item.file_pos < end)
294  {
295  // it has been overwritten by the current one
296  // and was alread removed from the queue in the while loop above
297  // so the current item is the new rear item.
298  _rear_item = _items.back();
299  // make sure that the file ends after the current item
300  _file->truncate(_current_pos);
301  _current_size = _current_pos;
302  }
303  }
304  }
305  }
306 
312  {
313  return _items.begin();
314  }
315 
321  {
322  return _items.end();
323  }
324 
325  protected:
331  {
332  FilePos mod = _current_pos % alignment;
333  if (mod)
334  {
335  FilePos fill = alignment - mod;
336  _file->writeAll(_alignment_buffer.getPtr(),
337  static_cast<size_t>(fill));
338  _current_pos += fill;
339  }
340  }
341 
345  void popFront()
346  {
347  if (_callback)
348  {
349  static Item dummy;
350 
351  Item& item = _items.front();
352  Item* next = &dummy;
353  if (_items.size() > 1)
354  {
355  next = &_items[1];
356  }
357  _callback->onDrop(item, *next);
358  }
359  _items.pop_front();
360  }
361 };
362 
363 }
364 
365 #endif
Definition: fileringbuffer.h:58
virtual void onDrop(const Item &dropped_item, const Item &next_item)=0
Definition: fileringbuffer.h:41
void startWrappingAround()
Definition: fileringbuffer.h:143
const_iterator begin() const
Definition: fileringbuffer.h:311
void fillForAlignment()
Definition: fileringbuffer.h:330
void appendItem(const ItemPiece *pieces, size_t count, const ADDITIONAL_DATA &additional, FilePos *file_pos=nullptr)
Definition: fileringbuffer.h:219
const FileSize & getCurrentSize()
Definition: fileringbuffer.h:135
void startAppending(Item *rear_data_item=nullptr, Item *last_data_item=nullptr)
Definition: fileringbuffer.h:160
void popFront()
Definition: fileringbuffer.h:345
void appendItem(const void *data, size_t data_size, const ADDITIONAL_DATA &additional, FilePos *file_pos=nullptr)
Definition: fileringbuffer.h:203
std::deque< Item > Items
Typedef for convienient access.
Definition: fileringbuffer.h:79
Items::const_iterator const_iterator
An const iterator in the buffer.
Definition: fileringbuffer.h:81
FileRingBuffer(File *file, FilePos start_offset=0, FileSize max_size=0, DropCallback *drop_callback=nullptr)
Definition: fileringbuffer.h:104
const_iterator end() const
Definition: fileringbuffer.h:320
Definition: file.h:121
@ fp_end
offsets are measured from the end of the file
Definition: file.h:187
@ fp_begin
offsets are measured from the beginning of the file
Definition: file.h:181
FilePos setFilePos(FilePos offset, FilePosRef move_mode)
FilePos getFilePos() const
void truncate(FilePos size)
void writeAll(const void *buffer, size_t buffer_size)
Definition: file.h:32
int64_t FilePos
Type for a file position.
Definition: file.h:37
void memZero(void *data, size_t bytes)
Helper function to set a memory buffer to zero.
Definition: file.h:519
FilePos FileSize
Type for the file size.
Definition: file.h:41
Definition: fileringbuffer.h:73
size_t data_size
The size of the piece.
Definition: fileringbuffer.h:75
const void * data
The data of the piece.
Definition: fileringbuffer.h:74
Definition: fileringbuffer.h:47
FilePos file_pos
The file position of the items data.
Definition: fileringbuffer.h:49
ADDITIONAL_DATA additional
additional bookkeeping data
Definition: fileringbuffer.h:51
size_t size
The size of the items data.
Definition: fileringbuffer.h:50

Copyright © CARIAD SE.
Generated on Mon Jun 10 2024 by doxygen 1.9.1
GIT Commit Hash: eb3af397a6b49ad6fcad9a60d8277d909b458b48