200 lines
4.8 KiB
C++
200 lines
4.8 KiB
C++
#include <byte_buffer.h>
|
|
|
|
#include <cstdlib>
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
#include <osapi.h>
|
|
#include <libb64/cdecode.h>
|
|
#include <libb64/cencode.h>
|
|
|
|
namespace utils
|
|
{
|
|
byte_buffer::byte_buffer(uint_fast16_t length)
|
|
: _length(length)
|
|
{
|
|
// +1 to allow this to be safely printed as a char
|
|
_buffer = reinterpret_cast<unsigned char *>(std::calloc(length + 1, sizeof(unsigned char)));
|
|
}
|
|
|
|
byte_buffer::~byte_buffer()
|
|
{
|
|
clear_buffer();
|
|
std::free(_buffer);
|
|
}
|
|
|
|
const bool byte_buffer::is_valid()
|
|
{
|
|
return _buffer != nullptr;
|
|
}
|
|
|
|
unsigned char *byte_buffer::get_ptr()
|
|
{
|
|
if (is_valid())
|
|
{
|
|
return _buffer;
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// Get the length of the buffer.
|
|
//
|
|
// Returns: The length of the buffer, or 0 if the buffer is invalid.
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
const uint_fast16_t byte_buffer::get_length()
|
|
{
|
|
if (is_valid())
|
|
{
|
|
return _length;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// Get a pointer to a location in the buffer, length is updated to show the length
|
|
// available in that buffer
|
|
//
|
|
// index: The location to get a pointer to.
|
|
// length: The length of the data you expect to access from this pointer.
|
|
//
|
|
// Returns: A ptr to the buffer, or nullptr if reading that much data would cause
|
|
// an overflow
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
unsigned char *byte_buffer::get_ptr(const uint_fast16_t index, uint_fast16_t &length)
|
|
{
|
|
unsigned char *ret = nullptr;
|
|
|
|
if (is_valid() && _length > index)
|
|
{
|
|
length = _length - index;
|
|
ret = &_buffer[index];
|
|
}
|
|
else
|
|
{
|
|
length = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Copy data into this buffer. The index value is updated to the index of the next point in the buffer
|
|
const bool byte_buffer::copy_from(const void *const sourceBuffer, uint_fast16_t &index, const uint_fast16_t &length)
|
|
{
|
|
auto ret = false;
|
|
if (is_valid() &&
|
|
sourceBuffer != nullptr &&
|
|
(index + length) <= _length)
|
|
{
|
|
std::memcpy(_buffer + index, sourceBuffer, length);
|
|
index += length;
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Copy data out of this buffer. The index value is updated to the index of the next point in the buffer
|
|
const bool byte_buffer::copy_to(void *destinationBuffer, uint_fast16_t &index, const uint_fast16_t &length)
|
|
{
|
|
auto ret = false;
|
|
if (is_valid() &&
|
|
destinationBuffer != nullptr &&
|
|
(index + length) < _length)
|
|
{
|
|
std::memcpy(destinationBuffer, _buffer + index, length);
|
|
index += length;
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
const bool byte_buffer::clone(byte_buffer &bufferToClone)
|
|
{
|
|
auto ret = false;
|
|
if (is_valid() &&
|
|
bufferToClone.is_valid() &&
|
|
bufferToClone.get_length() <= _length)
|
|
{
|
|
std::memcpy(bufferToClone.get_ptr(), 0, bufferToClone.get_length());
|
|
ret = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
const void byte_buffer::clear_buffer()
|
|
{
|
|
if (is_valid())
|
|
{
|
|
std::fill(_buffer, _buffer + _length, 0);
|
|
}
|
|
}
|
|
|
|
const void byte_buffer::fill_random()
|
|
{
|
|
if (is_valid())
|
|
{
|
|
os_get_random(_buffer, _length);
|
|
}
|
|
}
|
|
|
|
// Return the size of the data stored
|
|
const uint_fast16_t byte_buffer::load_base64(std::string base64Data)
|
|
{
|
|
auto read = 0u;
|
|
|
|
if (is_valid() && _length >= base64_decode_expected_len(base64Data.length()))
|
|
{
|
|
base64_decodestate state;
|
|
base64_init_decodestate(&state);
|
|
read = base64_decode_block(base64Data.c_str(), base64Data.length(), reinterpret_cast<char *>(_buffer), &state);
|
|
}
|
|
|
|
return read;
|
|
}
|
|
|
|
//// Get a base64 encoded string of this buffer.
|
|
const std::string byte_buffer::get_base64()
|
|
{
|
|
if (!is_valid())
|
|
{
|
|
return "";
|
|
}
|
|
|
|
auto b64String = std::string("");
|
|
auto size = base64_encode_expected_len_nonewlines(_length) + 1;
|
|
auto buffer = reinterpret_cast<char *>(std::calloc(size, 1));
|
|
if (buffer != nullptr)
|
|
{
|
|
|
|
base64_encodestate state;
|
|
base64_init_encodestate_nonewlines(&state);
|
|
|
|
auto encoded = base64_encode_block(reinterpret_cast<const char *>(_buffer), _length, buffer, &state);
|
|
encoded = base64_encode_blockend(buffer + encoded, &state);
|
|
|
|
b64String = std::string(buffer);
|
|
std::free(buffer);
|
|
}
|
|
|
|
return b64String;
|
|
}
|
|
|
|
const std::string byte_buffer::to_string()
|
|
{
|
|
if (!is_valid())
|
|
{
|
|
return "";
|
|
}
|
|
|
|
// Make sure that extra byte really is null!
|
|
_buffer[_length] = '\0';
|
|
return std::string(reinterpret_cast<char *>(_buffer));
|
|
}
|
|
} // namespace Control_System
|