Adds the sdi_toolBox library (temporary version)

This commit is contained in:
Sylvain Schneider
2026-03-12 16:31:18 +01:00
parent 0601326e2b
commit b5d0fef4d9
23 changed files with 28422 additions and 0 deletions

View 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

View 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

View 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