diff --git a/usb/device/utilities/ByteBuffer.cpp b/usb/device/utilities/ByteBuffer.cpp new file mode 100644 index 0000000000..e45b8b4a82 --- /dev/null +++ b/usb/device/utilities/ByteBuffer.cpp @@ -0,0 +1,151 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ByteBuffer.h" +#include "mbed_assert.h" +#include + +ByteBuffer::ByteBuffer(uint32_t size): _head(0), _tail(0), _size(0), _buf(NULL) +{ + resize(_size); +} + +ByteBuffer::~ByteBuffer() +{ + delete[] _buf; + _buf = 0; +} + +void ByteBuffer::resize(uint32_t size) +{ + delete[] _buf; + _head = 0; + _tail = 0; + _size = size + 1; + _buf = new uint8_t[_size](); +} + +void ByteBuffer::push(uint8_t data) +{ + _buf[_tail] = data; + _tail++; + if (_tail >= _size) { + _tail -= _size; + } + // Overflow not allowed + MBED_ASSERT(_head != _tail); +} + +void ByteBuffer::write(uint8_t *data, uint32_t size) +{ + MBED_ASSERT(size <= free()); + + if (size == 0) { + return; + } + + uint32_t new_tail = _tail + size; + if (new_tail >= _size) { + new_tail -= _size; + } + + // Perform first memcpy + uint32_t until_end = _size - _tail; + uint32_t copy_size = until_end < size ? until_end : size; + memcpy(_buf + _tail, data, copy_size); + data += copy_size; + size -= copy_size; + + // Perform second memcpy + if (size > 0) { + memcpy(_buf, data, size); + } + + // Update tail + _tail = new_tail; +} + +uint8_t ByteBuffer::pop() +{ + // Underflow not allowed + MBED_ASSERT(_head != _tail); + uint8_t val = _buf[_head]; + _head++; + if (_head >= _size) { + _head -= _size; + } + return val; +} + +void ByteBuffer::read(uint8_t *data, uint32_t size) +{ + MBED_ASSERT(size <= ByteBuffer::size()); + + if (size == 0) { + return; + } + + uint32_t new_head = _head + size; + if (new_head >= _size) { + new_head -= _size; + } + + // Perform first memcpy + uint32_t until_end = _size - _head; + uint32_t copy_size = until_end < size ? until_end : size; + memcpy(data, _buf + _head, copy_size); + data += copy_size; + size -= copy_size; + + // Perform second memcpy + if (size > 0) { + memcpy(data, _buf, size); + } + + // Update head + _head = new_head; +} + +uint32_t ByteBuffer::size() +{ + uint32_t size; + if (_tail < _head) { + size = _size + _tail - _head; + } else { + size = _tail - _head; + } + return size; +} + +uint32_t ByteBuffer::free() +{ + return _size - size() - 1; +} + +bool ByteBuffer::full() +{ + uint32_t next = _tail + 1; + if (next >= _size) { + next -= _size; + } + return next == _head; +} + +bool ByteBuffer::empty() +{ + return _head == _tail; +} + diff --git a/usb/device/utilities/ByteBuffer.h b/usb/device/utilities/ByteBuffer.h new file mode 100644 index 0000000000..8e9d40f40b --- /dev/null +++ b/usb/device/utilities/ByteBuffer.h @@ -0,0 +1,119 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BYTE_BUFFER_H +#define BYTE_BUFFER_H + +#include + +class ByteBuffer { +public: + + /** + * Create a byte buffer of the given size + * + * @param size Number of bytes this buffer can hold + */ + ByteBuffer(uint32_t size=0); + + /** + * Delete this byte buffer + */ + ~ByteBuffer(); + + /** + * Set the size of the buffer + * + * Buffer contents are reset. + * + * @param size New buffer size + */ + void resize(uint32_t size); + + /** + * Add a single byte to this buffer + * + * There must be enough space in the buffer or the behavior is undefined. + * + * @param data byte to add + */ + void push(uint8_t data); + + /** + * Write a block of data to this ByteBuffer + * + * There must be enough space in the ByteBuffer or the behavior is undefined. + * + * @param data Block of data to write + * @param size Size of data to write + */ + void write(uint8_t *data, uint32_t size); + + /** + * Remove a byte from this buffer + * + * @return data byte + */ + uint8_t pop(); + + /** + * Read a block of data from this ByteBuffer into a buffer pointed by 'data' + * + * There must be enough data in the ByteBuffer or the behavior is undefined. + * + * @param data Block of data to read + * @param size Size of data to read + */ + void read(uint8_t *data, uint32_t size); + + /** + * Return the number bytes in this byte buffer + * + * @return Number of used bytes + */ + uint32_t size(); + + /** + * Return the number of additional bytes this buffer can hold + * + * @return Number of free bytes + */ + uint32_t free(); + + /** + * Check if this byte buffer is full + * + * @return true if full, false otherwise + */ + bool full(); + + /** + * Check if this byte buffer is empty + * + * @return true if empty, false otherwise + */ + bool empty(); + +private: + + uint32_t _head; + uint32_t _tail; + uint32_t _size; + uint8_t *_buf; +}; + + +#endif