diff options
Diffstat (limited to 'indra/llcharacter/llgesture.cpp')
-rw-r--r-- | indra/llcharacter/llgesture.cpp | 696 |
1 files changed, 348 insertions, 348 deletions
diff --git a/indra/llcharacter/llgesture.cpp b/indra/llcharacter/llgesture.cpp index 9dee01c1ee..151bac7920 100644 --- a/indra/llcharacter/llgesture.cpp +++ b/indra/llcharacter/llgesture.cpp @@ -1,348 +1,348 @@ -/**
- * @file llgesture.cpp
- *
- * $LicenseInfo:firstyear=2002&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 "indra_constants.h"
-
-#include "llgesture.h"
-#include "llendianswizzle.h"
-#include "message.h"
-#include <boost/tokenizer.hpp>
-
-// for allocating serialization buffers - these need to be updated when members change
-const S32 LLGestureList::SERIAL_HEADER_SIZE = sizeof(S32);
-const S32 LLGesture::MAX_SERIAL_SIZE = sizeof(KEY) + sizeof(MASK) + 16 + 26 + 41 + 41;
-
-LLGesture::LLGesture()
-: mKey(KEY_NONE),
- mMask(MASK_NONE),
- mTrigger(),
- mTriggerLower(),
- mSoundItemID(),
- mAnimation(),
- mOutputString()
-{ }
-
-LLGesture::LLGesture(KEY key, MASK mask, const std::string &trigger,
- const LLUUID &sound_item_id,
- const std::string &animation,
- const std::string &output_string)
-:
- mKey(key),
- mMask(mask),
- mTrigger(trigger),
- mTriggerLower(trigger),
- mSoundItemID(sound_item_id),
- mAnimation(animation),
- mOutputString(output_string)
-{
- mTriggerLower = utf8str_tolower(mTriggerLower);
-}
-
-LLGesture::LLGesture(U8 **buffer, S32 max_size)
-{
- *buffer = deserialize(*buffer, max_size);
-}
-
-LLGesture::LLGesture(const LLGesture &rhs)
-{
- mKey = rhs.mKey;
- mMask = rhs.mMask;
- mTrigger = rhs.mTrigger;
- mTriggerLower = rhs.mTriggerLower;
- mSoundItemID = rhs.mSoundItemID;
- mAnimation = rhs.mAnimation;
- mOutputString = rhs.mOutputString;
-}
-
-const LLGesture &LLGesture::operator =(const LLGesture &rhs)
-{
- mKey = rhs.mKey;
- mMask = rhs.mMask;
- mTrigger = rhs.mTrigger;
- mTriggerLower = rhs.mTriggerLower;
- mSoundItemID = rhs.mSoundItemID;
- mAnimation = rhs.mAnimation;
- mOutputString = rhs.mOutputString;
- return (*this);
-}
-
-
-bool LLGesture::trigger(KEY key, MASK mask)
-{
- LL_WARNS() << "Parent class trigger called: you probably didn't mean this." << LL_ENDL;
- return false;
-}
-
-
-bool LLGesture::trigger(const std::string& trigger_string)
-{
- LL_WARNS() << "Parent class trigger called: you probably didn't mean this." << LL_ENDL;
- return false;
-}
-
-// NOT endian-neutral
-U8 *LLGesture::serialize(U8 *buffer) const
-{
- htolememcpy(buffer, &mKey, MVT_S8, 1);
- buffer += sizeof(mKey);
- htolememcpy(buffer, &mMask, MVT_U32, 4);
- buffer += sizeof(mMask);
- htolememcpy(buffer, mSoundItemID.mData, MVT_LLUUID, 16);
- buffer += 16;
-
- memcpy(buffer, mTrigger.c_str(), mTrigger.length() + 1); /* Flawfinder: ignore */
- buffer += mTrigger.length() + 1;
- memcpy(buffer, mAnimation.c_str(), mAnimation.length() + 1); /* Flawfinder: ignore */
- buffer += mAnimation.length() + 1;
- memcpy(buffer, mOutputString.c_str(), mOutputString.length() + 1); /* Flawfinder: ignore */
- buffer += mOutputString.length() + 1;
-
- return buffer;
-}
-
-U8 *LLGesture::deserialize(U8 *buffer, S32 max_size)
-{
- U8 *tmp = buffer;
-
- if (tmp + sizeof(mKey) + sizeof(mMask) + 16 > buffer + max_size)
- {
- LL_WARNS() << "Attempt to read past end of buffer, bad data!!!!" << LL_ENDL;
- return buffer;
- }
-
- htolememcpy(&mKey, tmp, MVT_S8, 1);
- tmp += sizeof(mKey);
- htolememcpy(&mMask, tmp, MVT_U32, 4);
- tmp += sizeof(mMask);
- htolememcpy(mSoundItemID.mData, tmp, MVT_LLUUID, 16);
- tmp += 16;
-
- mTrigger.assign((char *)tmp);
- mTriggerLower = mTrigger;
- mTriggerLower = utf8str_tolower(mTriggerLower);
- tmp += mTrigger.length() + 1;
- mAnimation.assign((char *)tmp);
- //RN: force animation names to lower case
- // must do this for backwards compatibility
- mAnimation = utf8str_tolower(mAnimation);
- tmp += mAnimation.length() + 1;
- mOutputString.assign((char *)tmp);
- tmp += mOutputString.length() + 1;
-
- if (tmp > buffer + max_size)
- {
- LL_WARNS() << "Read past end of buffer, bad data!!!!" << LL_ENDL;
- return tmp;
- }
-
- return tmp;
-}
-
-S32 LLGesture::getMaxSerialSize()
-{
- return MAX_SERIAL_SIZE;
-}
-
-//---------------------------------------------------------------------
-// LLGestureList
-//---------------------------------------------------------------------
-
-LLGestureList::LLGestureList()
-: mList(0)
-{}
-
-LLGestureList::~LLGestureList()
-{
- deleteAll();
-}
-
-
-void LLGestureList::deleteAll()
-{
- delete_and_clear(mList);
-}
-
-// Iterates through space delimited tokens in string, triggering any gestures found.
-// Generates a revised string that has the found tokens replaced by their replacement strings
-// and (as a minor side effect) has multiple spaces in a row replaced by single spaces.
-bool LLGestureList::triggerAndReviseString(const std::string &string, std::string* revised_string)
-{
- std::string tokenized = string;
-
- bool found_gestures = false;
- bool first_token = true;
-
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep(" ");
- tokenizer tokens(string, sep);
-
- for(const std::string& cur_token : tokens)
- {
- LLGesture* gesture = NULL;
-
- if( !found_gestures ) // Only pay attention to the first gesture in the string.
- {
- std::string cur_token_lower = cur_token;
- LLStringUtil::toLower(cur_token_lower);
-
- for (U32 i = 0; i < mList.size(); i++)
- {
- gesture = mList.at(i);
- if (gesture->trigger(cur_token_lower))
- {
- if( !gesture->getOutputString().empty() )
- {
- if( !first_token )
- {
- revised_string->append( " " );
- }
-
- // Don't muck with the user's capitalization if we don't have to.
- const std::string& output = gesture->getOutputString();
- std::string output_lower = std::string(output.c_str());
- LLStringUtil::toLower(output_lower);
- if( cur_token_lower == output_lower )
- {
- revised_string->append(cur_token);
- }
- else
- {
- revised_string->append(output);
- }
-
- }
- found_gestures = true;
- break;
- }
- gesture = NULL;
- }
- }
-
- if( !gesture )
- {
- if( !first_token )
- {
- revised_string->append( " " );
- }
- revised_string->append( cur_token );
- }
-
- first_token = false;
- }
- return found_gestures;
-}
-
-
-
-bool LLGestureList::trigger(KEY key, MASK mask)
-{
- for (U32 i = 0; i < mList.size(); i++)
- {
- LLGesture* gesture = mList.at(i);
- if( gesture )
- {
- if (gesture->trigger(key, mask))
- {
- return true;
- }
- }
- else
- {
- LL_WARNS() << "NULL gesture in gesture list (" << i << ")" << LL_ENDL;
- }
- }
- return false;
-}
-
-// NOT endian-neutral
-U8 *LLGestureList::serialize(U8 *buffer) const
-{
- // a single S32 serves as the header that tells us how many to read
- U32 count = mList.size();
- htolememcpy(buffer, &count, MVT_S32, 4);
- buffer += sizeof(count);
-
- for (S32 i = 0; i < count; i++)
- {
- buffer = mList[i]->serialize(buffer);
- }
-
- return buffer;
-}
-
-const S32 MAX_GESTURES = 4096;
-
-U8 *LLGestureList::deserialize(U8 *buffer, S32 max_size)
-{
- deleteAll();
-
- S32 count;
- U8 *tmp = buffer;
-
- if (tmp + sizeof(count) > buffer + max_size)
- {
- LL_WARNS() << "Invalid max_size" << LL_ENDL;
- return buffer;
- }
-
- htolememcpy(&count, tmp, MVT_S32, 4);
-
- if (count > MAX_GESTURES)
- {
- LL_WARNS() << "Unreasonably large gesture list count in deserialize: " << count << LL_ENDL;
- return tmp;
- }
-
- tmp += sizeof(count);
-
- mList.resize(count);
-
- for (S32 i = 0; i < count; i++)
- {
- mList[i] = create_gesture(&tmp, max_size - (S32)(tmp - buffer));
- if (tmp - buffer > max_size)
- {
- LL_WARNS() << "Deserialization read past end of buffer, bad data!!!!" << LL_ENDL;
- return tmp;
- }
- }
-
- return tmp;
-}
-
-// this is a helper for deserialize
-// it gets overridden by LLViewerGestureList to create LLViewerGestures
-// overridden by child class to use local LLGesture implementation
-LLGesture *LLGestureList::create_gesture(U8 **buffer, S32 max_size)
-{
- return new LLGesture(buffer, max_size);
-}
-
-S32 LLGestureList::getMaxSerialSize()
-{
- return SERIAL_HEADER_SIZE + (count() * LLGesture::getMaxSerialSize());
-}
+/** + * @file llgesture.cpp + * + * $LicenseInfo:firstyear=2002&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 "indra_constants.h" + +#include "llgesture.h" +#include "llendianswizzle.h" +#include "message.h" +#include <boost/tokenizer.hpp> + +// for allocating serialization buffers - these need to be updated when members change +const S32 LLGestureList::SERIAL_HEADER_SIZE = sizeof(S32); +const S32 LLGesture::MAX_SERIAL_SIZE = sizeof(KEY) + sizeof(MASK) + 16 + 26 + 41 + 41; + +LLGesture::LLGesture() +: mKey(KEY_NONE), + mMask(MASK_NONE), + mTrigger(), + mTriggerLower(), + mSoundItemID(), + mAnimation(), + mOutputString() +{ } + +LLGesture::LLGesture(KEY key, MASK mask, const std::string &trigger, + const LLUUID &sound_item_id, + const std::string &animation, + const std::string &output_string) +: + mKey(key), + mMask(mask), + mTrigger(trigger), + mTriggerLower(trigger), + mSoundItemID(sound_item_id), + mAnimation(animation), + mOutputString(output_string) +{ + mTriggerLower = utf8str_tolower(mTriggerLower); +} + +LLGesture::LLGesture(U8 **buffer, S32 max_size) +{ + *buffer = deserialize(*buffer, max_size); +} + +LLGesture::LLGesture(const LLGesture &rhs) +{ + mKey = rhs.mKey; + mMask = rhs.mMask; + mTrigger = rhs.mTrigger; + mTriggerLower = rhs.mTriggerLower; + mSoundItemID = rhs.mSoundItemID; + mAnimation = rhs.mAnimation; + mOutputString = rhs.mOutputString; +} + +const LLGesture &LLGesture::operator =(const LLGesture &rhs) +{ + mKey = rhs.mKey; + mMask = rhs.mMask; + mTrigger = rhs.mTrigger; + mTriggerLower = rhs.mTriggerLower; + mSoundItemID = rhs.mSoundItemID; + mAnimation = rhs.mAnimation; + mOutputString = rhs.mOutputString; + return (*this); +} + + +bool LLGesture::trigger(KEY key, MASK mask) +{ + LL_WARNS() << "Parent class trigger called: you probably didn't mean this." << LL_ENDL; + return false; +} + + +bool LLGesture::trigger(const std::string& trigger_string) +{ + LL_WARNS() << "Parent class trigger called: you probably didn't mean this." << LL_ENDL; + return false; +} + +// NOT endian-neutral +U8 *LLGesture::serialize(U8 *buffer) const +{ + htolememcpy(buffer, &mKey, MVT_S8, 1); + buffer += sizeof(mKey); + htolememcpy(buffer, &mMask, MVT_U32, 4); + buffer += sizeof(mMask); + htolememcpy(buffer, mSoundItemID.mData, MVT_LLUUID, 16); + buffer += 16; + + memcpy(buffer, mTrigger.c_str(), mTrigger.length() + 1); /* Flawfinder: ignore */ + buffer += mTrigger.length() + 1; + memcpy(buffer, mAnimation.c_str(), mAnimation.length() + 1); /* Flawfinder: ignore */ + buffer += mAnimation.length() + 1; + memcpy(buffer, mOutputString.c_str(), mOutputString.length() + 1); /* Flawfinder: ignore */ + buffer += mOutputString.length() + 1; + + return buffer; +} + +U8 *LLGesture::deserialize(U8 *buffer, S32 max_size) +{ + U8 *tmp = buffer; + + if (tmp + sizeof(mKey) + sizeof(mMask) + 16 > buffer + max_size) + { + LL_WARNS() << "Attempt to read past end of buffer, bad data!!!!" << LL_ENDL; + return buffer; + } + + htolememcpy(&mKey, tmp, MVT_S8, 1); + tmp += sizeof(mKey); + htolememcpy(&mMask, tmp, MVT_U32, 4); + tmp += sizeof(mMask); + htolememcpy(mSoundItemID.mData, tmp, MVT_LLUUID, 16); + tmp += 16; + + mTrigger.assign((char *)tmp); + mTriggerLower = mTrigger; + mTriggerLower = utf8str_tolower(mTriggerLower); + tmp += mTrigger.length() + 1; + mAnimation.assign((char *)tmp); + //RN: force animation names to lower case + // must do this for backwards compatibility + mAnimation = utf8str_tolower(mAnimation); + tmp += mAnimation.length() + 1; + mOutputString.assign((char *)tmp); + tmp += mOutputString.length() + 1; + + if (tmp > buffer + max_size) + { + LL_WARNS() << "Read past end of buffer, bad data!!!!" << LL_ENDL; + return tmp; + } + + return tmp; +} + +S32 LLGesture::getMaxSerialSize() +{ + return MAX_SERIAL_SIZE; +} + +//--------------------------------------------------------------------- +// LLGestureList +//--------------------------------------------------------------------- + +LLGestureList::LLGestureList() +: mList(0) +{} + +LLGestureList::~LLGestureList() +{ + deleteAll(); +} + + +void LLGestureList::deleteAll() +{ + delete_and_clear(mList); +} + +// Iterates through space delimited tokens in string, triggering any gestures found. +// Generates a revised string that has the found tokens replaced by their replacement strings +// and (as a minor side effect) has multiple spaces in a row replaced by single spaces. +bool LLGestureList::triggerAndReviseString(const std::string &string, std::string* revised_string) +{ + std::string tokenized = string; + + bool found_gestures = false; + bool first_token = true; + + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep(" "); + tokenizer tokens(string, sep); + + for(const std::string& cur_token : tokens) + { + LLGesture* gesture = NULL; + + if( !found_gestures ) // Only pay attention to the first gesture in the string. + { + std::string cur_token_lower = cur_token; + LLStringUtil::toLower(cur_token_lower); + + for (U32 i = 0; i < mList.size(); i++) + { + gesture = mList.at(i); + if (gesture->trigger(cur_token_lower)) + { + if( !gesture->getOutputString().empty() ) + { + if( !first_token ) + { + revised_string->append( " " ); + } + + // Don't muck with the user's capitalization if we don't have to. + const std::string& output = gesture->getOutputString(); + std::string output_lower = std::string(output.c_str()); + LLStringUtil::toLower(output_lower); + if( cur_token_lower == output_lower ) + { + revised_string->append(cur_token); + } + else + { + revised_string->append(output); + } + + } + found_gestures = true; + break; + } + gesture = NULL; + } + } + + if( !gesture ) + { + if( !first_token ) + { + revised_string->append( " " ); + } + revised_string->append( cur_token ); + } + + first_token = false; + } + return found_gestures; +} + + + +bool LLGestureList::trigger(KEY key, MASK mask) +{ + for (U32 i = 0; i < mList.size(); i++) + { + LLGesture* gesture = mList.at(i); + if( gesture ) + { + if (gesture->trigger(key, mask)) + { + return true; + } + } + else + { + LL_WARNS() << "NULL gesture in gesture list (" << i << ")" << LL_ENDL; + } + } + return false; +} + +// NOT endian-neutral +U8 *LLGestureList::serialize(U8 *buffer) const +{ + // a single S32 serves as the header that tells us how many to read + U32 count = mList.size(); + htolememcpy(buffer, &count, MVT_S32, 4); + buffer += sizeof(count); + + for (S32 i = 0; i < count; i++) + { + buffer = mList[i]->serialize(buffer); + } + + return buffer; +} + +const S32 MAX_GESTURES = 4096; + +U8 *LLGestureList::deserialize(U8 *buffer, S32 max_size) +{ + deleteAll(); + + S32 count; + U8 *tmp = buffer; + + if (tmp + sizeof(count) > buffer + max_size) + { + LL_WARNS() << "Invalid max_size" << LL_ENDL; + return buffer; + } + + htolememcpy(&count, tmp, MVT_S32, 4); + + if (count > MAX_GESTURES) + { + LL_WARNS() << "Unreasonably large gesture list count in deserialize: " << count << LL_ENDL; + return tmp; + } + + tmp += sizeof(count); + + mList.resize(count); + + for (S32 i = 0; i < count; i++) + { + mList[i] = create_gesture(&tmp, max_size - (S32)(tmp - buffer)); + if (tmp - buffer > max_size) + { + LL_WARNS() << "Deserialization read past end of buffer, bad data!!!!" << LL_ENDL; + return tmp; + } + } + + return tmp; +} + +// this is a helper for deserialize +// it gets overridden by LLViewerGestureList to create LLViewerGestures +// overridden by child class to use local LLGesture implementation +LLGesture *LLGestureList::create_gesture(U8 **buffer, S32 max_size) +{ + return new LLGesture(buffer, max_size); +} + +S32 LLGestureList::getMaxSerialSize() +{ + return SERIAL_HEADER_SIZE + (count() * LLGesture::getMaxSerialSize()); +} |