uc_transfer_buffer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
6 #include <cassert>
7 #include <cstdlib>
8 
9 namespace uavcan
10 {
11 /*
12  * StaticTransferBufferImpl
13  */
14 int StaticTransferBufferImpl::read(unsigned offset, uint8_t* data, unsigned len) const
15 {
16  if (!data)
17  {
18  UAVCAN_ASSERT(0);
19  return -ErrInvalidParam;
20  }
21  if (offset >= max_write_pos_)
22  {
23  return 0;
24  }
25  if ((offset + len) > max_write_pos_)
26  {
27  len = max_write_pos_ - offset;
28  }
29  UAVCAN_ASSERT((offset + len) <= max_write_pos_);
30  (void)copy(data_ + offset, data_ + offset + len, data);
31  return int(len);
32 }
33 
34 int StaticTransferBufferImpl::write(unsigned offset, const uint8_t* data, unsigned len)
35 {
36  if (!data)
37  {
38  UAVCAN_ASSERT(0);
39  return -ErrInvalidParam;
40  }
41  if (offset >= size_)
42  {
43  return 0;
44  }
45  if ((offset + len) > size_)
46  {
47  len = size_ - offset;
48  }
49  UAVCAN_ASSERT((offset + len) <= size_);
50  (void)copy(data, data + len, data_ + offset);
52  return int(len);
53 }
54 
56 {
57  max_write_pos_ = 0;
58 #if UAVCAN_DEBUG
59  fill(data_, data_ + size_, uint8_t(0));
60 #endif
61 }
62 
63 /*
64  * TransferBufferManagerKey
65  */
66 #if UAVCAN_TOSTRING
67 std::string TransferBufferManagerKey::toString() const
68 {
69  char buf[24];
70  (void)snprintf(buf, sizeof(buf), "nid=%i tt=%i", int(node_id_.get()), int(transfer_type_));
71  return std::string(buf);
72 }
73 #endif
74 
75 /*
76  * DynamicTransferBuffer::Block
77  */
78 TransferBufferManagerEntry::Block*
80 {
81  void* const praw = allocator.allocate(sizeof(Block));
82  if (praw == UAVCAN_NULLPTR)
83  {
84  return UAVCAN_NULLPTR;
85  }
86  return new (praw) Block;
87 }
88 
90 {
91  if (obj != UAVCAN_NULLPTR)
92  {
93  obj->~Block();
94  allocator.deallocate(obj);
95  obj = UAVCAN_NULLPTR;
96  }
97 }
98 
99 void TransferBufferManagerEntry::Block::read(uint8_t*& outptr, unsigned target_offset,
100  unsigned& total_offset, unsigned& left_to_read)
101 {
102  UAVCAN_ASSERT(outptr);
103  for (unsigned i = 0; (i < Block::Size) && (left_to_read > 0); i++, total_offset++)
104  {
105  if (total_offset >= target_offset)
106  {
107  *outptr++ = data[i];
108  left_to_read--;
109  }
110  }
111 }
112 
113 void TransferBufferManagerEntry::Block::write(const uint8_t*& inptr, unsigned target_offset,
114  unsigned& total_offset, unsigned& left_to_write)
115 {
116  UAVCAN_ASSERT(inptr);
117  for (unsigned i = 0; (i < Block::Size) && (left_to_write > 0); i++, total_offset++)
118  {
119  if (total_offset >= target_offset)
120  {
121  data[i] = *inptr++;
122  left_to_write--;
123  }
124  }
125 }
126 
127 /*
128  * DynamicTransferBuffer
129  */
131  uint16_t max_size)
132 {
133  void* const praw = allocator.allocate(sizeof(TransferBufferManagerEntry));
134  if (praw == UAVCAN_NULLPTR)
135  {
136  return UAVCAN_NULLPTR;
137  }
138  return new (praw) TransferBufferManagerEntry(allocator, max_size);
139 }
140 
142 {
143  if (obj != UAVCAN_NULLPTR)
144  {
146  allocator.deallocate(obj);
147  obj = UAVCAN_NULLPTR;
148  }
149 }
150 
151 int TransferBufferManagerEntry::read(unsigned offset, uint8_t* data, unsigned len) const
152 {
153  if (!data)
154  {
155  UAVCAN_ASSERT(0);
156  return -ErrInvalidParam;
157  }
158  if (offset >= max_write_pos_)
159  {
160  return 0;
161  }
162  if ((offset + len) > max_write_pos_)
163  {
164  len = max_write_pos_ - offset;
165  }
166  UAVCAN_ASSERT((offset + len) <= max_write_pos_);
167 
168  // This shall be optimized.
169  unsigned total_offset = 0;
170  unsigned left_to_read = len;
171  uint8_t* outptr = data;
172  Block* p = blocks_.get();
173  while (p)
174  {
175  p->read(outptr, offset, total_offset, left_to_read);
176  if (left_to_read == 0)
177  {
178  break;
179  }
180  p = p->getNextListNode();
181  }
182 
183  UAVCAN_ASSERT(left_to_read == 0);
184  return int(len);
185 }
186 
187 int TransferBufferManagerEntry::write(unsigned offset, const uint8_t* data, unsigned len)
188 {
189  if (!data)
190  {
191  UAVCAN_ASSERT(0);
192  return -ErrInvalidParam;
193  }
194 
195  if (offset >= max_size_)
196  {
197  return 0;
198  }
199  if ((offset + len) > max_size_)
200  {
201  len = max_size_ - offset;
202  }
203  UAVCAN_ASSERT((offset + len) <= max_size_);
204 
205  unsigned total_offset = 0;
206  unsigned left_to_write = len;
207  const uint8_t* inptr = data;
208  Block* p = blocks_.get();
209  Block* last_written_block = UAVCAN_NULLPTR;
210 
211  // First we need to write the part that is already allocated
212  while (p)
213  {
214  last_written_block = p;
215  p->write(inptr, offset, total_offset, left_to_write);
216  if (left_to_write == 0)
217  {
218  break;
219  }
220  p = p->getNextListNode();
221  }
222 
223  // Then we need to append new chunks until all data is written
224  while (left_to_write > 0)
225  {
226  // cppcheck-suppress nullPointer
228 
229  // Allocating the chunk
230  Block* new_block = Block::instantiate(allocator_);
231  if (new_block == UAVCAN_NULLPTR)
232  {
233  break; // We're in deep shit.
234  }
235  // Appending the chain with the new block
236  if (last_written_block != UAVCAN_NULLPTR)
237  {
238  UAVCAN_ASSERT(last_written_block->getNextListNode() == UAVCAN_NULLPTR); // Because it is last in the chain
239  last_written_block->setNextListNode(new_block);
240  new_block->setNextListNode(UAVCAN_NULLPTR);
241  }
242  else
243  {
244  blocks_.insert(new_block);
245  }
246  last_written_block = new_block;
247 
248  // Writing the data
249  new_block->write(inptr, offset, total_offset, left_to_write);
250  }
251 
252  UAVCAN_ASSERT(len >= left_to_write);
253  const unsigned actually_written = len - left_to_write;
254  max_write_pos_ = max(uint16_t(offset + actually_written), uint16_t(max_write_pos_));
255  return int(actually_written);
256 }
257 
259 {
260  key_ = key;
261  max_write_pos_ = 0;
262  Block* p = blocks_.get();
263  while (p)
264  {
265  Block* const next = p->getNextListNode();
266  blocks_.remove(p);
268  p = next;
269  }
270 }
271 
272 /*
273  * TransferBufferManager
274  */
276 {
277  TransferBufferManagerEntry* dyn = buffers_.get();
278  while (dyn)
279  {
280  UAVCAN_ASSERT(!dyn->isEmpty());
281  if (dyn->getKey() == key)
282  {
283  return dyn;
284  }
285  dyn = dyn->getNextListNode();
286  }
287  return UAVCAN_NULLPTR;
288 }
289 
291 {
292  TransferBufferManagerEntry* dyn = buffers_.get();
293  while (dyn)
294  {
295  TransferBufferManagerEntry* const next = dyn->getNextListNode();
296  buffers_.remove(dyn);
298  dyn = next;
299  }
300 }
301 
303 {
304  if (key.isEmpty())
305  {
306  UAVCAN_ASSERT(0);
307  return UAVCAN_NULLPTR;
308  }
309  return findFirst(key);
310 }
311 
313 {
314  if (key.isEmpty())
315  {
316  UAVCAN_ASSERT(0);
317  return UAVCAN_NULLPTR;
318  }
319  remove(key);
320 
322  if (tbme == UAVCAN_NULLPTR)
323  {
324  return UAVCAN_NULLPTR; // Epic fail.
325  }
326 
327  buffers_.insert(tbme);
328 
329  UAVCAN_TRACE("TransferBufferManager", "Buffer created [num=%u], %s", getNumBuffers(), key.toString().c_str());
330 
331  if (tbme != UAVCAN_NULLPTR)
332  {
333  UAVCAN_ASSERT(tbme->isEmpty());
334  tbme->reset(key);
335  }
336  return tbme;
337 }
338 
340 {
341  UAVCAN_ASSERT(!key.isEmpty());
342 
343  TransferBufferManagerEntry* dyn = findFirst(key);
344  if (dyn != UAVCAN_NULLPTR)
345  {
346  UAVCAN_TRACE("TransferBufferManager", "Buffer deleted, %s", key.toString().c_str());
347  buffers_.remove(dyn);
349  }
350 }
351 
353 {
354  return getNumBuffers() == 0;
355 }
356 
358 {
359  return buffers_.getLength();
360 }
361 
362 }
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
uavcan::StaticTransferBufferImpl::data_
uint8_t *const data_
Definition: transfer_buffer.hpp:24
uavcan::TransferBufferManagerEntry::allocator_
IPoolAllocator & allocator_
Definition: transfer_buffer.hpp:119
uavcan::TransferBufferManagerEntry::Block::instantiate
static Block * instantiate(IPoolAllocator &allocator)
Definition: uc_transfer_buffer.cpp:79
uavcan::StaticTransferBufferImpl::reset
void reset()
Definition: uc_transfer_buffer.cpp:55
uavcan::ITransferBuffer
Definition: abstract_transfer_buffer.hpp:16
uavcan::NodeID::get
uint8_t get() const
Definition: transfer.hpp:132
uavcan::TransferBufferManagerEntry::instantiate
static TransferBufferManagerEntry * instantiate(IPoolAllocator &allocator, uint16_t max_size)
Definition: uc_transfer_buffer.cpp:130
uavcan::TransferBufferManagerKey::transfer_type_
uint8_t transfer_type_
Definition: transfer_buffer.hpp:66
uavcan::TransferBufferManagerEntry::Block::destroy
static void destroy(Block *&obj, IPoolAllocator &allocator)
Definition: uc_transfer_buffer.cpp:89
uavcan::IPoolAllocator::allocate
virtual void * allocate(std::size_t size)=0
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::TransferBufferManager::create
ITransferBuffer * create(const TransferBufferManagerKey &key)
Definition: uc_transfer_buffer.cpp:312
uavcan::TransferBufferManagerEntry::destroy
static void destroy(TransferBufferManagerEntry *&obj, IPoolAllocator &allocator)
Definition: uc_transfer_buffer.cpp:141
uavcan::TransferBufferManagerEntry::Block::Size
@ Size
Definition: transfer_buffer.hpp:107
uavcan::uint16_t
std::uint16_t uint16_t
Definition: std.hpp:25
uavcan::TransferBufferManagerKey
Definition: transfer_buffer.hpp:63
uavcan::TransferBufferManager::findFirst
TransferBufferManagerEntry * findFirst(const TransferBufferManagerKey &key)
Definition: uc_transfer_buffer.cpp:275
uavcan::TransferBufferManager::remove
void remove(const TransferBufferManagerKey &key)
Definition: uc_transfer_buffer.cpp:339
uavcan::TransferBufferManagerEntry
Definition: transfer_buffer.hpp:102
uavcan::StaticTransferBufferImpl::write
virtual int write(unsigned offset, const uint8_t *data, unsigned len)
Definition: uc_transfer_buffer.cpp:34
uavcan::TransferBufferManagerEntry::Block::read
void read(uint8_t *&outptr, unsigned target_offset, unsigned &total_offset, unsigned &left_to_read)
Definition: uc_transfer_buffer.cpp:99
uavcan::IPoolAllocator::deallocate
virtual void deallocate(const void *ptr)=0
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan::snprintf
int snprintf(char *out, std::size_t maxlen, const char *format,...)
Definition: std.hpp:73
uavcan::TransferBufferManagerEntry::getKey
const TransferBufferManagerKey & getKey() const
Definition: transfer_buffer.hpp:146
uavcan::max
const UAVCAN_EXPORT T & max(const T &a, const T &b)
Definition: templates.hpp:291
uavcan::TransferBufferManagerEntry::~TransferBufferManagerEntry
virtual ~TransferBufferManagerEntry()
Definition: transfer_buffer.hpp:136
uavcan::TransferBufferManagerEntry::read
virtual int read(unsigned offset, uint8_t *data, unsigned len) const
Definition: uc_transfer_buffer.cpp:151
uavcan::TransferBufferManagerKey::isEmpty
bool isEmpty() const
Definition: transfer_buffer.hpp:87
uavcan::IPoolAllocator
Definition: dynamic_memory.hpp:21
toString
static std::string toString(long x)
Definition: multiset.cpp:16
uavcan::TransferBufferManager::~TransferBufferManager
~TransferBufferManager()
Definition: uc_transfer_buffer.cpp:290
uavcan::TransferBufferManagerEntry::TransferBufferManagerEntry
TransferBufferManagerEntry(IPoolAllocator &allocator, uint16_t max_size)
Definition: transfer_buffer.hpp:126
uavcan::LinkedListNode::setNextListNode
void setNextListNode(T *node)
Definition: linked_list.hpp:34
uavcan::TransferBufferManager::getNumBuffers
unsigned getNumBuffers() const
Definition: uc_transfer_buffer.cpp:357
int
int
Definition: libstubs.cpp:120
uavcan::TransferBufferManagerEntry::blocks_
LinkedListRoot< Block > blocks_
Definition: transfer_buffer.hpp:120
uavcan::TransferBufferManagerEntry::max_size_
const uint16_t max_size_
Definition: transfer_buffer.hpp:122
uavcan::TransferBufferManagerEntry::Block::write
void write(const uint8_t *&inptr, unsigned target_offset, unsigned &total_offset, unsigned &left_to_write)
Definition: uc_transfer_buffer.cpp:113
uavcan::TransferBufferManagerEntry::max_write_pos_
uint16_t max_write_pos_
Definition: transfer_buffer.hpp:121
uavcan::TransferBufferManagerKey::node_id_
NodeID node_id_
Definition: transfer_buffer.hpp:65
uavcan::fill
UAVCAN_EXPORT void fill(ForwardIt first, ForwardIt last, const T &value)
Definition: templates.hpp:254
uavcan::TransferBufferManager::isEmpty
bool isEmpty() const
Definition: uc_transfer_buffer.cpp:352
uavcan::TransferBufferManagerEntry::isEmpty
bool isEmpty() const
Definition: transfer_buffer.hpp:147
uavcan::LinkedListNode::getNextListNode
T * getNextListNode() const
Definition: linked_list.hpp:32
uavcan::TransferBufferManagerEntry::reset
void reset(const TransferBufferManagerKey &key=TransferBufferManagerKey())
Definition: uc_transfer_buffer.cpp:258
uavcan::StaticTransferBufferImpl::size_
const uint16_t size_
Definition: transfer_buffer.hpp:25
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::copy
UAVCAN_EXPORT OutputIt copy(InputIt first, InputIt last, OutputIt result)
Definition: templates.hpp:238
transfer_buffer.hpp
uavcan::TransferBufferManagerEntry::write
virtual int write(unsigned offset, const uint8_t *data, unsigned len)
Definition: uc_transfer_buffer.cpp:187
uavcan::TransferBufferManager::access
ITransferBuffer * access(const TransferBufferManagerKey &key)
Definition: uc_transfer_buffer.cpp:302
uavcan::TransferBufferManagerEntry::Block
Definition: transfer_buffer.hpp:105
uavcan::StaticTransferBufferImpl::max_write_pos_
uint16_t max_write_pos_
Definition: transfer_buffer.hpp:26
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::TransferBufferManagerEntry::key_
TransferBufferManagerKey key_
Definition: transfer_buffer.hpp:123
uavcan::StaticTransferBufferImpl::read
virtual int read(unsigned offset, uint8_t *data, unsigned len) const
Definition: uc_transfer_buffer.cpp:14


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:03