Files
aqhomecontrol/aqhome/ipc2/message.c
2025-02-26 20:59:20 +01:00

315 lines
6.5 KiB
C

/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./message_p.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/endianfns.h>
GWEN_LIST_FUNCTIONS(AQH_MESSAGE, AQH_Message)
GWEN_INHERIT_FUNCTIONS(AQH_MESSAGE)
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
static void _ensureSize(AQH_MESSAGE *msg, uint32_t neededSize);
/* ------------------------------------------------------------------------------------------------
* implementations
* ------------------------------------------------------------------------------------------------
*/
AQH_MESSAGE *AQH_Message_new(void)
{
AQH_MESSAGE *msg;
GWEN_NEW_OBJECT(AQH_MESSAGE, msg);
GWEN_INHERIT_INIT(AQH_MESSAGE, msg);
GWEN_LIST_INIT(AQH_MESSAGE, msg);
msg->refCount=1;
return msg;
}
void AQH_Message_IncRef(AQH_MESSAGE *msg)
{
if (msg && msg->refCount)
msg->refCount++;
}
void AQH_Message_free(AQH_MESSAGE *msg)
{
if (msg && msg->refCount>0) {
if (msg->refCount==1) {
msg->refCount=0;
GWEN_LIST_FINI(AQH_MESSAGE, msg);
GWEN_INHERIT_FINI(AQH_MESSAGE, msg);
free(msg->msgPointer);
GWEN_FREE_OBJECT(msg);
}
else
msg->refCount--;
}
}
AQH_OBJECT *AQH_Message_GetObject(const AQH_MESSAGE *msg)
{
return (msg && msg->refCount)?msg->object:NULL;
}
void AQH_Message_SetObject(AQH_MESSAGE *msg, AQH_OBJECT *o)
{
if (msg && msg->refCount)
msg->object=o;
}
uint8_t *AQH_Message_GetMsgPointer(const AQH_MESSAGE *msg)
{
return (msg && msg->refCount)?msg->msgPointer:NULL;
}
uint32_t AQH_Message_GetMsgSize(const AQH_MESSAGE *msg)
{
return (msg && msg->refCount)?msg->msgSize:0;
}
void AQH_Message_SetData(AQH_MESSAGE *msg, const uint8_t *msgPtr, uint32_t msgSize)
{
if (msg && msg->refCount) {
free(msg->msgPointer);
msg->msgPointer=NULL;
msg->msgSize=0;
if (msgSize) {
msg->msgPointer=(uint8_t*) malloc(msgSize);
if (msg->msgPointer) {
if (msgPtr)
memmove(msg->msgPointer, msgPtr, msgSize);
else
memset(msg->msgPointer, 0, msgSize);
msg->msgSize=msgSize;
}
}
}
}
uint32_t AQH_Message_GetUsedSize(const AQH_MESSAGE *msg)
{
return msg?msg->usedSize:0;
}
void AQH_Message_SetUsedSize(AQH_MESSAGE *msg, uint32_t i)
{
if (msg) {
_ensureSize(msg, i);
msg->usedSize=i;
}
}
void AQH_Message_IncUsedSize(AQH_MESSAGE *msg, uint32_t i)
{
if (msg) {
_ensureSize(msg, msg->usedSize+i);
msg->usedSize+=i;
}
}
void AQH_Message_WriteUint8At(AQH_MESSAGE *msg, uint32_t pos, uint8_t d)
{
if (msg) {
_ensureSize(msg, pos+1);
msg->msgPointer[pos]=d;
}
}
uint8_t AQH_Message_ReadUint8At(const AQH_MESSAGE *msg, uint32_t pos, uint8_t defaultValue)
{
if (msg && msg->msgPointer && msg->msgSize>=pos+1)
return msg->msgPointer[pos];
return defaultValue;
}
void AQH_Message_WriteUint16At(AQH_MESSAGE *msg, uint32_t pos, uint16_t d)
{
if (msg) {
_ensureSize(msg, pos+2);
*( (uint16_t*) (msg->msgPointer+pos) )=GWEN_ENDIAN_HTOLE16(d);
}
}
uint16_t AQH_Message_ReadUint16At(const AQH_MESSAGE *msg, uint32_t pos, uint16_t defaultValue)
{
if (msg && msg->msgPointer && msg->msgSize>=pos+2)
return GWEN_ENDIAN_LE16TOH(*( (uint16_t*) (msg->msgPointer+pos) ));
return defaultValue;
}
void AQH_Message_WriteUint32At(AQH_MESSAGE *msg, uint32_t pos, uint32_t d)
{
if (msg) {
_ensureSize(msg, pos+4);
*( (uint32_t*) (msg->msgPointer+pos) )=GWEN_ENDIAN_HTOLE32(d);
}
}
uint32_t AQH_Message_ReadUint32At(const AQH_MESSAGE *msg, uint32_t pos, uint32_t defaultValue)
{
if (msg && msg->msgPointer && msg->msgSize>=pos+4)
return GWEN_ENDIAN_LE32TOH(*( (uint32_t*) (msg->msgPointer+pos) ));
return defaultValue;
}
void AQH_Message_WriteUint64At(AQH_MESSAGE *msg, uint32_t pos, uint64_t d)
{
if (msg) {
_ensureSize(msg, pos+8);
*( (uint64_t*) (msg->msgPointer+pos) )=GWEN_ENDIAN_HTOLE64(d);
}
}
uint64_t AQH_Message_ReadUint64At(const AQH_MESSAGE *msg, uint32_t pos, uint64_t defaultValue)
{
if (msg && msg->msgPointer && msg->msgSize>=pos+8)
return GWEN_ENDIAN_LE64TOH(*( (uint64_t*) (msg->msgPointer+pos) ));
return defaultValue;
}
void AQH_Message_WriteBytesAt(AQH_MESSAGE *msg, uint32_t pos, const uint8_t *bufferPtr, uint32_t bufferLen)
{
if (msg && bufferPtr && bufferLen) {
_ensureSize(msg, pos+bufferLen);
memmove(msg->msgPointer+pos, bufferPtr, bufferLen);
}
}
int AQH_Message_WriteStringAt(AQH_MESSAGE *msg, uint32_t pos, uint32_t maxSize, int filler, const char *s)
{
if (msg && maxSize) {
uint32_t slen=0;
if (s) {
slen=strlen(s);
if (slen>maxSize) {
DBG_ERROR(AQH_LOGDOMAIN, "String too long (%d > %d)", slen, maxSize);
return GWEN_ERROR_INVALID;
}
}
_ensureSize(msg, pos+maxSize);
if (s)
memmove(msg->msgPointer+pos, s, slen);
if (slen<maxSize)
memset(msg->msgPointer+pos+slen, filler, maxSize-slen);
}
return 0;
}
int AQH_Message_WriteStringWithTrailingNullAt(AQH_MESSAGE *msg, uint32_t pos, uint32_t maxSize, int filler, const char *s)
{
if (msg && maxSize) {
uint32_t slen=1;
if (s) {
slen=strlen(s)+1;
if (slen>maxSize) {
DBG_ERROR(AQH_LOGDOMAIN, "String too long (%d > %d)", slen, maxSize);
return GWEN_ERROR_INVALID;
}
}
_ensureSize(msg, pos+maxSize);
if (s)
memmove(msg->msgPointer+pos, s, slen);
if (slen<maxSize)
memset(msg->msgPointer+pos+slen, filler, maxSize-slen);
}
return 0;
}
void _ensureSize(AQH_MESSAGE *msg, uint32_t neededSize)
{
if (msg && neededSize) {
if (msg->msgPointer==0 || msg->msgSize==0) {
msg->msgPointer=(uint8_t*) malloc(neededSize);
assert(msg->msgPointer);
}
else {
if (neededSize>msg->msgSize) {
uint8_t *ptr;
ptr=realloc(msg->msgPointer, neededSize);
assert(ptr);
if (ptr) {
msg->msgPointer=ptr;
msg->msgSize=neededSize;
}
}
}
}
}