Files
SingularityViewer/indra/llmessage/llsdmessagebuilder.cpp

418 lines
9.3 KiB
C++

/**
* @file llsdmessagebuilder.cpp
* @brief LLSDMessageBuilder class implementation.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llsdmessagebuilder.h"
#include "llmessagetemplate.h"
#include "llmath.h"
#include "llquaternion.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
#include "llsdserialize.h"
#include "u64.h"
#include "v3dmath.h"
#include "v3math.h"
#include "v4math.h"
LLSDMessageBuilder::LLSDMessageBuilder() :
mCurrentMessage(LLSD::emptyMap()),
mCurrentBlock(NULL),
mCurrentMessageName(""),
mCurrentBlockName(""),
mbSBuilt(FALSE),
mbSClear(TRUE)
{
}
//virtual
LLSDMessageBuilder::~LLSDMessageBuilder()
{
}
// virtual
void LLSDMessageBuilder::newMessage(const char* name)
{
mbSBuilt = FALSE;
mbSClear = FALSE;
mCurrentMessage = LLSD::emptyMap();
mCurrentMessageName = (char*)name;
}
// virtual
void LLSDMessageBuilder::clearMessage()
{
mbSBuilt = FALSE;
mbSClear = TRUE;
mCurrentMessage = LLSD::emptyMap();
mCurrentMessageName = "";
}
// virtual
void LLSDMessageBuilder::nextBlock(const char* blockname)
{
LLSD& block = mCurrentMessage[blockname];
if(block.isUndefined())
{
block[0] = LLSD::emptyMap();
mCurrentBlock = &(block[0]);
}
else if(block.isArray())
{
block[block.size()] = LLSD::emptyMap();
mCurrentBlock = &(block[block.size() - 1]);
}
else
{
LL_ERRS() << "existing block not array" << LL_ENDL;
}
}
void LLSDMessageBuilder::addBinaryData(
const char* varname,
const void* data,
S32 size)
{
std::vector<U8> v;
v.resize(size);
memcpy(&(v[0]), reinterpret_cast<const U8*>(data), size);
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::addS8(const char* varname, S8 v)
{
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::addU8(const char* varname, U8 v)
{
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::addS16(const char* varname, S16 v)
{
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::addU16(const char* varname, U16 v)
{
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::addF32(const char* varname, F32 v)
{
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::addS32(const char* varname, S32 v)
{
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::addU32(const char* varname, U32 v)
{
(*mCurrentBlock)[varname] = ll_sd_from_U32(v);
}
void LLSDMessageBuilder::addU64(const char* varname, U64 v)
{
(*mCurrentBlock)[varname] = ll_sd_from_U64(v);
}
void LLSDMessageBuilder::addF64(const char* varname, F64 v)
{
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::addIPAddr(const char* varname, U32 v)
{
(*mCurrentBlock)[varname] = ll_sd_from_ipaddr(v);
}
void LLSDMessageBuilder::addIPPort(const char* varname, U16 v)
{
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::addBOOL(const char* varname, BOOL v)
{
(*mCurrentBlock)[varname] = (v == TRUE);
}
void LLSDMessageBuilder::addString(const char* varname, const char* v)
{
if (v)
(*mCurrentBlock)[varname] = v; /* Flawfinder: ignore */
else
(*mCurrentBlock)[varname] = "";
}
void LLSDMessageBuilder::addString(const char* varname, const std::string& v)
{
if (v.size())
(*mCurrentBlock)[varname] = v;
else
(*mCurrentBlock)[varname] = "";
}
void LLSDMessageBuilder::addVector3(const char* varname, const LLVector3& v)
{
(*mCurrentBlock)[varname] = ll_sd_from_vector3(v);
}
void LLSDMessageBuilder::addVector4(const char* varname, const LLVector4& v)
{
(*mCurrentBlock)[varname] = ll_sd_from_vector4(v);
}
void LLSDMessageBuilder::addVector3d(const char* varname, const LLVector3d& v)
{
(*mCurrentBlock)[varname] = ll_sd_from_vector3d(v);
}
void LLSDMessageBuilder::addQuat(const char* varname, const LLQuaternion& v)
{
(*mCurrentBlock)[varname] = ll_sd_from_quaternion(v);
}
void LLSDMessageBuilder::addUUID(const char* varname, const LLUUID& v)
{
(*mCurrentBlock)[varname] = v;
}
void LLSDMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
{
}
BOOL LLSDMessageBuilder::isMessageFull(const char* blockname) const
{
return FALSE;
}
U32 LLSDMessageBuilder::buildMessage(U8*, U32, U8)
{
return 0;
}
void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data)
{
// copy the blocks
// counting variables used to encode multiple block info
S32 block_count = 0;
char* block_name = NULL;
// loop through msg blocks to loop through variables, totalling up size
// data and filling the new (send) message
LLMsgData::msg_blk_data_map_t::const_iterator iter =
data.mMemberBlocks.begin();
LLMsgData::msg_blk_data_map_t::const_iterator end =
data.mMemberBlocks.end();
for(; iter != end; ++iter)
{
const LLMsgBlkData* mbci = iter->second;
if(!mbci) continue;
// do we need to encode a block code?
if (block_count == 0)
{
block_count = mbci->mBlockNumber;
block_name = (char*)mbci->mName;
}
// counting down mutliple blocks
block_count--;
nextBlock(block_name);
// now loop through the variables
LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
for(; dit != dend; ++dit)
{
const LLMsgVarData& mvci = mbci->mMemberVarData.toValue(dit);
const char* varname = mvci.getName();
switch(mvci.getType())
{
case MVT_FIXED:
addBinaryData(varname, mvci.getData(), mvci.getSize());
break;
case MVT_VARIABLE:
{
const char end = ((const char*)mvci.getData())[mvci.getSize()-1]; // Ensure null terminated
if (mvci.getDataSize() == 1 && end == 0)
{
addString(varname, (const char*)mvci.getData());
}
else
{
addBinaryData(varname, mvci.getData(), mvci.getSize());
}
break;
}
case MVT_U8:
addU8(varname, *(U8*)mvci.getData());
break;
case MVT_U16:
addU16(varname, *(U16*)mvci.getData());
break;
case MVT_U32:
addU32(varname, *(U32*)mvci.getData());
break;
case MVT_U64:
addU64(varname, *(U64*)mvci.getData());
break;
case MVT_S8:
addS8(varname, *(S8*)mvci.getData());
break;
case MVT_S16:
addS16(varname, *(S16*)mvci.getData());
break;
case MVT_S32:
addS32(varname, *(S32*)mvci.getData());
break;
// S64 not supported in LLSD so we just truncate it
case MVT_S64:
addS32(varname, (S32)*(S64*)mvci.getData());
break;
case MVT_F32:
addF32(varname, *(F32*)mvci.getData());
break;
case MVT_F64:
addF64(varname, *(F64*)mvci.getData());
break;
case MVT_LLVector3:
addVector3(varname, *(LLVector3*)mvci.getData());
break;
case MVT_LLVector3d:
addVector3d(varname, *(LLVector3d*)mvci.getData());
break;
case MVT_LLVector4:
addVector4(varname, *(LLVector4*)mvci.getData());
break;
case MVT_LLQuaternion:
{
LLVector3 v = *(LLVector3*)mvci.getData();
LLQuaternion q;
q.unpackFromVector3(v);
addQuat(varname, q);
break;
}
case MVT_LLUUID:
addUUID(varname, *(LLUUID*)mvci.getData());
break;
case MVT_BOOL:
addBOOL(varname, *(BOOL*)mvci.getData());
break;
case MVT_IP_ADDR:
addIPAddr(varname, *(U32*)mvci.getData());
break;
case MVT_IP_PORT:
addIPPort(varname, *(U16*)mvci.getData());
break;
case MVT_U16Vec3:
//treated as an array of 6 bytes
addBinaryData(varname, mvci.getData(), 6);
break;
case MVT_U16Quat:
//treated as an array of 8 bytes
addBinaryData(varname, mvci.getData(), 8);
break;
case MVT_S16Array:
addBinaryData(varname, mvci.getData(), mvci.getSize());
break;
default:
LL_WARNS() << "Unknown type in conversion of message to LLSD" << LL_ENDL;
break;
}
}
}
}
//virtual
void LLSDMessageBuilder::copyFromLLSD(const LLSD& msg)
{
mCurrentMessage = msg;
LL_DEBUGS() << LLSDNotationStreamer(mCurrentMessage) << LL_ENDL;
}
const LLSD& LLSDMessageBuilder::getMessage() const
{
return mCurrentMessage;
}
//virtual
void LLSDMessageBuilder::setBuilt(BOOL b) { mbSBuilt = b; }
//virtual
BOOL LLSDMessageBuilder::isBuilt() const {return mbSBuilt;}
//virtual
BOOL LLSDMessageBuilder::isClear() const {return mbSClear;}
//virtual
S32 LLSDMessageBuilder::getMessageSize()
{
// babbage: size is unknown as message stored as LLSD.
// return non-zero if pending data, as send can be skipped for 0 size.
// return 1 to encourage senders checking size against splitting message.
return mCurrentMessage.size()? 1 : 0;
}
//virtual
const char* LLSDMessageBuilder::getMessageName() const
{
return mCurrentMessageName.c_str();
}