258 lines
7.0 KiB
C
258 lines
7.0 KiB
C
|
#ifndef MICROBIT_MANAGED_BUFFER_H
|
||
|
#define MICROBIT_MANAGED_BUFFER_H
|
||
|
|
||
|
#include "mbed.h"
|
||
|
#include "RefCounted.h"
|
||
|
|
||
|
struct BufferData : RefCounted
|
||
|
{
|
||
|
uint16_t length; // The length of the payload in bytes
|
||
|
uint8_t payload[0]; // ManagedBuffer data
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Class definition for a ManagedBuffer.
|
||
|
* A ManagedBuffer holds a series of bytes, used with MicroBitRadio channels and in other places.
|
||
|
* n.b. This is a mutable, managed type.
|
||
|
*/
|
||
|
class ManagedBuffer
|
||
|
{
|
||
|
BufferData *ptr; // Pointer to payload data
|
||
|
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
* Default Constructor.
|
||
|
* Creates an empty ManagedBuffer. The 'ptr' field in all empty buffers is shared.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* ManagedBuffer p();
|
||
|
* @endcode
|
||
|
*/
|
||
|
ManagedBuffer();
|
||
|
|
||
|
/**
|
||
|
* Constructor.
|
||
|
* Creates a new ManagedBuffer of the given size.
|
||
|
*
|
||
|
* @param length The length of the buffer to create.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* ManagedBuffer p(16); // Creates a ManagedBuffer 16 bytes long.
|
||
|
* @endcode
|
||
|
*/
|
||
|
ManagedBuffer(int length);
|
||
|
|
||
|
/**
|
||
|
* Constructor.
|
||
|
* Creates an empty ManagedBuffer of the given size,
|
||
|
* and fills it with the data provided.
|
||
|
*
|
||
|
* @param data The data with which to fill the buffer.
|
||
|
* @param length The length of the buffer to create.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* uint8_t buf[] = {13,5,2};
|
||
|
* ManagedBuffer p(buf, 3); // Creates a ManagedBuffer 3 bytes long.
|
||
|
* @endcode
|
||
|
*/
|
||
|
ManagedBuffer(uint8_t *data, int length);
|
||
|
|
||
|
/**
|
||
|
* Copy Constructor.
|
||
|
* Add ourselves as a reference to an existing ManagedBuffer.
|
||
|
*
|
||
|
* @param buffer The ManagedBuffer to reference.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* ManagedBuffer p();
|
||
|
* ManagedBuffer p2(i); // Refers to the same buffer as p.
|
||
|
* @endcode
|
||
|
*/
|
||
|
ManagedBuffer(const ManagedBuffer &buffer);
|
||
|
|
||
|
/**
|
||
|
* Constructor.
|
||
|
* Create a buffer from a raw BufferData pointer. It will ptr->incr(). This is to be used by specialized runtimes.
|
||
|
*
|
||
|
* @param p The pointer to use.
|
||
|
*/
|
||
|
ManagedBuffer(BufferData *p);
|
||
|
|
||
|
/**
|
||
|
* Internal constructor helper.
|
||
|
* Configures this ManagedBuffer to refer to the static empty buffer.
|
||
|
*/
|
||
|
void initEmpty();
|
||
|
|
||
|
/**
|
||
|
* Internal constructor-initialiser.
|
||
|
*
|
||
|
* @param data The data with which to fill the buffer.
|
||
|
* @param length The length of the buffer to create.
|
||
|
*
|
||
|
*/
|
||
|
void init(uint8_t *data, int length);
|
||
|
|
||
|
/**
|
||
|
* Destructor.
|
||
|
* Removes buffer resources held by the instance.
|
||
|
*/
|
||
|
~ManagedBuffer();
|
||
|
|
||
|
/**
|
||
|
* Provide an array containing the buffer data.
|
||
|
* @return The contents of this buffer, as an array of bytes.
|
||
|
*/
|
||
|
uint8_t *getBytes()
|
||
|
{
|
||
|
return ptr->payload;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get current ptr, do not decr() it, and set the current instance to an empty buffer.
|
||
|
* This is to be used by specialized runtimes which pass BufferData around.
|
||
|
*/
|
||
|
BufferData *leakData();
|
||
|
|
||
|
/**
|
||
|
* Copy assign operation.
|
||
|
*
|
||
|
* Called when one ManagedBuffer is assigned the value of another using the '=' operator.
|
||
|
* Decrements our reference count and free up the buffer as necessary.
|
||
|
* Then, update our buffer to refer to that of the supplied ManagedBuffer,
|
||
|
* and increase its reference count.
|
||
|
*
|
||
|
* @param p The ManagedBuffer to reference.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* uint8_t buf = {13,5,2};
|
||
|
* ManagedBuffer p1(16);
|
||
|
* ManagedBuffer p2(buf, 3);
|
||
|
*
|
||
|
* p1 = p2;
|
||
|
* @endcode
|
||
|
*/
|
||
|
ManagedBuffer& operator = (const ManagedBuffer& p);
|
||
|
|
||
|
/**
|
||
|
* Array access operation (read).
|
||
|
*
|
||
|
* Called when a ManagedBuffer is dereferenced with a [] operation.
|
||
|
* Transparently map this through to the underlying payload for elegance of programming.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* ManagedBuffer p1(16);
|
||
|
* uint8_t data = p1[0];
|
||
|
* @endcode
|
||
|
*/
|
||
|
uint8_t operator [] (int i) const
|
||
|
{
|
||
|
return ptr->payload[i];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Array access operation (modify).
|
||
|
*
|
||
|
* Called when a ManagedBuffer is dereferenced with a [] operation.
|
||
|
* Transparently map this through to the underlying payload for elegance of programming.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* ManagedBuffer p1(16);
|
||
|
* p1[0] = 42;
|
||
|
* @endcode
|
||
|
*/
|
||
|
uint8_t& operator [] (int i)
|
||
|
{
|
||
|
return ptr->payload[i];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Equality operation.
|
||
|
*
|
||
|
* Called when one ManagedBuffer is tested to be equal to another using the '==' operator.
|
||
|
*
|
||
|
* @param p The ManagedBuffer to test ourselves against.
|
||
|
* @return true if this ManagedBuffer is identical to the one supplied, false otherwise.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
*
|
||
|
* uint8_t buf = {13,5,2};
|
||
|
* ManagedBuffer p1(16);
|
||
|
* ManagedBuffer p2(buf, 3);
|
||
|
*
|
||
|
* if(p1 == p2) // will be true
|
||
|
* uBit.display.scroll("same!");
|
||
|
* @endcode
|
||
|
*/
|
||
|
bool operator== (const ManagedBuffer& p);
|
||
|
|
||
|
/**
|
||
|
* Sets the byte at the given index to value provided.
|
||
|
* @param position The index of the byte to change.
|
||
|
* @param value The new value of the byte (0-255).
|
||
|
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* ManagedBuffer p1(16);
|
||
|
* p1.setByte(0,255); // Sets the first byte in the buffer to the value 255.
|
||
|
* @endcode
|
||
|
*/
|
||
|
int setByte(int position, uint8_t value);
|
||
|
|
||
|
/**
|
||
|
* Determines the value of the given byte in the buffer.
|
||
|
*
|
||
|
* @param position The index of the byte to read.
|
||
|
* @return The value of the byte at the given position, or MICROBIT_INVALID_PARAMETER.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* ManagedBuffer p1(16);
|
||
|
* p1.setByte(0,255); // Sets the first byte in the buffer to the value 255.
|
||
|
* p1.getByte(0); // Returns 255.
|
||
|
* @endcode
|
||
|
*/
|
||
|
int getByte(int position);
|
||
|
|
||
|
/**
|
||
|
* Gets number of bytes in this buffer
|
||
|
* @return The size of the buffer in bytes.
|
||
|
*
|
||
|
* Example:
|
||
|
* @code
|
||
|
* ManagedBuffer p1(16);
|
||
|
* p1.length(); // Returns 16.
|
||
|
* @endcode
|
||
|
*/
|
||
|
int length() const { return ptr->length; }
|
||
|
|
||
|
int fill(uint8_t value, int offset = 0, int length = -1);
|
||
|
|
||
|
ManagedBuffer slice(int offset = 0, int length = -1) const;
|
||
|
|
||
|
void shift(int offset, int start = 0, int length = -1);
|
||
|
|
||
|
void rotate(int offset, int start = 0, int length = -1);
|
||
|
|
||
|
int readBytes(uint8_t *dst, int offset, int length, bool swapBytes = false) const;
|
||
|
|
||
|
int writeBytes(int dstOffset, uint8_t *src, int length, bool swapBytes = false);
|
||
|
|
||
|
int writeBuffer(int dstOffset, const ManagedBuffer &src, int srcOffset = 0, int length = -1);
|
||
|
|
||
|
bool isReadOnly() const { return ptr->isReadOnly(); }
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|