Files
2022-10-26 12:25:11 +08:00

92 lines
3.0 KiB
C++

#pragma once
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
//
#ifndef __SSQ_MSG_HDR__
#define __SSQ_MSG_HDR__
// <Prototype of WAR_MSG_HDR>
// 전체 메시지의 길이가 담겨진다. (variable stream)
struct WAR_MSG_HDR
{
typedef ulong MSG_SIZE_T; // expanded by _NA001605_EP2_CHANGE_SKILL_BROADCASTER_
MSG_SIZE_T size;
};
// <Raw Header of Each Message>
// - 각 메시지의 타입들이 기재된다.
// - 1Byte, 하지만 raw stream인 WAR_TAG_V의 이것을 직접 사용하는 경우는 없어야 한다.
// (이것 common routine에서의 offset연산 편의성이 목적이다.)
// 모든 메시지들은 실질적으로 WAR_TAG1_<id, type>을 상속해서 구현되게 되어 있다.
// <목적>
// - Server/Client 각각 pointer연산을 수행하면서 버그를 유발할 수 있다.
// 하나의 로직으로 serializing input/output이 가능해지도록 하는 것이 목표다.
typedef struct WAR_TAG_V
{
BYTE _TAG;
} *WAR_TAG_P;
#endif
const WORD MAX_WAR_MSG_SEQUENCIAL_STREAM_SIZE = 8000;
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
//
#define WAR_MSG_DECL( protocol ) \
struct MSGSUB_##protocol : WAR_TAG1_< protocol, MSGSUB_##protocol >
//────────────────────────────────────────────────────────────────
// <Sample>
// case SSQ_PROTOCOL_TRAP_EARTHQUAKE_EXECUTE:
// {
// RECV_PATTERNCODE_FOR_SSQ( SSQ_PROTOCOL_TRAP_EARTHQUAKE_INDICATION );
// // enable keyword 'rMsg'
// rMsg.Count ~~
#define RECV_PATTERNCODE_FOR_WAR( subprotocol ) \
const MSGSUB_##subprotocol& rMsg = static_cast<MSGSUB_##subprotocol&>(*pIt); \
size = rMsg.GetSize()
//==================================================================================================
//
#pragma pack(push, 1)
//--------------------------------------------------------------------------------------------------
// <Base Header of Each Message>
template<uint8_t _PROTOCOL, typename _MSGTYPE >
struct WAR_TAG1_ : public WAR_TAG_V
{
static const uint8_t value = _PROTOCOL;
typedef _MSGTYPE msg_type;
typedef WAR_TAG1_<value, msg_type> this_type;
// 이것은 기본 연산자... 해당 타입을 상속한 별도의 타입은 가변 길이를 가진다면
// GetSize를 별도로 구현해야 한다. 그외의 고정형은 이것으로 모두 해결될 것이다.
// default, can overriding
uint16_t GetSize() const {
return static_cast<uint16_t>(sizeof(*static_cast<const msg_type*>(this)));
}
bool SerializeTo(WAR_MSG_HDR* const IN header) const
{
uint16_t size = static_cast<const msg_type*>(this)->GetSize();
WAR_MSG_HDR::MSG_SIZE_T offset = size + header->size;
if (MAX_WAR_MSG_SEQUENCIAL_STREAM_SIZE < offset) {
return false;
}
msg_type* const dest = reinterpret_cast<msg_type*>(\
reinterpret_cast<uint8_t*>(header + 1) + header->size);
*dest = *static_cast<const msg_type*>(this);
//
dest->_TAG = msg_type::value;
header->size = offset;
return true;
}
};
#pragma pack(pop)