map/das-dn/third_party/AdsLib/Frame.h
2024-12-05 11:04:47 +08:00

141 lines
3.4 KiB
C++

// 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()
{
return bhf::ads::letoh(pop<T>());
}
/**
* @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;
};