Adds the sdi_toolBox library (temporary version)
This commit is contained in:
105
sdi_toolBox_1.0.x/toolBox/sdi_toolBox/generic/circularBuffer.h
Normal file
105
sdi_toolBox_1.0.x/toolBox/sdi_toolBox/generic/circularBuffer.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
{{copyright}}
|
||||
*/
|
||||
|
||||
/*
|
||||
{{version}}
|
||||
*/
|
||||
|
||||
/*
|
||||
{{license}}
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
namespace sdi_toolBox::generic
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
template<class T, size_t BUFFER_SIZE>
|
||||
class CircularBuffer final
|
||||
{
|
||||
public:
|
||||
CircularBuffer() = default; // Constructor
|
||||
~CircularBuffer() = default; // Destructor
|
||||
CircularBuffer(const CircularBuffer &other) = delete; // Copy constructor
|
||||
CircularBuffer(CircularBuffer &&other) noexcept = delete; // Move constructor
|
||||
CircularBuffer &operator=(const CircularBuffer &other) = delete; // Copy assignment
|
||||
CircularBuffer &operator=(CircularBuffer &&other) noexcept = delete; // Move assignment
|
||||
|
||||
bool push(const T &item); // Add an element to the buffer
|
||||
std::optional<T> pop(); // Retrieve an element from the buffer
|
||||
bool isEmpty() const; // Check if the buffer is empty
|
||||
bool isFull() const; // Check if the buffer is full
|
||||
size_t size() const; // Get the current number of elements
|
||||
|
||||
protected:
|
||||
std::array<T, BUFFER_SIZE> m_buffer;
|
||||
volatile size_t m_head = 0; // Index for the next write (push)
|
||||
volatile size_t m_tail = 0; // Index for the next read (pop)
|
||||
volatile size_t m_size = 0; // Current number of elements stored
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------
|
||||
/* Add an element to the buffer */
|
||||
template<class T, size_t BUFFER_SIZE>
|
||||
inline bool CircularBuffer<T, BUFFER_SIZE>::push(const T &item)
|
||||
{
|
||||
if (isFull())
|
||||
return false; // Buffer is full
|
||||
|
||||
// Write the item at the current head position
|
||||
m_buffer[m_head] = item;
|
||||
|
||||
// Move head pointer, wrapping around using modulo
|
||||
m_head = (m_head + 1) % BUFFER_SIZE;
|
||||
|
||||
// Increase the current size of the data in the buffer
|
||||
m_size = m_size + 1;
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Retrieve an element from the buffer */
|
||||
template<class T, size_t BUFFER_SIZE>
|
||||
inline std::optional<T> CircularBuffer<T, BUFFER_SIZE>::pop()
|
||||
{
|
||||
if (isEmpty())
|
||||
return {}; // Buffer is empty, cannot pop
|
||||
|
||||
// Read (copy) the item at the current tail position
|
||||
T item = m_buffer[m_tail];
|
||||
|
||||
// Move tail pointer, wrapping around using modulo
|
||||
m_tail = (m_tail + 1) % BUFFER_SIZE;
|
||||
|
||||
// Decrease the current size of the data in the buffer
|
||||
m_size = m_size - 1;
|
||||
return item;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Check if the buffer is empty */
|
||||
template<class T, size_t BUFFER_SIZE>
|
||||
inline bool CircularBuffer<T, BUFFER_SIZE>::isEmpty() const
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Check if the buffer is full */
|
||||
template<class T, size_t BUFFER_SIZE>
|
||||
inline bool CircularBuffer<T, BUFFER_SIZE>::isFull() const
|
||||
{
|
||||
return m_size == BUFFER_SIZE;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the current number of elements */
|
||||
template<class T, size_t BUFFER_SIZE>
|
||||
inline size_t CircularBuffer<T, BUFFER_SIZE>::size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
} // namespace sdi_toolBox::generic
|
||||
163
sdi_toolBox_1.0.x/toolBox/sdi_toolBox/generic/crc.h
Normal file
163
sdi_toolBox_1.0.x/toolBox/sdi_toolBox/generic/crc.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
{{copyright}}
|
||||
*/
|
||||
|
||||
/*
|
||||
{{version}}
|
||||
*/
|
||||
|
||||
/*
|
||||
{{license}}
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
|
||||
namespace sdi_ToolBox::generic
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
/**
|
||||
* @class CRC16_modbus
|
||||
* @brief CRC16 calculator for the Modbus protocol.
|
||||
*
|
||||
* Provides both static and incremental interfaces to compute the CRC16 checksum
|
||||
* as used in the Modbus protocol (polynomial 0xA001, initial value 0xFFFF).
|
||||
*
|
||||
* Usage examples:
|
||||
* @code
|
||||
* // One-shot CRC calculation
|
||||
* std::array<uint8_t, 8> data = { ... };
|
||||
* uint16_t crc = Crc16_modbus::computeCRC(data);
|
||||
*
|
||||
* // Incremental CRC calculation
|
||||
* Crc16_modbus crcHandle;
|
||||
* crcHandle.init();
|
||||
* for (uint8_t b : data) {
|
||||
* crcHandle.update(b);
|
||||
* }
|
||||
* uint16_t crc = crcHandle.finalize();
|
||||
* @endcode
|
||||
*/
|
||||
class CRC16_modbus
|
||||
{
|
||||
static constexpr uint16_t INITIAL_VALUE = 0xFFFF;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Computes the CRC16 of the given data in one call.
|
||||
* @param data The data buffer to compute the CRC for.
|
||||
* @return The computed CRC16 value.
|
||||
*/
|
||||
static uint16_t computeCRC(const std::span<const uint8_t> &data);
|
||||
|
||||
public:
|
||||
CRC16_modbus() = default; // Default constructor
|
||||
virtual ~CRC16_modbus() = default; // Default destructor
|
||||
CRC16_modbus(const CRC16_modbus &other) = default; // Copy constructor
|
||||
CRC16_modbus(CRC16_modbus &&other) noexcept = default; // Move constructor
|
||||
CRC16_modbus &operator=(const CRC16_modbus &other) = default; // Copy assignment
|
||||
CRC16_modbus &operator=(CRC16_modbus &&other) noexcept = default; // Move assignment
|
||||
|
||||
/**
|
||||
* @brief Constructs and initializes the CRC with the given data.
|
||||
* @param data The data buffer to initialize and update the CRC with.
|
||||
*/
|
||||
explicit CRC16_modbus(const std::span<const uint8_t> &data);
|
||||
|
||||
/**
|
||||
* @brief Initializes or re-initializes the CRC to the default value (0xFFFF).
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* @brief Updates the CRC with a single byte.
|
||||
* @param val The byte value to update the CRC with.
|
||||
*/
|
||||
void update(const uint8_t &val);
|
||||
|
||||
/**
|
||||
* @brief Updates the CRC with a data buffer.
|
||||
* @param data The data buffer to update the CRC with.
|
||||
*/
|
||||
void update(const std::span<const uint8_t> &data);
|
||||
|
||||
/**
|
||||
* @brief Finalizes the CRC calculation and returns the CRC value.
|
||||
* @return The finalized CRC16 value.
|
||||
*/
|
||||
uint16_t finalize() const;
|
||||
|
||||
/**
|
||||
* @brief Returns the current CRC value.
|
||||
* @return The current CRC16 value.
|
||||
*/
|
||||
[[nodiscard]] uint16_t getCRC() const;
|
||||
|
||||
protected:
|
||||
uint16_t m_crc = INITIAL_VALUE; // Current CRC value
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------
|
||||
/* Compute CRC in one go */
|
||||
inline uint16_t CRC16_modbus::computeCRC(const std::span<const uint8_t> &data)
|
||||
{
|
||||
const CRC16_modbus crc(data);
|
||||
return crc.finalize();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
inline CRC16_modbus::CRC16_modbus(const std::span<const uint8_t> &data)
|
||||
{
|
||||
init();
|
||||
update(data);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Reinit crc handle */
|
||||
inline void CRC16_modbus::init()
|
||||
{
|
||||
m_crc = INITIAL_VALUE;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Update CRC */
|
||||
inline void CRC16_modbus::update(const uint8_t &val)
|
||||
{
|
||||
constexpr uint16_t PolynomialValue = 0xA001;
|
||||
|
||||
m_crc ^= static_cast<uint16_t>(val); // XOR byte into least sig. byte of crc
|
||||
for (int i = 8; i != 0; i--) // Loop over each bit
|
||||
{
|
||||
if ((m_crc & 0x0001) != 0) // If the LSB is set
|
||||
{
|
||||
m_crc >>= 1; // Shift right and XOR PolynomialValue
|
||||
m_crc ^= PolynomialValue;
|
||||
}
|
||||
else // Else LSB is not set
|
||||
{
|
||||
m_crc >>= 1; // Just shift right
|
||||
}
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Update CRC */
|
||||
inline void CRC16_modbus::update(const std::span<const uint8_t> &data)
|
||||
{
|
||||
for (const auto &c : data)
|
||||
update(c);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Finalize and return CRC value */
|
||||
inline uint16_t CRC16_modbus::finalize() const
|
||||
{
|
||||
return getCRC();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Return CRC value */
|
||||
inline uint16_t CRC16_modbus::getCRC() const
|
||||
{
|
||||
return m_crc;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
} // namespace sdi_ToolBox::generic
|
||||
79
sdi_toolBox_1.0.x/toolBox/sdi_toolBox/generic/uuid.h
Normal file
79
sdi_toolBox_1.0.x/toolBox/sdi_toolBox/generic/uuid.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
{{copyright}}
|
||||
*/
|
||||
|
||||
/*
|
||||
{{version}}
|
||||
*/
|
||||
|
||||
/*
|
||||
{{license}}
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/uuid/uuid.hpp> // Pour boost::uuids::uuid
|
||||
#include <boost/uuid/uuid_generators.hpp> // Pour boost::uuids::random_generator
|
||||
#include <boost/uuid/uuid_io.hpp> // Pour boost::uuids::to_string
|
||||
#include <format>
|
||||
#include <string>
|
||||
|
||||
namespace sdi_toolBox::generic
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
class UuidGenerator
|
||||
{
|
||||
public:
|
||||
static std::string uuid_v4(); // Generate a random UUID v4 string
|
||||
static std::string uniqid(bool moreEntropy = false); // Generate a unique identifier string (as in PHP)
|
||||
|
||||
protected:
|
||||
UuidGenerator() = default; // Default constructor
|
||||
~UuidGenerator() = default; // Default destructor
|
||||
UuidGenerator(const UuidGenerator &) = default; // Copy constructor
|
||||
UuidGenerator(UuidGenerator &&) noexcept = default; // Move constructor
|
||||
UuidGenerator &operator=(const UuidGenerator &) = default; // Copy assignment operator
|
||||
UuidGenerator &operator=(UuidGenerator &&) noexcept = default; // Move assignment operator
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
/* Generate a random UUID v4 string */
|
||||
inline std::string UuidGenerator::uuid_v4()
|
||||
{
|
||||
boost::uuids::random_generator gen; // Create a random UUID generator
|
||||
boost::uuids::uuid u = gen(); // Generate a random UUID
|
||||
return boost::uuids::to_string(u); // Convert the UUID to a string and return it
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Generate a unique identifier string (as in PHP) */
|
||||
inline std::string UuidGenerator::uniqid(const bool moreEntropy)
|
||||
{
|
||||
const auto now = std::chrono::high_resolution_clock::now(); // Get current time point
|
||||
const auto epoch = now.time_since_epoch(); // Get duration since epoch
|
||||
const auto us_since_epoch = std::chrono::duration_cast<std::chrono::microseconds>(epoch).count();
|
||||
|
||||
// Format the time part into a hexadecimal string
|
||||
const auto time_part = us_since_epoch / 16;
|
||||
|
||||
std::string result = std::format("{0:x}", time_part);
|
||||
|
||||
// PHP's uniqid pads the result to 13 characters if needed. We replicate the core logic.
|
||||
// If the time part is shorter than 13 characters (highly unlikely today), it should be padded.
|
||||
if (result.length() < 13)
|
||||
result.insert(0, 13 - result.length(), '0');
|
||||
|
||||
// Add more entropy if requested (similar to PHP's second argument = true)
|
||||
if (moreEntropy)
|
||||
{
|
||||
// Generate 5 bytes of random data (10 characters hex)
|
||||
static std::random_device rd;
|
||||
static std::mt19937 generator(rd());
|
||||
unsigned int rand_val = generator(); // Generate a random 32-bit number and use a portion of a second random number
|
||||
|
||||
// Append the random data in hexadecimal format
|
||||
result = result + std::format(".{0:08x}", rand_val);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
} // namespace sdi_toolBox::generic
|
||||
Reference in New Issue
Block a user