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 b36b83e75e..9dee01c1ee 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());
+}
|