/**************************************************************************** * 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 #endif #include "./message_p.h" #include #include #include 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; } AQH_MESSAGE *AQH_Message_dup(const AQH_MESSAGE *origMsg) { if (origMsg) { AQH_MESSAGE *msg; msg=AQH_Message_new(); if (origMsg->msgPointer && origMsg->msgSize) { AQH_Message_SetData(msg, origMsg->msgPointer, origMsg->msgSize); msg->usedSize=origMsg->usedSize; } return msg; } else return NULL; } 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 (slenmsgPointer+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 (slenmsgPointer+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; } } } } }