#include #include #include #include #include #include #include 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(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(_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(std::calloc(size, 1)); if (buffer != nullptr) { base64_encodestate state; base64_init_encodestate_nonewlines(&state); auto encoded = base64_encode_block(reinterpret_cast(_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(_buffer)); } } // namespace Control_System