2024-12-03 10:36:06 +08:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
/**
|
|
|
|
Copyright (c) 2015 - 2022 Beckhoff Automation GmbH & Co. KG
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "wrap_endian.h"
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
struct Frame {
|
|
|
|
/**
|
|
|
|
* @brief Frame
|
|
|
|
* @param length number of bytes preallocated in the internale buffer
|
|
|
|
* @param data, if not null this frame will be initialized with <lenght> number of bytes from <data>
|
|
|
|
*/
|
|
|
|
Frame(size_t length, const void* data = nullptr);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief operator []
|
|
|
|
* bytewise access to the frame bytes
|
|
|
|
* @param index should be within the frames bounds!
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
uint8_t operator[](size_t index) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief capacity
|
|
|
|
* @return number of bytes, which are accessable by rawData()
|
|
|
|
*/
|
|
|
|
size_t capacity() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief clear
|
|
|
|
* Reset internal buffer to an empty frame
|
|
|
|
* @return reference to self
|
|
|
|
*/
|
|
|
|
Frame& clear();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief limit
|
|
|
|
* If the frame is reused as a response buffer, call limit() to lock the frames state
|
|
|
|
* and limit its size to the length of the response
|
|
|
|
* @param newSize length of the response
|
|
|
|
* @return reference to self
|
|
|
|
*/
|
|
|
|
Frame& limit(size_t newSize);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief reset
|
|
|
|
* Prepare the frame to be reused as a response buffer
|
|
|
|
* @param newSize expected size of the response
|
|
|
|
* @return reference to self
|
|
|
|
*/
|
|
|
|
Frame& reset(size_t newSize = 4096);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief data
|
|
|
|
* @return a pointer to the beginning of the frame
|
|
|
|
*/
|
|
|
|
const uint8_t* data() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* remove sizeof(T) bytes from the beginning of the frame and return them
|
|
|
|
* interpreted as T. If frame is to short to fit a T, we silently return
|
|
|
|
* a default initialized T.
|
|
|
|
*/
|
|
|
|
template<typename T> T pop()
|
|
|
|
{
|
|
|
|
T value {};
|
|
|
|
if (sizeof(value) <= capacity()) {
|
|
|
|
value = *reinterpret_cast<T*>(m_Pos);
|
|
|
|
}
|
|
|
|
remove(sizeof(T));
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* remove sizeof(T) bytes from the beginning of the frame and return them
|
|
|
|
* interpreted as T in little endian byte order (result is in host order).
|
|
|
|
*/
|
|
|
|
template<typename T> T pop_letoh()
|
|
|
|
{
|
2024-12-05 11:04:47 +08:00
|
|
|
return bhf::ads::letoh(pop<T>());
|
2024-12-03 10:36:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief prepend
|
|
|
|
* prepend <data> in front of the frame
|
|
|
|
* @param data
|
|
|
|
* @param size number of bytes in <data>
|
|
|
|
* @return reference to self
|
|
|
|
*/
|
|
|
|
Frame& prepend(const void* const data, const size_t size);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* prepend a header of type <T>
|
|
|
|
*/
|
|
|
|
template<class T> Frame& prepend(const T& header)
|
|
|
|
{
|
|
|
|
return prepend(&header, sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief rawData
|
|
|
|
* Reuse the frame as response buffer, use with care!
|
|
|
|
* @return a raw pointer to the beginning of the internal allocated buffer
|
|
|
|
*/
|
|
|
|
uint8_t* rawData() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief remove
|
|
|
|
* remove <numBytest> from the beginning of the frame
|
|
|
|
* @param numBytes
|
|
|
|
* @return reference to self
|
|
|
|
*/
|
|
|
|
Frame& remove(size_t numBytes);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* remove header of type <T> from the beginning of the frame
|
|
|
|
*/
|
|
|
|
template<class T> T remove()
|
|
|
|
{
|
|
|
|
const auto p = m_Pos;
|
|
|
|
remove(sizeof(T));
|
|
|
|
return T(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief size
|
|
|
|
* @return length of the frame in bytes
|
|
|
|
*/
|
|
|
|
size_t size() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::unique_ptr<uint8_t[]> m_Data;
|
|
|
|
uint8_t* m_Pos;
|
|
|
|
size_t m_Size;
|
|
|
|
size_t m_OriginalSize;
|
|
|
|
};
|