Merge branch 'master' of git://github.com/AlericInglewood/SingularityViewer

This commit is contained in:
Latif Khalifa
2013-11-07 01:07:21 +01:00
45 changed files with 2448 additions and 534 deletions

View File

@@ -117,7 +117,8 @@ public:
/*virtual*/ void stopAnimating(BOOL upload_bake);
/*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
/*virtual*/ void resetDrivenParams();
/*virtual*/ char const* getTypeString(void) const { return "param_driver"; }
// LLViewerVisualParam Virtual functions
/*virtual*/ F32 getTotalDistortion();
/*virtual*/ const LLVector4a& getAvgDistortion();

View File

@@ -173,6 +173,7 @@ public:
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex sex );
/*virtual*/ char const* getTypeString(void) const { return "param_morph"; }
// LLViewerVisualParam Virtual functions
/*virtual*/ F32 getTotalDistortion();

View File

@@ -109,7 +109,8 @@ public:
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex sex );
/*virtual*/ char const* getTypeString(void) const { return "param_skeleton"; }
// LLViewerVisualParam Virtual functions
/*virtual*/ F32 getTotalDistortion() { return 0.1f; }
/*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; }

View File

@@ -86,6 +86,7 @@ public:
/*virtual*/ void setWeight(F32 weight, BOOL upload_bake);
/*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake);
/*virtual*/ void animate(F32 delta, BOOL upload_bake);
/*virtual*/ char const* getTypeString(void) const { return "param_alpha"; }
// LLViewerVisualParam Virtual functions
/*virtual*/ F32 getTotalDistortion() { return 1.f; }
@@ -177,7 +178,7 @@ public:
/*virtual*/ void setWeight(F32 weight, BOOL upload_bake);
/*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake);
/*virtual*/ void animate(F32 delta, BOOL upload_bake);
/*virtual*/ char const* getTypeString(void) const { return "param_color"; }
// LLViewerVisualParam Virtual functions
/*virtual*/ F32 getTotalDistortion() { return 1.f; }

View File

@@ -143,6 +143,12 @@ BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info)
return TRUE;
}
//virtual
std::string LLViewerVisualParam::getDumpWearableTypeName(void) const
{
return LLWearableType::getTypeName(LLWearableType::EType(getInfo()->mWearableType));
}
/*
//=============================================================================
// These virtual functions should always be overridden,

View File

@@ -82,6 +82,7 @@ public:
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ std::string getDumpWearableTypeName(void) const;
// New Virtual functions
virtual F32 getTotalDistortion() = 0;

View File

@@ -41,6 +41,7 @@ class LLVisualParam;
class LLTexGlobalColorInfo;
class LLTexGlobalColor;
class LLAvatarAppearance;
class AIArchetype;
// Abstract class.
class LLWearable

View File

@@ -162,6 +162,10 @@ public:
void setParamLocation(EParamLocation loc);
EParamLocation getParamLocation() const { return mParamLocation; }
// Singu extensions. Used for dumping the archtype.
virtual char const* getTypeString(void) const = 0;
virtual std::string getDumpWearableTypeName(void) const = 0;
protected:
F32 mCurWeight; // current weight
F32 mLastWeight; // last weight

View File

@@ -17,6 +17,8 @@ include_directories(
)
set(llcommon_SOURCE_FILES
aialert.cpp
aifile.cpp
aiframetimer.cpp
aithreadid.cpp
imageids.cpp
@@ -106,6 +108,8 @@ set(llcommon_SOURCE_FILES
set(llcommon_HEADER_FILES
CMakeLists.txt
aialert.h
aifile.h
aiframetimer.h
airecursive.h
aithreadid.h

View File

@@ -0,0 +1,75 @@
/**
* @file aialert.cpp
*
* Copyright (c) 2013, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 02/11/2013
* - Initial version, written by Aleric Inglewood @ SL
*
* 05/11/2013
* Moved everything in namespace AIAlert, except AIArgs.
*/
#include "aialert.h"
namespace AIAlert
{
Error::Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, AIArgs const& args) : mModal(type)
{
if (prefix) mLines.push_back(Line(prefix));
mLines.push_back(Line(xml_desc, args));
}
Error::Error(Prefix const& prefix, modal_nt type,
Error const& alert,
std::string const& xml_desc, AIArgs const& args) : mLines(alert.mLines), mModal(type)
{
if (alert.mModal == modal) mModal = modal;
if (prefix) mLines.push_back(Line(prefix, !mLines.empty()));
mLines.push_back(Line(xml_desc, args));
}
Error::Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc,
Error const& alert) : mLines(alert.mLines), mModal(type)
{
if (alert.mModal == modal) mModal = modal;
if (!mLines.empty()) { mLines.front().set_newline(); }
mLines.push_front(Line(xml_desc));
if (prefix) mLines.push_front(Line(prefix));
}
Error::Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, AIArgs const& args,
Error const& alert) : mLines(alert.mLines), mModal(type)
{
if (alert.mModal == modal) mModal = modal;
if (!mLines.empty()) { mLines.front().set_newline(); }
mLines.push_front(Line(xml_desc, args));
if (prefix) mLines.push_front(Line(prefix));
}
} // namespace AIAlert

293
indra/llcommon/aialert.h Normal file
View File

@@ -0,0 +1,293 @@
/**
* @file aialert.h
* @brief Declaration of AIArgs and AIAlert classes.
*
* Copyright (c) 2013, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 02/11/2013
* Initial version, written by Aleric Inglewood @ SL
*
* 05/11/2013
* Moved everything in namespace AIAlert, except AIArgs.
*/
#ifndef AI_ALERT
#define AI_ALERT
#include "llpreprocessor.h"
#include "llstring.h"
#include <deque>
#include <exception>
//===================================================================================================================================
// Facility to throw errors that can easily be converted to an informative pop-up floater for the user.
// Throw arbitrary class.
#define THROW_ALERT_CLASS(Alert, ...) throw Alert(AIAlert::Prefix(), AIAlert::not_modal, __VA_ARGS__)
#define THROW_MALERT_CLASS(Alert, ...) throw Alert(AIAlert::Prefix(), AIAlert::modal, __VA_ARGS__)
#define THROW_FALERT_CLASS(Alert, ...) throw Alert(AIAlert::Prefix(__PRETTY_FUNCTION__, AIAlert::pretty_function_prefix), AIAlert::not_modal, __VA_ARGS__)
#define THROW_FMALERT_CLASS(Alert, ...) throw Alert(AIAlert::Prefix(__PRETTY_FUNCTION__, AIAlert::pretty_function_prefix), AIAlert::modal, __VA_ARGS__)
// Shortcut to throw AIAlert::Error.
#define THROW_ALERT(...) THROW_ALERT_CLASS(AIAlert::Error, __VA_ARGS__)
#define THROW_MALERT(...) THROW_MALERT_CLASS(AIAlert::Error, __VA_ARGS__)
#define THROW_FALERT(...) THROW_FALERT_CLASS(AIAlert::Error, __VA_ARGS__)
#define THROW_FMALERT(...) THROW_FMALERT_CLASS(AIAlert::Error, __VA_ARGS__)
// Shortcut to throw AIAlert::ErrorCode.
#define THROW_ALERTC(...) THROW_ALERT_CLASS(AIAlert::ErrorCode, __VA_ARGS__)
#define THROW_MALERTC(...) THROW_MALERT_CLASS(AIAlert::ErrorCode, __VA_ARGS__)
#define THROW_FALERTC(...) THROW_FALERT_CLASS(AIAlert::ErrorCode, __VA_ARGS__)
#define THROW_FMALERTC(...) THROW_FMALERT_CLASS(AIAlert::ErrorCode, __VA_ARGS__)
// Shortcut to throw AIAlert::ErrorCode with errno as code.
#define THROW_ALERTE(...) do { int errn = errno; THROW_ALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__); } while(0)
#define THROW_MALERTE(...) do { int errn = errno; THROW_MALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__); } while(0)
#define THROW_FALERTE(...) do { int errn = errno; THROW_FALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__); } while(0)
#define THROW_FMALERTE(...) do { int errn = errno; THROW_FMALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__); } while(0)
// Examples
#ifdef EXAMPLE_CODE
//----------------------------------------------------------
// To show the alert box:
catch (AIAlert::Error const& error)
{
AIAlert::add(error); // Optionally pass pretty_function_prefix as second parameter to *suppress* that output.
}
// or, for example
catch (AIAlert::ErrorCode const& error)
{
if (error.getCode() != EEXIST)
{
AIAlert::add(alert, AIAlert::pretty_function_prefix);
}
}
//----------------------------------------------------------
// To throw alerts:
THROW_ALERT("ExampleKey"); // A) Lookup "ExampleKey" in strings.xml and show translation.
THROW_ALERT("ExampleKey", AIArgs("[FIRST]", first)("[SECOND]", second)(...etc...)); // B) Same as A, but replace [FIRST] with first, [SECOND] with second, etc.
THROW_ALERT("ExampleKey", error); // C) As A, but followed by a colon and a newline, and then the text of 'error'.
THROW_ALERT(error, "ExampleKey"); // D) The text of 'error', followed by a colon and a newline and then as A.
THROW_ALERT("ExampleKey", AIArgs("[FIRST]", first)("[SECOND]", second), error); // E) As B, but followed by a colon and a newline, and then the text of 'error'.
THROW_ALERT(error, "ExampleKey", AIArgs("[FIRST]", first)("[SECOND]", second)); // F) The text of 'error', followed by a colon and a newline and then as B.
// where 'error' is a caught Error object (as above) in a rethrow.
// Prepend ALERT with M and/or F to make the alert box Modal and/or prepend the text with the current function name.
// For example,
THROW_MFALERT("ExampleKey", AIArgs("[FIRST]", first)); // Throw a Modal alert box that is prefixed with the current Function name.
// Append E after ALERT to throw an ErrorCode class that contains the current errno.
// For example,
THROW_FALERTE("ExampleKey", AIArgs("[FIRST]", first)); // Throw an alert box that is prefixed with the current Function name and pass errno to the catcher.
#endif // EXAMPLE_CODE
//
//===================================================================================================================================
// A wrapper around LLStringUtil::format_map_t to allow constructing a dictionary
// on one line by doing:
//
// AIArgs("[ARG1]", arg1)("[ARG2]", arg2)("[ARG3]", arg3)...
class LL_COMMON_API AIArgs
{
private:
LLStringUtil::format_map_t mArgs; // The underlying replacement map.
public:
// Construct an empty map.
AIArgs(void) { }
// Construct a map with a single replacement.
AIArgs(char const* key, std::string const& replacement) { mArgs[key] = replacement; }
// Add another replacement.
AIArgs& operator()(char const* key, std::string const& replacement) { mArgs[key] = replacement; return *this; }
// The destructor may not throw.
~AIArgs() throw() { }
// Accessor.
LLStringUtil::format_map_t const& operator*() const { return mArgs; }
};
namespace AIAlert
{
enum modal_nt
{
not_modal,
modal
};
enum alert_line_type_nt
{
normal = 0,
empty_prefix = 1,
pretty_function_prefix = 2
// These must exist of single bits (a mask).
};
// An Prefix currently comes only in two flavors:
//
// empty_prefix : An empty prefix.
// pretty_function_prefix : A function name prefix, this is the function from which the alert was thrown.
class LL_COMMON_API Prefix
{
public:
Prefix(void) : mType(empty_prefix) { }
Prefix(char const* str, alert_line_type_nt type) : mStr(str), mType(type) { }
operator bool(void) const { return mType != empty_prefix; }
alert_line_type_nt type(void) const { return mType; }
std::string const& str(void) const { return mStr; }
private:
std::string mStr; // Literal text. For example a C++ function name.
alert_line_type_nt mType; // The type of this prefix.
};
// A class that represents one line with its replacements.
// The string mXmlDesc shall be looked up in strings.xml.
// This is not done as part of this class because LLTrans::getString
// is not part of llcommon.
class LL_COMMON_API Line
{
private:
bool mNewline; // Prepend this line with a newline if set.
std::string mXmlDesc; // The keyword to look up in string.xml.
AIArgs mArgs; // Replacement map.
alert_line_type_nt mType; // The type of this line: normal for normal lines, other for prefixes.
public:
Line(std::string const& xml_desc, bool newline = false) : mNewline(newline), mXmlDesc(xml_desc), mType(normal) { }
Line(std::string const& xml_desc, AIArgs const& args, bool newline = false) : mNewline(newline), mXmlDesc(xml_desc), mArgs(args), mType(normal) { }
Line(Prefix const& prefix, bool newline = false) : mNewline(newline), mXmlDesc("AIPrefix"), mArgs("[PREFIX]", prefix.str()), mType(prefix.type()) { }
// The destructor may not throw.
~Line() throw() { }
// Prepend a newline before this line.
void set_newline(void) { mNewline = true; }
// These are to be used like: LLTrans::getString(line.getXmlDesc(), line.args()) and prepend with a \n if prepend_newline() returns true.
std::string getXmlDesc(void) const { return mXmlDesc; }
LLStringUtil::format_map_t const& args(void) const { return *mArgs; }
bool prepend_newline(void) const { return mNewline; }
// Accessors.
bool suppressed(unsigned int suppress_mask) const { return (suppress_mask & mType) != 0; }
bool is_prefix(void) const { return mType != normal; }
};
// This class is used to throw an error that will cause
// an alert box to pop up for the user.
//
// An alert box only has text and an OK button.
// The alert box does not give feed back to the program; it is purely informational.
// The class represents multiple lines, each line is to be translated and catenated,
// separated by newlines, and then written to an alert box. This is not done as part
// of this class because LLTrans::getString and LLNotification is not part of llcommon.
// Instead call LLNotificationUtil::add(Error const&).
class LL_COMMON_API Error : public std::exception
{
public:
typedef std::deque<Line> lines_type;
// The destructor may not throw.
~Error() throw() { }
// Accessors.
lines_type const& lines(void) const { return mLines; }
bool is_modal(void) const { return mModal == modal; }
// A string with zero or more replacements.
Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, AIArgs const& args = AIArgs());
// Same as above bit prepending the message with the text of another alert.
Error(Prefix const& prefix, modal_nt type,
Error const& alert,
std::string const& xml_desc, AIArgs const& args = AIArgs());
// Same as above but appending the message with the text of another alert.
// (no args)
Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc,
Error const& alert);
// (with args)
Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, AIArgs const& args,
Error const& alert);
private:
lines_type mLines; // The lines (or prefixes) of text to be displayed, each consisting on a keyword (to be looked up in strings.xml) and a replacement map.
modal_nt mModal; // If true, make the alert box a modal floater.
};
// Same as Error but allows to pass an additional error code.
class LL_COMMON_API ErrorCode : public Error
{
private:
int mCode;
public:
// The destructor may not throw.
~ErrorCode() throw() { }
// Accessor.
int getCode(void) const { return mCode; }
// A string with zero or more replacements.
ErrorCode(Prefix const& prefix, modal_nt type, int code,
std::string const& xml_desc, AIArgs const& args = AIArgs()) :
Error(prefix, modal, xml_desc, args) { }
// Same as above bit prepending the message with the text of another alert.
ErrorCode(Prefix const& prefix, modal_nt type, int code,
Error const& alert,
std::string const& xml_desc, AIArgs const& args = AIArgs()) :
Error(prefix, modal, alert, xml_desc, args) { }
// Same as above but appending the message with the text of another alert.
// (no args)
ErrorCode(Prefix const& prefix, modal_nt type, int code,
std::string const& xml_desc,
Error const& alert) :
Error(prefix, modal, xml_desc, alert) { }
// (with args)
ErrorCode(Prefix const& prefix, modal_nt type, int code,
std::string const& xml_desc, AIArgs const& args,
Error const& alert) :
Error(prefix, modal, xml_desc, args, alert) { }
};
} // namespace AIAlert
#endif // AI_ALERT

118
indra/llcommon/aifile.cpp Normal file
View File

@@ -0,0 +1,118 @@
/**
* @file aifile.cpp
* @brief POSIX file operations that throw on error.
*
* Copyright (c) 2013, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 03/11/2013
* Initial version, written by Aleric Inglewood @ SL
*/
#include "linden_common.h"
#include "aifile.h"
#include "aialert.h"
#if LL_WINDOWS
#include <windows.h>
#include <stdlib.h> // Windows errno
#else
#include <errno.h>
#endif
AIFile::AIFile(std::string const& filename, char const* accessmode)
{
mFp = AIFile::fopen(filename, accessmode);
}
AIFile::~AIFile()
{
AIFile::close(mFp);
}
// Like THROW_MALERTE but appends "LLFile::strerr(errn) << " (" << errn << ')'" as argument to replace [ERROR].
#define THROW_ERROR(...) \
do { \
int errn = errno; \
std::ostringstream error; \
error << LLFile::strerr(errn) << " (" << errn << ')'; \
THROW_MALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__ ("[ERROR]", error.str())); \
} while(0)
//static
void AIFile::mkdir(std::string const& dirname, int perms)
{
int rc = LLFile::mkdir(dirname, perms);
if (rc < 0 && rc != EEXIST)
{
THROW_ERROR("AIFile_mkdir_Failed_to_create_DIRNAME", AIArgs("[DIRNAME]", dirname));
}
}
//static
void AIFile::rmdir(std::string const& dirname)
{
int rc = LLFile::rmdir(dirname);
if (rc < 0 && rc != ENOENT)
{
THROW_ERROR("AIFile_rmdir_Failed_to_remove_DIRNAME", AIArgs("[DIRNAME]", dirname));
}
}
//static
LLFILE* AIFile::fopen(std::string const& filename, const char* mode)
{
LLFILE* fp = LLFile::fopen(filename, mode);
if (!fp)
{
THROW_ERROR("AIFile_fopen_Failed_to_open_FILENAME", AIArgs("[FILENAME]", filename));
}
return fp;
}
//static
void AIFile::close(LLFILE* file)
{
if (LLFile::close(file) < 0)
{
THROW_ERROR("AIFile_close_Failed_to_close_file", AIArgs);
}
}
//static
void AIFile::remove(std::string const& filename)
{
if (LLFile::remove(filename) < 0)
{
THROW_ERROR("AIFile_remove_Failed_to_remove_FILENAME", AIArgs("[FILENAME]", filename));
}
}
//static
void AIFile::rename(std::string const& filename, std::string const& newname)
{
if (LLFile::rename(filename, newname) < 0)
{
THROW_ERROR("AIFile_rename_Failed_to_rename_FILE_to_NEWFILE", AIArgs("[FILE]", filename)("[NEWFILE]", newname));
}
}

59
indra/llcommon/aifile.h Normal file
View File

@@ -0,0 +1,59 @@
/**
* @file aifile.h
* @brief Declaration of AIFile.
*
* Copyright (c) 2013, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 02/11/2013
* Initial version, written by Aleric Inglewood @ SL
*/
#ifndef AIFILE_H
#define AIFILE_H
#include "llfile.h"
// As LLFile, but throws AIAlert instead of printing a warning.
class LL_COMMON_API AIFile
{
private:
LLFILE* mFp;
public:
// Scoped file (exception safe). Throws AIAlertCode with errno on failure.
AIFile(std::string const& filename, char const* accessmode);
~AIFile();
operator LLFILE* () const { return mFp; }
// All these functions take UTF8 path/filenames.
static LLFILE* fopen(std::string const& filename, char const* accessmode);
static void close(LLFILE* file);
static void mkdir(std::string const& dirname, int perms = 0700); // Does NOT throw when dirname already exists.
static void rmdir(std::string const& dirname); // Does NOT throw when dirname does not exist.
static void remove(std::string const& filename); // Does NOT throw when filename does not exist.
static void rename(std::string const& filename, std::string const& newname);
};
#endif // AIFILE_H

View File

@@ -49,7 +49,8 @@ static std::string empty;
#if LL_WINDOWS
// On Windows, use strerror_s().
std::string strerr(int errn)
//static
std::string LLFile::strerr(int errn)
{
char buffer[256];
strerror_s(buffer, errn); // infers sizeof(buffer) -- love it!
@@ -98,7 +99,8 @@ std::string message_from(int orig_errno, const char* buffer, size_t bufflen,
<< " (error " << stre_errno << ')');
}
std::string strerr(int errn)
//static
std::string LLFile::strerr(int errn)
{
char buffer[256];
// Select message_from() function matching the strerror_r() we have on hand.
@@ -108,7 +110,8 @@ std::string strerr(int errn)
#endif // ! LL_WINDOWS
// On either system, shorthand call just infers global 'errno'.
std::string strerr()
//static
std::string LLFile::strerr()
{
return strerr(errno);
}
@@ -125,7 +128,7 @@ int warnif(const std::string& desc, const std::string& filename, int rc, int acc
if (errn != accept)
{
LL_WARNS("LLFile") << "Couldn't " << desc << " '" << filename
<< "' (errno " << errn << "): " << strerr(errn) << LL_ENDL;
<< "' (errno " << errn << "): " << LLFile::strerr(errn) << LL_ENDL;
}
#if 0 && LL_WINDOWS // turn on to debug file-locking problems
// If the problem is "Permission denied," maybe it's because another

View File

@@ -30,6 +30,9 @@
#ifndef LL_LLFILE_H
#define LL_LLFILE_H
#include <fstream>
#include <sys/stat.h>
/**
* This class provides a cross platform interface to the filesystem.
* Attempts to mostly mirror the POSIX style IO functions.
@@ -37,9 +40,6 @@
typedef FILE LLFILE;
#include <fstream>
#include <sys/stat.h>
#if LL_WINDOWS
// windows version of stat function and stat data structure are called _stat
typedef struct _stat llstat;
@@ -82,6 +82,9 @@ public:
std::ios::openmode mode);
static const char * tmpdir();
static std::string strerr(int errn);
static std::string strerr();
};
/**

View File

@@ -281,7 +281,12 @@ void LLMD5::raw_digest(unsigned char *s) const
return;
}
//Singu extension: the inverse of LLMD5::raw_digest.
void LLMD5::clone(unsigned char const* s)
{
memcpy(digest, s, 16);
finalized = 1;
}
void LLMD5::hex_digest(char *s) const
{
@@ -305,12 +310,26 @@ void LLMD5::hex_digest(char *s) const
return;
}
//Singu extension: the inverse of LLMD5::hex_digest.
void LLMD5::clone(std::string const& hash_str)
{
for (int i = 0; i < 16; ++i)
{
unsigned char byte = 0;
for (int j = 0; j < 2; ++j)
{
char c = hash_str[i * 2 + j];
unsigned char nibble = (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10;
byte += nibble << ((1 - j) << 2);
}
digest[i] = byte;
}
finalized = 1;
}
std::ostream& operator<<(std::ostream &stream, LLMD5 context)
std::ostream& operator<<(std::ostream &stream, LLMD5 const& context)
{
char s[33]; /* Flawfinder: ignore */
context.hex_digest(s);
@@ -318,23 +337,6 @@ std::ostream& operator<<(std::ostream &stream, LLMD5 context)
return stream;
}
bool operator==(const LLMD5& a, const LLMD5& b)
{
unsigned char a_guts[16];
unsigned char b_guts[16];
a.raw_digest(a_guts);
b.raw_digest(b_guts);
if (memcmp(a_guts,b_guts,16)==0)
return true;
else
return false;
}
bool operator!=(const LLMD5& a, const LLMD5& b)
{
return !(a==b);
}
// PRIVATE METHODS:
void LLMD5::init(){

View File

@@ -32,6 +32,10 @@
#ifndef LL_LLMD5_H
#define LL_LLMD5_H
#include "llpreprocessor.h"
#include <iosfwd>
#include <cstring> // memcmp
// LLMD5.CC - source code for the C++/object oriented translation and
// modification of MD5.
@@ -98,18 +102,27 @@ public:
void update (const std::string& str);
void finalize ();
bool isFinalized() const { return finalized; }
// constructors for special circumstances. All these constructors finalize
// the MD5 context.
LLMD5 (const unsigned char *string); // digest string, finalize
LLMD5 (std::istream& stream); // digest stream, finalize
LLMD5 (FILE *file); // digest file, close, finalize
LLMD5 (const unsigned char *string, const unsigned int number);
// Singu extension: set digest directly, finalize.
void clone(unsigned char const* digest); // Inverse of raw_digest.
void clone(std::string const& hash_str); // Inverse of hex_digest.
// methods to acquire finalized result
void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data
void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string
friend LL_COMMON_API std::ostream& operator<< (std::ostream&, LLMD5 context);
friend LL_COMMON_API std::ostream& operator<< (std::ostream&, LLMD5 const& context);
friend LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b) { return std::memcmp(a.digest ,b.digest, 16) == 0; }
friend LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b) { return std::memcmp(a.digest ,b.digest, 16) != 0; }
friend LL_COMMON_API bool operator<(const LLMD5& a, const LLMD5& b) { return std::memcmp(a.digest ,b.digest, 16) < 0; }
private:
@@ -131,7 +144,4 @@ private:
};
LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b);
LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b);
#endif // LL_LLMD5_H

View File

@@ -27,6 +27,9 @@
#define LLREFCOUNT_H
#include <boost/noncopyable.hpp>
#include "llpreprocessor.h" // LL_COMMON_API
#include "stdtypes.h" // S32
#include "llerror.h" // llassert
#define LL_REF_COUNT_DEBUG 0
#if LL_REF_COUNT_DEBUG

View File

@@ -37,6 +37,8 @@
#include <vector>
#include <boost/shared_ptr.hpp>
#include "llpreprocessor.h"
#include "stdtypes.h"
class LLRunnable;

View File

@@ -27,6 +27,7 @@
#include "llerror.h" // *TODO: eliminate this
#include <map>
#include <typeinfo>
#include <boost/noncopyable.hpp>

View File

@@ -231,7 +231,9 @@ public:
operator std::string() const { return mString; }
bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; }
std::size_t length() const { return mString.length(); }
// The destructor may not throw.
~LLFormatMapString() throw() { }
private:
std::string mString;
};

View File

@@ -28,6 +28,7 @@
#include <iostream>
#include <set>
#include <vector>
#include "stdtypes.h"
#include "llpreprocessor.h"

View File

@@ -40,6 +40,7 @@
#include "lltrans.h"
#include "llnotifications.h"
#include "aialert.h"
#include "../newview/hippogridmanager.h"
@@ -1479,6 +1480,32 @@ LLNotificationPtr LLNotifications::add(const LLNotification::Params& p)
return pNotif;
}
LLNotificationPtr LLNotifications::add(AIAlert::Error const& error, int type, unsigned int suppress_mask)
{
std::string alert_text;
bool suppress_newlines = false;
bool last_was_prefix = false;
for (AIAlert::Error::lines_type::const_iterator line = error.lines().begin(); line != error.lines().end(); ++line)
{
// Even if a line is suppressed, we print its leading newline if requested, but never more than one.
if (!suppress_newlines && line->prepend_newline())
{
alert_text += '\n';
suppress_newlines = true;
}
if (!line->suppressed(suppress_mask))
{
if (last_was_prefix) alert_text += ' '; // The translation system strips off spaces... add them back.
alert_text += LLTrans::getString(line->getXmlDesc(), line->args());
suppress_newlines = false;
last_was_prefix = line->is_prefix();
}
}
LLSD substitutions = LLSD::emptyMap();
substitutions["[PAYLOAD]"] = alert_text;
return add(LLNotification::Params((type == AIAlert::modal || error.is_modal()) ? "AIAlertModal" : "AIAlert").substitutions(substitutions));
}
void LLNotifications::add(const LLNotificationPtr pNotif)
{

View File

@@ -108,6 +108,8 @@
#include "llnotificationptr.h"
#include "llnotificationcontext.h"
namespace AIAlert { class Error; }
typedef enum e_notification_priority
{
NOTIFICATION_PRIORITY_UNSPECIFIED,
@@ -737,6 +739,7 @@ public:
const LLSD& substitutions,
const LLSD& payload,
LLNotificationFunctorRegistry::ResponseFunctor functor);
LLNotificationPtr add(AIAlert::Error const& error, int type, unsigned int suppress_mask);
LLNotificationPtr add(const LLNotification::Params& p);
void forceResponse(const LLNotification::Params& params, S32 option);

View File

@@ -30,6 +30,46 @@
#include "llsd.h"
#include "llxmlnode.h" // apparently needed to call LLNotifications::instance()
namespace AIAlert
{
LLNotificationPtr add(Error const& error, modal_nt type, unsigned int suppress_mask)
{
return LLNotifications::instance().add(error, type, suppress_mask);
}
LLNotificationPtr add(std::string const& xml_desc, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, xml_desc, AIArgs()), type, 0);
}
LLNotificationPtr add(std::string const& xml_desc, AIArgs const& args, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, xml_desc, args), type, 0);
}
LLNotificationPtr add(Error const& error, std::string const& xml_desc, unsigned int suppress_mask, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, error, xml_desc, AIArgs()), type, suppress_mask);
}
LLNotificationPtr add(Error const& error, std::string const& xml_desc, AIArgs const& args, unsigned int suppress_mask, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, error, xml_desc, args), type, suppress_mask);
}
LLNotificationPtr add(std::string const& xml_desc, Error const& error, unsigned int suppress_mask, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, xml_desc, AIArgs(), error), type, suppress_mask);
}
LLNotificationPtr add(std::string const& xml_desc, AIArgs const& args, Error const& error, unsigned int suppress_mask, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, xml_desc, args, error), type, suppress_mask);
}
} // namespace AIAlert
LLNotificationPtr LLNotificationsUtil::add(const std::string& name)
{
return LLNotifications::instance().add(

View File

@@ -30,11 +30,51 @@
// to avoid including the heavyweight llnotifications.h
#include "llnotificationptr.h"
#include "aialert.h"
#include <boost/function.hpp>
class LLSD;
namespace AIAlert
{
// Add an alert directly to LLNotifications.
// Look up xml_desc in strings.xml.
LLNotificationPtr add(std::string const& xml_desc,
modal_nt type = not_modal);
// ... with replacement args.
LLNotificationPtr add(std::string const& xml_desc, AIArgs const& args,
modal_nt type = not_modal);
// Append it to an existing alert error.
LLNotificationPtr add(Error const& error,
std::string const& xml_desc,
unsigned int suppress_mask = 0, modal_nt type = not_modal);
LLNotificationPtr add(Error const& error,
std::string const& xml_desc, AIArgs const& args,
unsigned int suppress_mask = 0, modal_nt type = not_modal);
// Prepend it to an existing alert error.
LLNotificationPtr add(std::string const& xml_desc,
Error const& error,
unsigned int suppress_mask = 0, modal_nt type = not_modal);
LLNotificationPtr add(std::string const& xml_desc, AIArgs const& args,
Error const& error,
unsigned int suppress_mask = 0, modal_nt type = not_modal);
// Just show the caught alert error.
LLNotificationPtr add(Error const& error,
modal_nt type = not_modal, unsigned int suppress_mask = 0);
// Short cuts for enforcing modal alerts.
inline LLNotificationPtr add_modal(std::string const& xml_desc) { return add(xml_desc, modal); }
inline LLNotificationPtr add_modal(std::string const& xml_desc, AIArgs const& args) { return add(xml_desc, args, modal); }
inline LLNotificationPtr add_modal(Error const& error, std::string const& xml_desc, unsigned int suppress_mask = 0) { return add(error, xml_desc, suppress_mask, modal); }
inline LLNotificationPtr add_modal(Error const& error, std::string const& xml_desc, AIArgs const& args, unsigned int suppress_mask = 0) { return add(error, xml_desc, args, suppress_mask, modal); }
inline LLNotificationPtr add_modal(std::string const& xml_desc, Error const& error, unsigned int suppress_mask = 0) { return add(xml_desc, error, suppress_mask, modal); }
inline LLNotificationPtr add_modal(std::string const& xml_desc, AIArgs const& args, Error const& error, unsigned int suppress_mask = 0) { return add(xml_desc, args, error, suppress_mask, modal); }
}
namespace LLNotificationsUtil
{
LLNotificationPtr add(const std::string& name);

View File

@@ -13,6 +13,7 @@ include_directories(
)
set(llxml_SOURCE_FILES
aixml.cpp
llcontrol.cpp
llxmlnode.cpp
llxmlparser.cpp
@@ -22,6 +23,7 @@ set(llxml_SOURCE_FILES
set(llxml_HEADER_FILES
CMakeLists.txt
aixml.h
llcontrol.h
llcontrolgroupreader.h
llxmlnode.h

609
indra/llxml/aixml.cpp Normal file
View File

@@ -0,0 +1,609 @@
/**
* @file aixml.cpp
* @brief XML serialization support.
*
* Copyright (c) 2013, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 30/07/2013
* Initial version, written by Aleric Inglewood @ SL
*/
#include "sys.h"
#include "aixml.h"
#include "llmd5.h"
#include <boost/tokenizer.hpp>
#include "aifile.h"
//=============================================================================
// Overview
// The AIXML* classes provide an Object Oriented way to serialize objects
// to and from an XML file.
//
// The following classes are provided:
//
// AIXMLRootElement - Write an object to a file (including XML declaration at the top).
// AIXMLElement - Write an ojbect to an ostream (just one XML element).
//
// AIXMLParser - Read and deserialize an XML file written with AIXMLRootElement.
// AIXMLElementParser - Read and deserialize an XML stream written with AIXMLElement.
//
// Classes that need to be written to and from XML would typically
// supply two member functions. For example,
#ifdef EXAMPLE_CODE // undefined
class HelloWorld {
public:
// Write object to XML.
void toXML(std::ostream& os, int indentation) const;
// Read object from XML.
HelloWorld(AIXMLElementParser const& parser);
private:
// Example member variables...
Attribute1 mAttribute1;
Attribute2 mAttribute2;
// etc.
Custom1 mCustom;
std::vector<Custom2> mContainer;
LLDate mDate;
LLMD5 mMd5;
LLUUID mUUID;
};
// Typical serialization member function.
void HelloWorld::toXML(std::ostream& os, int indentation) const
{
AIXMLElement tag(os, "helloworld", indentation);
// Zero or more attributes:
tag.attribute("attributename1", mAttribute1); // Uses operator<<(std::ostream&, Attribute1 const&) to write mAttribute1.
tag.attribute("attributename2", mAttribute2); // Uses operator<<(std::ostream&, Attribute2 const&) to write mAttribute2.
// etc.
// Zero or more child elements:
tag.child("tagname", mChild1);
tag.child(mCustom); // Calls mCustom.toXML() to insert the object.
tag.child(mContainer.begin(), mContainer.end()); // Calls tag.child(element) for each element of the container.
// Special allowed cases:
tag.child(mDate); // Uses "date" as tag name.
tag.child(mMd5); // Uses "md5" as tag name.
tag.child(mUUID); // Uses "uuid" as tag name.
}
// Typical deserialization member function.
HelloWorld::HelloWorld(AIXMLElementParser const& parser)
{
// Zero or more attributes:
parser.attribute("attributename1", "foobar"); // Throws std::runtime_error is attributename1 is missing or does not have the value "foobar".
if (!parser.attribute("attributename2", mAttribute2)) // Reads value of attributename2 into mAttribute2 (throws if it could not be parsed).
{
throw std::runtime_error("..."); // Attribute was missing.
}
// Zero or more child elements:
parser.child("tagname", mChild1);
parser.child("custom1", mCustom);
parser.insert_children("custom2", mContainer);
// Special allowed cases:
parser.child(mDate);
parser.child(mMd5);
parser.child(mUUID);
}
// To actually write to an XML file one would do, for example:
LLFILE* fp = fopen(...);
AIXMLRootElement tag(fp, "rootname");
tag.attribute("version", "1.0");
tag.child(LLDate::now());
tag.child(mHelloWorld);
// And to read it again,
AIXMLParser helloworld(filename, "description of file used for error reporting", "rootname", 1);
helloworld.attribute("version", "1.0");
helloworld.child("helloworld", mHelloWorld);
// Of course, both would need to be in a try { } catch block.
#endif // EXAMPLE_CODE
// Do NOT change these - it would break old databases.
char const* const DEFAULT_LLUUID_NAME = "uuid";
char const* const DEFAULT_MD5STR_NAME = "md5";
char const* const DEFAULT_LLDATE_NAME = "date";
std::string const DEFAULT_MD5STR_ATTRIBUTE_NAME = DEFAULT_MD5STR_NAME;
std::string const DEFAULT_LLUUID_ATTRIBUTE_NAME = DEFAULT_LLUUID_NAME;
std::string const DEFAULT_LLDATE_ATTRIBUTE_NAME = DEFAULT_LLDATE_NAME;
std::string const DEFAULT_VERSION_ATTRIBUTE_NAME = "version";
struct xdigit {
bool isxdigit;
xdigit(void) : isxdigit(true) { }
void operator()(char c) { isxdigit = isxdigit && std::isxdigit(c); }
operator bool() const { return isxdigit; }
};
static bool is_valid_md5str(std::string const& str)
{
return str.length() == MD5HEX_STR_BYTES && std::for_each(str.begin(), str.end(), xdigit());
}
// Conversion routine that is a lot more strict then LLStringUtil::convertToU32.
// This version does not allow leading or trailing spaces, nor does it allow a leading minus sign.
// Leading zeroes are not allowed except a 0 by itself.
bool convertToU32strict(std::string const& str, U32& value)
{
bool first = true;
value = 0;
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
{
if (value == 0 && !first || !std::isdigit(*i)) // Reject leading zeroes and non-digits.
return false;
value = value * 10 + *i - '0';
first = false;
}
return !first; // Reject empty string.
}
typedef boost::tokenizer<boost::char_separator<char> > boost_tokenizer;
bool decode_version(std::string const& version, U32& major, U32& minor)
{
boost_tokenizer tokens(version, boost::char_separator<char>("", "."));
boost_tokenizer::const_iterator itTok = tokens.begin();
return itTok != tokens.end() && convertToU32strict(*itTok++, major) &&
itTok != tokens.end() && *itTok++ == "." &&
itTok != tokens.end() && convertToU32strict(*itTok, minor);
}
bool md5strFromXML(LLXmlTreeNode* node, std::string& md5str_out)
{
static LLStdStringHandle const DEFAULT_MD5STR_ATTRIBUTE_NAME_HANDLE = LLXmlTree::addAttributeString(DEFAULT_MD5STR_ATTRIBUTE_NAME);
return node->getFastAttributeString(DEFAULT_MD5STR_ATTRIBUTE_NAME_HANDLE, md5str_out) && is_valid_md5str(md5str_out);
}
bool md5strFromXML(LLXmlTreeNode* node, std::string& md5str_out, std::string const& attribute_name)
{
return node->getAttributeString(attribute_name, md5str_out) && is_valid_md5str(md5str_out);
}
bool UUIDFromXML(LLXmlTreeNode* node, LLUUID& uuid_out)
{
static LLStdStringHandle const DEFAULT_LLUUID_ATTRIBUTE_NAME_HANDLE = LLXmlTree::addAttributeString(DEFAULT_LLUUID_ATTRIBUTE_NAME);
return node->getFastAttributeUUID(DEFAULT_LLUUID_ATTRIBUTE_NAME_HANDLE, uuid_out);
}
bool UUIDFromXML(LLXmlTreeNode* node, LLUUID& uuid_out, std::string const& attribute_name)
{
return node->getAttributeUUID(attribute_name, uuid_out);
}
bool dateFromXML(LLXmlTreeNode* node, LLDate& date_out)
{
static LLStdStringHandle const DEFAULT_LLDATE_ATTRIBUTE_NAME_HANDLE = LLXmlTree::addAttributeString(DEFAULT_LLDATE_ATTRIBUTE_NAME);
std::string date_s;
return node->getFastAttributeString(DEFAULT_LLDATE_ATTRIBUTE_NAME_HANDLE, date_s) && date_out.fromString(date_s);
}
bool dateFromXML(LLXmlTreeNode* node, LLDate& date_out, std::string const& attribute_name)
{
std::string date_s;
return node->getAttributeString(attribute_name, date_s) && date_out.fromString(date_s);
}
bool versionFromXML(LLXmlTreeNode* node, U32& major_out, U32& minor_out)
{
static LLStdStringHandle const DEFAULT_VERSION_ATTRIBUTE_NAME_HANDLE = LLXmlTree::addAttributeString(DEFAULT_VERSION_ATTRIBUTE_NAME);
major_out = minor_out = 0;
std::string version_s;
return node->getFastAttributeString(DEFAULT_VERSION_ATTRIBUTE_NAME_HANDLE, version_s) && decode_version(version_s, major_out, minor_out);
}
bool versionFromXML(LLXmlTreeNode* node, U32& major_out, U32& minor_out, std::string const& attribute_name)
{
major_out = minor_out = 0;
std::string version_s;
return node->getAttributeString(attribute_name, version_s) && decode_version(version_s, major_out, minor_out);
}
//-----------------------------------------------------------------------------
// AIXMLElement
AIXMLElement::AIXMLElement(std::ostream& os, char const* name, int indentation) :
mOs(os), mName(name), mIndentation(indentation), mHasChildren(false)
{
mOs << std::string(mIndentation, ' ') << '<' << mName;
if (!mOs.good())
{
THROW_ALERT("AIXMLElement_Failed_to_write_DATA", AIArgs("[DATA]", "<" + mName));
}
}
int AIXMLElement::open_child(void)
{
if (!mHasChildren)
{
mOs << ">\n";
if (!mOs.good())
{
THROW_ALERT("AIXMLElement_closing_child_Failed_to_write_DATA", AIArgs("[DATA]", ">\\n"));
}
mHasChildren = true;
}
mIndentation += 2;
return mIndentation;
}
void AIXMLElement::close_child(void)
{
mIndentation -= 2;
}
AIXMLElement::~AIXMLElement()
{
if (mHasChildren)
{
mOs << std::string(mIndentation, ' ') << "</" << mName << ">\n";
if (!mOs.good())
{
THROW_ALERT("AIXMLElement_closing_child_Failed_to_write_DATA",
AIArgs("[DATA]", "\\n" + std::string(mIndentation, ' ') + "</" + mName + ">\\n"));
}
}
else
{
mOs << " />\n";
if (!mOs.good())
{
THROW_ALERT("AIXMLElement_closing_child_Failed_to_write_DATA", AIArgs("[DATA]", " />\\n"));
}
}
}
template<>
void AIXMLElement::child(LLUUID const& element)
{
open_child();
write_child(DEFAULT_LLUUID_NAME, element);
close_child();
}
template<>
void AIXMLElement::child(LLMD5 const& element)
{
open_child();
write_child(DEFAULT_MD5STR_NAME, element);
close_child();
}
template<>
void AIXMLElement::child(LLDate const& element)
{
open_child();
write_child(DEFAULT_LLDATE_NAME, element);
close_child();
}
//-----------------------------------------------------------------------------
// AIXMLStream
AIXMLStream::AIXMLStream(LLFILE* fp, bool standalone) : mOfs(fp)
{
char const* sp = standalone ? " standalone=\"yes\"" : "";
int rc = fprintf(fp, "<?xml version=\"1.0\" encoding=\"utf-8\"%s ?>\n", sp);
if (rc < 0 || ferror(fp))
{
// I don't think that errno is set to anything else but EBADF here,
// so there is not really any informative message to add here.
THROW_MALERT("AIXMLStream_fprintf_failed_to_write_xml_header");
}
}
AIXMLStream::~AIXMLStream()
{
if (mOfs.is_open())
{
mOfs.close();
}
}
//-----------------------------------------------------------------------------
// AIXMLParser
AIXMLParser::AIXMLParser(std::string const& filename, char const* file_desc, std::string const& name, U32 major_version) :
AIXMLElementParser(mFilename, mFileDesc, major_version),
mFilename(filename), mFileDesc(file_desc)
{
char const* error = NULL;
AIArgs args;
if (!mXmlTree.parseFile(filename, TRUE))
{
AIFile dummy(filename, "rb"); // Check if the file can be opened at all (throws with a more descriptive error if not).
error = "AIXMLParser_Cannot_parse_FILEDESC_FILENAME";
}
else
{
mNode = mXmlTree.getRoot();
if (!mNode)
{
error = "AIXMLParser_No_root_node_found_in_FILEDESC_FILENAME";
}
else if (!mNode->hasName(name))
{
error = "AIXMLParser_Missing_header_NAME_invalid_FILEDESC_FILENAME";
args("[NAME]", name);
}
else if (!versionFromXML(mNode, mVersionMajor, mVersionMinor))
{
error = "AIXMLParser_Invalid_or_missing_NAME_version_attribute_in_FILEDESC_FILENAME";
args("[NAME]", name);
}
else if (mVersionMajor != major_version)
{
error = "AIXMLParser_Incompatible_NAME_version_MAJOR_MINOR_in";
args("[NAME]", name)("[MAJOR]", llformat("%u", mVersionMajor))("[MINOR]", llformat("%u", mVersionMinor));
}
}
if (error)
{
THROW_MALERT(error, args("[FILEDESC]", mFileDesc)("[FILENAME]", mFilename));
}
}
//-----------------------------------------------------------------------------
// AIXMLElementParser
template<>
LLMD5 AIXMLElementParser::read_string(std::string const& value) const
{
if (!is_valid_md5str(value))
{
THROW_MALERT("AIXMLElementParser_read_string_Invalid_MD5_VALUE_in_FILEDESC_FILENAME",
AIArgs("[VALUE]", value)("[FILEDESC]", mFileDesc)("[FILENAME]", mFilename));
}
unsigned char digest[16];
std::memset(digest, 0, sizeof(digest));
for (int i = 0; i < 32; ++i)
{
int x = value[i];
digest[i >> 1] += (x - (x & 0xf0) + (x >> 6) * 9) << ((~i & 1) << 2);
}
LLMD5 result;
result.clone(digest);
return result;
}
template<>
LLDate AIXMLElementParser::read_string(std::string const& value) const
{
LLDate result;
result.fromString(value);
return result;
}
template<typename T>
T AIXMLElementParser::read_integer(char const* type, std::string const& value) const
{
long long int result;
sscanf(value.c_str(),"%lld", &result);
if (result < std::numeric_limits<T>::min() || result > std::numeric_limits<T>::max())
{
THROW_MALERT("AIXMLElementParser_read_integer_Invalid_TYPE_VALUE_in_FILEDESC_FILENAME",
AIArgs("[TYPE]", type)("[VALUE]", value)("FILEDESC", mFileDesc)("[FILENAME]", mFilename));
}
return result;
}
template<>
U8 AIXMLElementParser::read_string(std::string const& value) const
{
return read_integer<U8>("U8", value);
}
template<>
S8 AIXMLElementParser::read_string(std::string const& value) const
{
return read_integer<S8>("S8", value);
}
template<>
U16 AIXMLElementParser::read_string(std::string const& value) const
{
return read_integer<U16>("U16", value);
}
template<>
S16 AIXMLElementParser::read_string(std::string const& value) const
{
return read_integer<S16>("S16", value);
}
template<>
U32 AIXMLElementParser::read_string(std::string const& value) const
{
return read_integer<U32>("U32", value);
}
template<>
S32 AIXMLElementParser::read_string(std::string const& value) const
{
return read_integer<S32>("S32", value);
}
double read_float(std::string const& value)
{
double result;
sscanf(value.c_str(),"%lf", &result);
return result;
}
template<>
F32 AIXMLElementParser::read_string(std::string const& value) const
{
return read_float(value);
}
template<>
F64 AIXMLElementParser::read_string(std::string const& value) const
{
return read_float(value);
}
template<>
bool AIXMLElementParser::read_string(std::string const& value) const
{
if (value == "true")
{
return true;
}
else if (value != "false")
{
THROW_MALERT("AIXMLElementParser_read_string_Invalid_boolean_VALUE_in_FILEDESC_FILENAME",
AIArgs("[VALUE]", value)("FILEDESC]", mFileDesc)("[FILENAME]", mFilename));
}
return false;
}
void AIXMLElementParser::attribute(char const* name, char const* required_value) const
{
char const* error = NULL;
AIArgs args;
std::string value;
if (!mNode->getAttributeString(name, value))
{
error = "AIXMLElementParser_attribute_Missing_NAME_attribute_in_NODENAME_of_FILEDESC_FILENAME";
}
else if (value != required_value)
{
error = "AIXMLElementParser_attribute_Invalid_NAME_attribute_should_be_REQUIRED_in_NODENAME_of_FILEDESC_FILENAME";
args("[REQUIRED]", required_value);
}
if (error)
{
THROW_MALERT(error, args("[NAME]", name)("[NODENAME]", node_name())("[FILEDESC]", mFileDesc)("[FILENAME]", mFilename));
}
}
template<>
LLUUID AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
LLUUID result;
if (!LLUUID::parseUUID(node->getContents(), &result))
{
THROW_MALERT("AIXMLElementParser_read_child_Invalid_uuid_in_FILEDESC_FILENAME",
AIArgs("[FILEDESC]", mFileDesc)("[FILENAME]", mFilename));
}
return result;
}
template<>
LLMD5 AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_string<LLMD5>(node->getContents());
}
template<>
LLDate AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
LLDate result;
if (!result.fromString(node->getContents()))
{
THROW_MALERT("AIXMLElementParser_read_child_Invalid_date_DATE_in_FILEDESC_FILENAME",
AIArgs("[DATE]", node->getContents())("[FILEDESC]", mFileDesc)("[FILENAME]", mFilename));
}
return result;
}
template<>
S8 AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_integer<S8>("S8", node->getContents());
}
template<>
U8 AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_integer<U8>("U8", node->getContents());
}
template<>
S16 AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_integer<S16>("S16", node->getContents());
}
template<>
U16 AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_integer<U16>("U16", node->getContents());
}
template<>
S32 AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_integer<S32>("S32", node->getContents());
}
template<>
U32 AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_integer<U32>("U32", node->getContents());
}
template<>
F32 AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_string<F32>(node->getContents());
}
template<>
F64 AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_string<F64>(node->getContents());
}
template<>
bool AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return read_string<bool>(node->getContents());
}
bool AIXMLElementParser::child(LLUUID& uuid) const
{
return child(DEFAULT_LLUUID_NAME, uuid);
}
bool AIXMLElementParser::child(LLMD5& md5) const
{
return child(DEFAULT_MD5STR_NAME, md5);
}
bool AIXMLElementParser::child(LLDate& date) const
{
return child(DEFAULT_LLDATE_NAME, date);
}

374
indra/llxml/aixml.h Normal file
View File

@@ -0,0 +1,374 @@
/**
* @file aixml.h
* @brief XML serialization support.
*
* Copyright (c) 2013, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 30/07/2013
* Initial version, written by Aleric Inglewood @ SL
*/
#ifndef AIXML_H
#define AIXML_H
#include "llxmltree.h"
#include "llxmlnode.h"
#include "llfile.h"
#include <sstream>
#include "aialert.h"
extern char const* const DEFAULT_LLUUID_NAME;
extern char const* const DEFAULT_MD5STR_NAME;
extern char const* const DEFAULT_LLDATE_NAME;
class LLUUID;
class LLMD5;
class LLDate;
bool md5strFromXML(LLXmlTreeNode* node, std::string& md5str_out);
bool md5strFromXML(LLXmlTreeNode* node, std::string& md5str_out, std::string const& attribute_name);
bool UUIDFromXML(LLXmlTreeNode* node, LLUUID& uuid_out);
bool UUIDFromXML(LLXmlTreeNode* node, LLUUID& uuid_out, std::string const& attribute_name);
bool dateFromXML(LLXmlTreeNode* node, LLDate& date_out);
bool dateFromXML(LLXmlTreeNode* node, LLDate& date_out, std::string const& attribute_name);
bool versionFromXML(LLXmlTreeNode* node, U32& major_out, U32& minor_out);
bool versionFromXML(LLXmlTreeNode* node, U32& major_out, U32& minor_out, std::string const& attribute_name);
class AIXMLElement
{
private:
std::ostream& mOs;
std::string mName;
int mIndentation;
bool mHasChildren;
public:
AIXMLElement(std::ostream& os, char const* name, int indentation);
~AIXMLElement();
template<typename T>
void attribute(char const* name, T const& attribute);
template<typename T>
void child(T const& element);
template<typename T>
void child(char const* name, T const& element);
template<typename FWD_ITERATOR>
void child(FWD_ITERATOR i1, FWD_ITERATOR const& i2);
private:
template<typename T>
void write_child(char const* name, T const& element);
int open_child(void);
void close_child(void);
};
template<typename T>
void AIXMLElement::attribute(char const* name, T const& attribute)
{
std::ostringstream raw_attribute;
raw_attribute << attribute;
mOs << ' ' << name << "=\"" << LLXMLNode::escapeXML(raw_attribute.str()) << '"';
if (!mOs.good())
{
std::ostringstream ss;
ss << ' ' << name << "=\"" << LLXMLNode::escapeXML(raw_attribute.str()) << '"';
THROW_FALERT("AIXMLElement_attribute_Failed_to_write_DATA", AIArgs("[DATA]", ss.str()));
}
}
template<typename T>
void AIXMLElement::child(T const& element)
{
open_child();
element.toXML(mOs, mIndentation);
if (!mOs.good()) // Normally toXML will already have thrown.
{
THROW_FALERT("AIXMLElement_child_Bad_ostream");
}
close_child();
}
template<>
void AIXMLElement::child(LLUUID const& element);
template<>
void AIXMLElement::child(LLMD5 const& element);
template<>
void AIXMLElement::child(LLDate const& element);
template<typename T>
void AIXMLElement::write_child(char const* name, T const& element)
{
mOs << std::string(mIndentation, ' ') << '<' << name << '>' << element << "</" << name << ">\n";
if (!mOs.good())
{
std::ostringstream ss;
ss << std::string(mIndentation, ' ') << '<' << name << '>' << element << "</" << name << ">\\n";
THROW_FALERT("AIXMLElement_write_child_Failed_to_write_DATA", AIArgs("[DATA]", ss.str()));
}
}
template<typename T>
void AIXMLElement::child(char const* name, T const& element)
{
open_child();
write_child(name, element);
close_child();
}
template<typename FWD_ITERATOR>
void AIXMLElement::child(FWD_ITERATOR i1, FWD_ITERATOR const& i2)
{
while (i1 != i2)
{
child(*i1++);
}
}
// Helper class for AIXMLRootElement.
class AIXMLStream {
protected:
llofstream mOfs;
AIXMLStream(LLFILE* fp, bool standalone);
~AIXMLStream();
};
// Class to write XML files.
class AIXMLRootElement : public AIXMLStream, public AIXMLElement
{
public:
AIXMLRootElement(LLFILE* fp, char const* name, bool standalone = true) : AIXMLStream(fp, standalone), AIXMLElement(mOfs, name, 0) { }
};
class AIXMLElementParser
{
private:
U32 mVersion;
std::string const& mFilename;
std::string const& mFileDesc;
protected:
LLXmlTreeNode* mNode;
protected:
// Used by AIXMLParser, which initializes mNode directly.
AIXMLElementParser(std::string const& filename, std::string const& file_desc, U32 version) : mVersion(version), mFilename(filename), mFileDesc(file_desc) { }
// Used for error reporting.
virtual std::string node_name(void) const { return "node '" + mNode->getName() + "'"; }
// Parse the integer given as string 'value' and return it as type T (U8, S8, U16, S16, U32 or S32).
template<typename T>
T read_integer(char const* type, std::string const& value) const;
// Parse the string 'value' and return it as type T.
template<typename T>
T read_string(std::string const& value) const;
// Parse a child node and return it as type T.
template<typename T>
T read_child(LLXmlTreeNode* node) const;
public:
// Constructor for child member functions.
AIXMLElementParser(std::string const& filename, std::string const& file_desc, U32 version, LLXmlTreeNode* node) : mVersion(version), mFilename(filename), mFileDesc(file_desc), mNode(node) { }
// Require the existence of some attribute with given value.
void attribute(char const* name, char const* required_value) const;
// Read attribute. Returns true if attribute was found.
template<typename T>
bool attribute(char const* name, T& attribute) const;
// Read child element. Returns true if child was found.
template<typename T>
bool child(char const* name, T& child) const;
// Read Linden types. Return true if the child was found.
bool child(LLUUID& uuid) const;
bool child(LLMD5& md5) const;
bool child(LLDate& date) const;
// Append all elements with name 'name' to container.
template<typename CONTAINER>
void push_back_children(char const* name, CONTAINER& container) const;
// Insert all elements with name 'name' into container.
template<typename CONTAINER>
void insert_children(char const* name, CONTAINER& container) const;
// Set version of this particular element (if not set mVersion will be the version of the parent, all the way up to the xml header with a version of 1).
void setVersion(U32 version) { mVersion = version; }
// Accessors.
std::string const& filename(void) const { return mFilename; }
std::string const& filedesc(void) const { return mFileDesc; }
U32 version(void) const { return mVersion; }
};
template<typename T>
inline T AIXMLElementParser::read_string(std::string const& value) const
{
// Construct from string.
return T(value);
}
// Specializations.
template<>
LLMD5 AIXMLElementParser::read_string(std::string const& value) const;
template<>
LLDate AIXMLElementParser::read_string(std::string const& value) const;
template<>
U8 AIXMLElementParser::read_string(std::string const& value) const;
template<>
S8 AIXMLElementParser::read_string(std::string const& value) const;
template<>
U16 AIXMLElementParser::read_string(std::string const& value) const;
template<>
S16 AIXMLElementParser::read_string(std::string const& value) const;
template<>
U32 AIXMLElementParser::read_string(std::string const& value) const;
template<>
S32 AIXMLElementParser::read_string(std::string const& value) const;
template<>
F32 AIXMLElementParser::read_string(std::string const& value) const;
template<>
F64 AIXMLElementParser::read_string(std::string const& value) const;
template<>
bool AIXMLElementParser::read_string(std::string const& value) const;
template<typename T>
bool AIXMLElementParser::attribute(char const* name, T& attribute) const
{
std::string value;
if (!mNode->getAttributeString(name, value))
{
return false;
}
attribute = read_string<T>(value);
return true;
}
template<typename T>
inline T AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return AIXMLElementParser(mFilename, mFileDesc, mVersion, node);
}
// Specializations.
template<>
inline std::string AIXMLElementParser::read_child(LLXmlTreeNode* node) const
{
return node->getContents();
}
template<>
LLMD5 AIXMLElementParser::read_child(LLXmlTreeNode* node) const;
template<>
LLUUID AIXMLElementParser::read_child(LLXmlTreeNode* node) const;
template<>
LLDate AIXMLElementParser::read_child(LLXmlTreeNode* node) const;
template<>
S32 AIXMLElementParser::read_child(LLXmlTreeNode* node) const;
template<>
F32 AIXMLElementParser::read_child(LLXmlTreeNode* node) const;
template<>
bool AIXMLElementParser::read_child(LLXmlTreeNode* node) const;
template<typename T>
bool AIXMLElementParser::child(char const* name, T& child) const
{
LLXmlTreeNode* node = mNode->getChildByName(name);
if (!node)
{
return false;
}
child = read_child<T>(node);
return true;
}
template<typename CONTAINER>
void AIXMLElementParser::insert_children(char const* name, CONTAINER& container) const
{
for (LLXmlTreeNode* node = mNode->getFirstChild(); node; node = mNode->getNextChild())
{
if (!node->hasName(name))
continue;
container.insert(read_child<typename CONTAINER::value_type>(node));
}
}
template<typename CONTAINER>
void AIXMLElementParser::push_back_children(char const* name, CONTAINER& container) const
{
for (LLXmlTreeNode* node = mNode->getFirstChild(); node; node = mNode->getNextChild())
{
if (!node->hasName(name))
continue;
container.push_back(read_child<typename CONTAINER::value_type>(node));
}
}
// Class to read XML files.
class AIXMLParser : public AIXMLElementParser
{
private:
std::string mFilename;
std::string mFileDesc;
LLXmlTree mXmlTree;
U32 mVersionMajor;
U32 mVersionMinor;
public:
AIXMLParser(std::string const& filename, char const* file_desc, std::string const& name, U32 major_version);
U32 version_major(void) const { return mVersionMajor; }
U32 version_minor(void) const { return mVersionMinor; }
protected:
/*virtual*/ std::string node_name(void) const { return "root node"; }
};
#endif // AIXML_H

View File

@@ -555,6 +555,36 @@ void XMLCALL EndXMLNode(void *userData,
node->setValue(value);
}
}
// Singu note: moved here from XMLData.
if (LLXMLNode::sStripEscapedStrings)
{
std::string value = node->getValue();
int len = value.length();
if (len > 1 && value[0] == '"' && value[len - 1] == '"')
{
// Special-case: Escaped string.
std::string unescaped_string;
for (S32 pos = 1; pos < len - 1; ++pos)
{
if (value[pos] == '\\' && value[pos + 1] == '\\')
{
unescaped_string += '\\';
++pos;
}
else if (value[pos] == '\\' && value[pos + 1] == '"')
{
unescaped_string += '"';
++pos;
}
else
{
unescaped_string += value[pos];
}
}
value += unescaped_string;
node->setValue(value);
}
}
}
void XMLCALL XMLData(void *userData,
@@ -563,6 +593,15 @@ void XMLCALL XMLData(void *userData,
{
LLXMLNode* current_node = (LLXMLNode *)userData;
std::string value = current_node->getValue();
#if 0
// Apparently also Lindens who write XML parsers can't read documentation.
// "A single block of contiguous text free of markup may still result in a sequence
// of calls to this handler. In other words, if you're searching for a pattern in
// the text, it may be split across calls to this handler."
// (http://sepp.oetiker.ch/expat-1.95.6-rs.SEPP/expat-1.95.6/doc/reference.html#XML_SetCharacterDataHandler)
//
// In other words, this is not guaranteed to work at all -- Aleric.
if (LLXMLNode::sStripEscapedStrings)
{
if (s[0] == '\"' && s[len-1] == '\"')
@@ -591,6 +630,7 @@ void XMLCALL XMLData(void *userData,
return;
}
}
#endif
value.append(std::string(s, len));
current_node->setValue(value);
}
@@ -928,12 +968,6 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,
return true;
}
// static
void LLXMLNode::writeHeaderToFile(LLFILE *out_file)
{
fprintf(out_file, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n");
}
void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent, bool use_type_decorations)
{
if (isFullyDefault())

View File

@@ -157,11 +157,6 @@ public:
static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector<std::string>& paths);
// Write standard XML file header:
// <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
static void writeHeaderToFile(LLFILE *out_file);
// Write XML to file with one attribute per line.
// XML escapes values as they are written.
void writeToFile(LLFILE *out_file, const std::string& indent = std::string(), bool use_type_decorations=true);

View File

@@ -82,6 +82,7 @@ include_directories(
set(viewer_SOURCE_FILES
NACLantispam.cpp
aihttpview.cpp
aixmllindengenepool.cpp
aoremotectrl.cpp
ascentfloatercontactgroups.cpp
ascentkeyword.cpp
@@ -599,6 +600,7 @@ set(viewer_HEADER_FILES
NACLantispam.h
aihttpview.h
aixmllindengenepool.h
aoremotectrl.h
ascentfloatercontactgroups.h
ascentkeyword.h

View File

@@ -0,0 +1,205 @@
/**
* @file aixmllindengenepool.cpp
* @brief XML linden_genepool serialization support.
*
* Copyright (c) 2013, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 01/11/2013
* Initial version, written by Aleric Inglewood @ SL
*/
// metaversion 1.0
// ===============
//
// Added as child of <linden_genepool>:
//
// <meta gridnick="secondlife" date="2013-07-16T16:49:00.40Z" />
//
// Optionally, as child of <archetype>, the following node may appear:
//
// <meta path="clothing/jackets" name="Purple jacket" description="A jacket with mainly the color purple" />
//
// Furthermore, metaversion 1.0 and higher allow the occurance of one or more <archetype> blocks.
// If this is used then it is strongly advised to use one <archetype> per wearable, so that
// the the <meta> node makes sense (it then refers to the wearable of that <archetype>).
//
// The reason for this clumsy way to link wearable to extra meta data is to stay
// compatible with the older format (no metaversion).
#include "sys.h"
#include "aixmllindengenepool.h"
#include "hippogridmanager.h"
#include "llvisualparam.h"
#include "llviewerwearable.h"
#include "llquantize.h"
extern void append_path_short(LLUUID const& id, std::string& path);
void AIXMLLindenGenepool::MetaData::toXML(std::ostream& os, int indentation) const
{
AIXMLElement tag(os, "meta", indentation);
tag.attribute("gridnick", mGridNick);
tag.attribute(DEFAULT_LLDATE_NAME, mDate);
}
AIXMLLindenGenepool::MetaData::MetaData(AIXMLElementParser const& parser)
{
parser.attribute("gridnick", mGridNick);
parser.attribute(DEFAULT_LLDATE_NAME, mDate);
}
AIXMLLindenGenepool::AIXMLLindenGenepool(LLFILE* fp) : AIXMLRootElement(fp, "linden_genepool")
{
attribute("version", "1.0");
attribute("metaversion", "1.0");
child(MetaData(gHippoGridManager->getConnectedGrid()->getGridNick(), LLDate::now()));
}
void AIVisualParamIDValuePair::toXML(std::ostream& os, int indentation) const
{
LLVisualParam const* visual_param = mVisualParam;
if (!visual_param && mWearable)
{
visual_param = mWearable->getVisualParam(mID);
}
if (visual_param)
{
AIXMLElement tag(os, "param", indentation);
tag.attribute("id", mID);
tag.attribute("name", visual_param->getName());
tag.attribute("value", mValue);
tag.attribute("u8", (U32)F32_to_U8(mValue, visual_param->getMinWeight(), visual_param->getMaxWeight()));
tag.attribute("type", visual_param->getTypeString());
tag.attribute("wearable", visual_param->getDumpWearableTypeName());
}
}
AIVisualParamIDValuePair::AIVisualParamIDValuePair(AIXMLElementParser const& parser)
{
// Only id and value are relevant. Ignore all other attributes.
parser.attribute("id", mID);
parser.attribute("value", mValue);
}
void AITextureIDUUIDPair::toXML(std::ostream& os, int indentation) const
{
AIXMLElement tag(os, "texture", indentation);
tag.attribute("te", mID);
tag.attribute(DEFAULT_LLUUID_NAME, mUUID);
}
AITextureIDUUIDPair::AITextureIDUUIDPair(AIXMLElementParser const& parser)
{
parser.attribute("te", mID);
parser.attribute(DEFAULT_LLUUID_NAME, mUUID);
}
void AIArchetype::MetaData::toXML(std::ostream& os, int indentation) const
{
AIXMLElement tag(os, "meta", indentation);
tag.attribute("path", mPath);
tag.attribute("name", mName);
tag.attribute("description", mDescription);
}
AIArchetype::MetaData::MetaData(AIXMLElementParser const& parser)
{
char const* missing = NULL;
if (!parser.attribute("path", mPath))
{
missing = "path";
}
if (!parser.attribute("name", mName))
{
missing = "name";
}
if (!parser.attribute("description", mDescription))
{
missing = "description";
}
if (missing)
{
THROW_ALERT("AIArchetype_MetaData_archetype_meta_has_no_ATTRIBUTE", AIArgs("[ATTRIBUTE]", missing));
}
}
AIArchetype::MetaData::MetaData(LLViewerWearable const* wearable) : mName(wearable->getName()), mDescription(wearable->getDescription())
{
append_path_short(wearable->getItemID(), mPath);
}
AIArchetype::AIArchetype(void) : mType(LLWearableType::WT_NONE)
{
}
AIArchetype::AIArchetype(LLWearableType::EType type) : mType(type)
{
}
AIArchetype::AIArchetype(LLViewerWearable const* wearable) : mType(wearable->getType()), mMetaData(wearable)
{
}
void AIArchetype::toXML(std::ostream& os, int indentation) const
{
AIXMLElement tag(os, "archetype", indentation);
if (mType == LLWearableType::WT_NONE)
{
tag.attribute("name", "???");
}
else
{
tag.attribute("name", LLWearableType::getTypeName(mType));
}
if (!mMetaData.mPath.empty())
{
tag.child(mMetaData);
}
tag.child(mParams.begin(), mParams.end());
tag.child(mTextures.begin(), mTextures.end());
}
AIArchetype::AIArchetype(AIXMLElementParser const& parser)
{
std::string name;
mType = LLWearableType::WT_NONE;
if (!parser.attribute("name", name))
{
llwarns << "The <archetype> tag in file \"" << parser.filename() << "\" is missing the 'name' parameter." << llendl;
}
else if (name != "???")
{
mType = LLWearableType::typeNameToType(name);
}
if (parser.version() >= 1)
{
if (!parser.child("meta", mMetaData))
{
THROW_ALERT("AIArchetype_archetype_has_no_meta");
}
}
parser.push_back_children("param", mParams);
parser.push_back_children("texture", mTextures);
}

View File

@@ -0,0 +1,150 @@
/**
* @file aixmllindengenepool.h
* @brief XML linden_genepool serialization support.
*
* Copyright (c) 2013, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 01/11/2013
* Initial version, written by Aleric Inglewood @ SL
*/
#ifndef AIXMLLINDENGENEPOOL_H
#define AIXMLLINDENGENEPOOL_H
#include "aixml.h"
#include "llwearabletype.h"
#include "llviewervisualparam.h"
#include <vector>
class LLViewerWearable;
class AIXMLLindenGenepool : public AIXMLRootElement
{
public:
struct MetaData
{
std::string mGridNick;
LLDate mDate;
MetaData(void) { }
MetaData(std::string const& grid_nick, LLDate const& date) : mGridNick(grid_nick), mDate(date) { }
void toXML(std::ostream& os, int indentation) const;
MetaData(AIXMLElementParser const& parser);
};
AIXMLLindenGenepool(LLFILE* fp);
};
class AIVisualParamIDValuePair
{
private:
// A wearable + ID define the LLVisualParam, but it also possible to specify the LLVisualParam directly.
LLVisualParam const* mVisualParam; // Specific LLVisualParam, given at construction, or ...
LLViewerWearable const* mWearable; // Underlaying wearable, if any.
U32 mID; // The visual parameter id.
F32 mValue; // The value of the visual parameter.
public:
AIVisualParamIDValuePair(LLVisualParam const* visual_param) :
mVisualParam(visual_param), mWearable(NULL), mID(visual_param->getID()), mValue(visual_param->getWeight()) { }
AIVisualParamIDValuePair(LLVisualParam const* visual_param, F32 value) :
mVisualParam(visual_param), mWearable(NULL), mID(visual_param->getID()), mValue(value) { }
AIVisualParamIDValuePair(LLViewerWearable const* wearable, U32 id, F32 value) :
mVisualParam(NULL), mWearable(wearable), mID(id), mValue(value) { }
void toXML(std::ostream& os, int indentation) const;
AIVisualParamIDValuePair(AIXMLElementParser const& parser);
// Accessors.
U32 getID(void) const { return mID; }
F32 getValue(void) const { return mValue; }
};
class AITextureIDUUIDPair
{
private:
U32 mID;
LLUUID mUUID;
public:
AITextureIDUUIDPair(U32 id, LLUUID const& uuid) : mID(id), mUUID(uuid) { }
void toXML(std::ostream& os, int indentation) const;
AITextureIDUUIDPair(AIXMLElementParser const& parser);
// Accessors.
U32 getID(void) const { return mID; }
LLUUID const& getUUID(void) const { return mUUID; }
};
class AIArchetype
{
public:
struct MetaData
{
std::string mPath; // The wearable location in the inventory.
std::string mName; // The wearable name.
std::string mDescription; // The wearable description.
MetaData(void) { }
MetaData(LLViewerWearable const* wearable);
void toXML(std::ostream& os, int indentation) const;
MetaData(AIXMLElementParser const& parser);
};
typedef std::vector<AIVisualParamIDValuePair> params_type;
typedef std::vector<AITextureIDUUIDPair> textures_type;
private:
LLWearableType::EType mType; // The type of the wearable.
MetaData mMetaData;
params_type mParams;
textures_type mTextures;
public:
// Accessors.
LLWearableType::EType getType(void) const { return mType; }
MetaData const& getMetaData(void) const { return mMetaData; }
params_type const& getParams(void) const { return mParams; }
textures_type const& getTextures(void) const { return mTextures; }
public:
// An archtype without wearable has no (known) metadata. This is recognized because mPath will be empty.
// An archtype without type with get the attribute name="???".
AIArchetype(void); // <archetype name="???">
AIArchetype(LLWearableType::EType type); // <archetype name="shirt">
AIArchetype(LLViewerWearable const* wearable); // <archetype name="shirt"> <meta path="myclothes" name="blue shirt" description="Awesome blue shirt">
void add(AIVisualParamIDValuePair const& visual_param_id_value_pair) { mParams.push_back(visual_param_id_value_pair); }
void add(AITextureIDUUIDPair const& texture_id_uuid_pair) { mTextures.push_back(texture_id_uuid_pair); }
void toXML(std::ostream& os, int indentation) const;
AIArchetype(AIXMLElementParser const& parser);
};
#endif // AIXMLLINDENGENEPOOL_H

View File

@@ -53,8 +53,9 @@
#include "llvoavatarself.h"
#include "statemachine/aifilepicker.h"
#include "llxmltree.h"
#include "hippogridmanager.h"
#include "aixmllindengenepool.h"
#include "aifile.h"
using namespace LLAvatarAppearanceDefines;
@@ -330,215 +331,112 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
LLPanelEditWearable* panel_edit_wearable = getCurrentWearablePanel();
LLViewerWearable* edit_wearable = panel_edit_wearable->getWearable();
LLWearableType::EType panel_wearable_type = panel_edit_wearable->getType();
std::string label = utf8str_tolower(panel_edit_wearable->getLabel());
std::string const filename = filepicker->getFilename();
LLSD args(LLSD::emptyMap());
args["FILE"] = gDirUtilp->getBaseFileName(filename);
LLXmlTree xml;
BOOL success = xml.parseFile(filename, FALSE);
if (!success)
{
LLNotificationsUtil::add("AIXMLImportParseError", args);
return;
}
LLXmlTreeNode* root = xml.getRoot();
if (!root)
{
llwarns << "No root node found in wearable import file: " << filename << llendl;
LLNotificationsUtil::add("AIXMLImportParseError", args);
return;
}
AIArgs args("[FILE]", gDirUtilp->getBaseFileName(filename));
//-------------------------------------------------------------------------
// <linden_genepool version="1.0" [metaversion="?"]> (root)
//-------------------------------------------------------------------------
if (!root->hasName("linden_genepool"))
{
llwarns << "Invalid wearable import file (missing linden_genepool header): " << filename << llendl;
LLNotificationsUtil::add("AIXMLImportRootTypeError", args);
return;
}
static LLStdStringHandle const version_string = LLXmlTree::addAttributeString("version");
std::string version;
if (!root->getFastAttributeString(version_string, version) || (version != "1.0"))
{
llwarns << "Invalid or incompatible linden_genepool version: " << version << " in file: " << filename << llendl;
args["TAG"] = "version";
args["VERSIONMAJOR"] = "1";
LLNotificationsUtil::add("AIXMLImportRootVersionError", args);
return;
}
static LLStdStringHandle const metaversion_string = LLXmlTree::addAttributeString("metaversion");
std::string metaversion;
U32 metaversion_major;
if (!root->getFastAttributeString(metaversion_string, metaversion))
{
llwarns << "Invalid linden_genepool metaversion: " << metaversion << " in file: " << filename << llendl;
metaversion_major = 0;
}
else if (!LLStringUtil::convertToU32(metaversion, metaversion_major) || metaversion_major > 1)
{
llwarns << "Invalid or incompatible linden_genepool metaversion: " << metaversion << " in file: " << filename << llendl;
args["TAG"] = "metaversion";
args["VERSIONMAJOR"] = "1";
LLNotificationsUtil::add("AIXMLImportRootVersionError", args);
return;
}
//-------------------------------------------------------------------------
// <meta gridnick="secondlife" date="2013-07-20T15:27:55.80Z">
//-------------------------------------------------------------------------
std::string gridnick;
LLDate date;
bool different_grid = false; // By default assume it was exported on the same grid as we're on now.
bool mixed_grids = false; // Set to true if two different grids (might) share UUIDs. Currently only "secondlife" and "secondlife_beta".
if (metaversion_major >= 1)
{
static LLStdStringHandle const gridnick_string = LLXmlTree::addAttributeString("gridnick");
static LLStdStringHandle const date_string = LLXmlTree::addAttributeString("date");
std::string date_s;
bool invalid = true;
LLXmlTreeNode* meta_node = root->getChildByName("meta");
if (!meta_node)
{
llwarns << "No meta (1) in wearable import file: " << filename << llendl;
}
else if (!meta_node->getFastAttributeString(gridnick_string, gridnick))
{
llwarns << "meta tag in file: " << filename << " is missing the 'gridnick' parameter." << llendl;
}
else if (!meta_node->getFastAttributeString(date_string, date_s) || !date.fromString(date_s))
{
llwarns << "meta tag in file: " << filename << " is missing or invalid 'date' parameter." << llendl;
}
else
{
invalid = false;
std::string current_gridnick = gHippoGridManager->getConnectedGrid()->getGridNick();
different_grid = gridnick != current_gridnick;
mixed_grids = (gridnick == "secondlife" && current_gridnick == "secondlife_beta") ||
(gridnick == "secondlife_beta" && current_gridnick == "secondlife");
}
if (invalid)
{
LLNotificationsUtil::add("AIXMLImportInvalidError", args);
return;
}
}
static LLStdStringHandle const name_string = LLXmlTree::addAttributeString("name");
//-------------------------------------------------------------------------
// <archetype name="???">
//-------------------------------------------------------------------------
LLXmlTreeNode* archetype_node = root->getChildByName("archetype");
if (!archetype_node)
{
llwarns << "No archetype in wearable import file: " << filename << llendl;
LLNotificationsUtil::add("AIXMLImportInvalidError", args);
return;
}
// Legacy that name="" exists. Using it as human (only) readable type label of contents. Don't use it for anything else because it might not be set.
std::string label = "???";
if (metaversion_major >= 1)
{
if (!archetype_node->getFastAttributeString(name_string, label))
{
llwarns << "archetype tag in file: " << filename << " is missing the 'name' parameter." << llendl;
}
}
//-------------------------------------------------------------------------
// <meta path="Clothing" name="New Shirt27" description="Some description"/>
//-------------------------------------------------------------------------
std::string path;
std::string wearable_name;
std::string wearable_description;
if (metaversion_major >= 1)
{
static LLStdStringHandle const path_string = LLXmlTree::addAttributeString("path");
static LLStdStringHandle const description_string = LLXmlTree::addAttributeString("description");
bool invalid = true;
LLXmlTreeNode* meta_node = archetype_node->getChildByName("meta");
if (!meta_node)
{
llwarns << "No meta (2) in wearable import file: " << filename << llendl;
}
else if (!meta_node->getFastAttributeString(path_string, path))
{
llwarns << "meta tag in file: " << filename << " is missing the 'path' parameter." << llendl;
}
else if (!meta_node->getFastAttributeString(name_string, wearable_name))
{
llwarns << "meta tag in file: " << filename << " is missing the 'name' parameter." << llendl;
}
else if (!meta_node->getFastAttributeString(description_string, wearable_description))
{
llwarns << "meta tag in file: " << filename << " is missing the 'description' parameter." << llendl;
}
else
{
invalid = false;
}
if (invalid)
{
LLNotificationsUtil::add("AIXMLImportInvalidError", args);
return;
}
}
// Parse the XML content.
static LLStdStringHandle const id_string = LLXmlTree::addAttributeString("id");
static LLStdStringHandle const value_string = LLXmlTree::addAttributeString("value");
static LLStdStringHandle const te_string = LLXmlTree::addAttributeString("te");
static LLStdStringHandle const uuid_string = LLXmlTree::addAttributeString("uuid");
bool found_param = false;
bool found_texture = false;
for(LLXmlTreeNode* child = archetype_node->getFirstChild(); child; child = archetype_node->getNextChild())
bool found_type = false;
bool different_grid = false; // By default assume it was exported on the same grid as we're on now.
bool mixed_grids = false; // Set to true if two different grids (might) share UUIDs. Currently only "secondlife" and "secondlife_beta".
std::string gridnick;
std::string wearable_types;
try
{
if (child->hasName("param"))
//-------------------------------------------------------------------------
// <linden_genepool version="1.0" [metaversion="?"]> (root)
//-------------------------------------------------------------------------
std::string metaversion;
U32 metaversion_major;
AIXMLParser linden_genepool(filename, "wearable import file", "linden_genepool", 1);
linden_genepool.attribute("version", "1.0");
linden_genepool.attribute("metaversion", metaversion);
if (!LLStringUtil::convertToU32(metaversion, metaversion_major) || metaversion_major > 1)
{
std::string id_s;
U32 id;
std::string value_s;
F32 value;
if (!child->getFastAttributeString(id_string, id_s) || !LLStringUtil::convertToU32(id_s, id) ||
!child->getFastAttributeString(value_string, value_s) || !LLStringUtil::convertToF32(value_s, value))
{
llwarns << "Possible syntax error or corruption for <param id=... value=... /> node in " << filename << llendl;
continue;
}
LLVisualParam* visual_param = edit_wearable->getVisualParam(id);
if (visual_param)
{
found_param = true;
visual_param->setWeight(value, FALSE);
}
THROW_MALERT("AIXMLImportRootVersionError", args("[TAG]", "metaversion")("[VERSIONMAJOR]", "1"));
}
else if (child->hasName("texture"))
//-------------------------------------------------------------------------
// <meta gridnick="secondlife" date="2013-07-20T15:27:55.80Z">
//-------------------------------------------------------------------------
AIXMLLindenGenepool::MetaData meta_data;
if (metaversion_major >= 1)
{
std::string te_s;
S32 te;
std::string uuid_s;
LLUUID uuid;
if (!child->getFastAttributeString(te_string, te_s) || !LLStringUtil::convertToS32(te_s, te) || te < 0 || te >= TEX_NUM_INDICES ||
!child->getFastAttributeString(uuid_string, uuid_s) || !uuid.set(uuid_s, TRUE))
linden_genepool.child("meta", meta_data);
std::string current_gridnick = gHippoGridManager->getConnectedGrid()->getGridNick();
gridnick = meta_data.mGridNick;
different_grid = gridnick != current_gridnick;
mixed_grids = (gridnick == "secondlife" && current_gridnick == "secondlife_beta") ||
(gridnick == "secondlife_beta" && current_gridnick == "secondlife");
}
std::vector<AIArchetype> archetypes;
linden_genepool.setVersion(metaversion_major);
linden_genepool.push_back_children("archetype", archetypes);
if (archetypes.empty())
{
THROW_ALERT("AIXMLImportNoArchetypeError", AIArgs("[FILE]", filename));
}
for (std::vector<AIArchetype>::iterator archetype = archetypes.begin(); archetype != archetypes.end(); ++archetype)
{
LLWearableType::EType type = archetype->getType();
if (type != LLWearableType::WT_NONE)
{
llwarns << "Possible syntax error or corruption for <texture te=... uuid=... /> node in " << filename << llendl;
continue;
}
ETextureIndex te_index = (ETextureIndex)te;
LLWearableType::EType te_wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(te_index);
if (te_wearable_type == edit_wearable->getType())
{
found_texture = true;
if (!different_grid || mixed_grids)
if (!wearable_types.empty())
{
panel_edit_wearable->setNewImageID(te_index, uuid);
wearable_types += "/";
}
wearable_types += LLWearableType::getTypeName(type);
if (panel_wearable_type == type)
{
found_type = true;
}
}
for (AIArchetype::params_type::const_iterator param = archetype->getParams().begin(); param != archetype->getParams().end(); ++param)
{
LLVisualParam* visual_param = edit_wearable->getVisualParam(param->getID());
if (visual_param)
{
found_param = true;
visual_param->setWeight(param->getValue(), FALSE);
}
}
for (AIArchetype::textures_type::const_iterator texture = archetype->getTextures().begin(); texture != archetype->getTextures().end(); ++texture)
{
U32 te = texture->getID();
if (te >= TEX_NUM_INDICES)
{
}
ETextureIndex te_index = (ETextureIndex)te;
LLWearableType::EType te_wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(te_index);
if (te_wearable_type == edit_wearable->getType())
{
found_texture = true;
if (!different_grid || mixed_grids)
{
panel_edit_wearable->setNewImageID(te_index, texture->getUUID());
}
}
}
}
}
catch (AIAlert::Error const& error)
{
AIAlert::add_modal("AIXMLImportError", AIArgs("[TYPE]", label), error);
return;
}
if (found_param || found_texture)
{
edit_wearable->writeToAvatar(gAgentAvatarp);
@@ -546,23 +444,25 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
panel_edit_wearable->updateScrollingPanelUI();
if (found_texture && different_grid)
{
args["EXPORTGRID"] = gridnick;
args["CURRENTGRID"] = gHippoGridManager->getConnectedGrid()->getGridNick();
args("[EXPORTGRID]", gridnick);
args("[CURRENTGRID]", gHippoGridManager->getConnectedGrid()->getGridNick());
if (mixed_grids)
{
LLNotificationsUtil::add("AIXMLImportMixedGrid", args);
AIAlert::add_modal("AIXMLImportMixedGrid", args);
}
else
{
LLNotificationsUtil::add("AIXMLImportDifferentGrid", args);
AIAlert::add_modal("AIXMLImportDifferentGrid", args);
}
}
}
else
else if (found_type)
{
args["TYPE"] = panel_edit_wearable->LLPanel::getLabel();
args["ARCHETYPENAME"] = label;
LLNotificationsUtil::add("AIXMLImportWearableTypeMismatch", args);
AIAlert::add("AIXMLImportEmptyArchetype", args("[TYPE]", label));
}
else if (!wearable_types.empty())
{
AIAlert::add("AIXMLImportWearableTypeMismatch", args("[TYPE]", label)("[ARCHETYPENAME]", wearable_types));
}
}
@@ -615,21 +515,26 @@ void LLFloaterCustomize::onBtnExport_continued(LLViewerWearable* edit_wearable,
}
std::string filename = filepicker->getFilename();
LLSD args(LLSD::emptyMap());
args["FILE"] = filename;
LLAPRFile outfile;
outfile.open(filename, LL_APR_WB);
if (!outfile.getFileHandle())
bool success = false;
try
{
llwarns << "Could not open \"" << filename << "\" for writing." << llendl;
LLNotificationsUtil::add("AIXMLExportWriteError", args);
return;
AIFile outfile(filename, "wb");
AIXMLLindenGenepool linden_genepool(outfile);
linden_genepool.child(edit_wearable->getArchetype());
success = true;
}
catch (AIAlert::Error const& error)
{
AIAlert::add_modal("AIXMLExportWriteError", AIArgs("[FILE]", filename), error);
}
LLVOAvatar::dumpArchetypeXML_header(outfile, edit_wearable->getTypeName());
edit_wearable->archetypeExport(outfile);
LLVOAvatar::dumpArchetypeXML_footer(outfile);
if (success)
{
AIAlert::add_modal("AIXMLExportSuccess", AIArgs("[FILE]", filename));
}
}
void LLFloaterCustomize::onBtnOk()

View File

@@ -297,6 +297,8 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
mRegionFlags( REGION_FLAGS_DEFAULT ),
mRegionProtocols( 0 ),
mSimAccess( SIM_ACCESS_MIN ),
mLastSimAccess( 0 ),
mSimAccessString( "unknown" ),
mBillableFactor(1.0),
mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT),
mCentralBakeVersion(0),
@@ -599,9 +601,15 @@ BOOL LLViewerRegion::canManageEstate() const
|| gAgent.getID() == getOwner();
}
const std::string LLViewerRegion::getSimAccessString() const
std::string const& LLViewerRegion::getSimAccessString()
{
return accessToString(mSimAccess);
// Singu: added a cache because this is called every frame.
if (mLastSimAccess != mSimAccess)
{
mSimAccessString = accessToString(mSimAccess);
mLastSimAccess = mSimAccess;
}
return mSimAccessString;
}
std::string LLViewerRegion::getLocalizedSimProductName() const
@@ -2134,4 +2142,4 @@ U32 LLViewerRegion::getMaxMaterialsPerTransaction() const
max_entries = mSimulatorFeatures[ "MaxMaterialsPerTransaction" ].asInteger();
}
return max_entries;
}
}

View File

@@ -204,8 +204,8 @@ public:
void setSimAccess(U8 sim_access) { mSimAccess = sim_access; }
U8 getSimAccess() const { return mSimAccess; }
const std::string getSimAccessString() const;
std::string const& getSimAccessString(); // Singu note: return reference to mSimAccessString.
// Homestead-related getters; there are no setters as nobody should be
// setting them other than the individual message handler which is a member
S32 getSimClassID() const { return mClassID; }
@@ -430,6 +430,8 @@ private:
U64 mRegionFlags; // includes damage flags
U64 mRegionProtocols; // protocols supported by this region
U8 mSimAccess;
U8 mLastSimAccess; // Singularity extension.
std::string mSimAccessString; // Singularity extension.
F32 mBillableFactor;
U32 mMaxTasks; // max prim count
F32 mCameraDistanceSquared; // updated once per frame

View File

@@ -40,6 +40,7 @@
#include "llviewerregion.h"
#include "llinventoryobserver.h"
#include "llinventoryfunctions.h"
#include "aixmllindengenepool.h"
using namespace LLAvatarAppearanceDefines;
@@ -134,32 +135,18 @@ LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_st
return result;
}
extern void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value);
void LLViewerWearable::archetypeExport(LLAPRFile& file) const
AIArchetype LLViewerWearable::getArchetype(void) const
{
apr_file_t* fp = file.getFileHandle();
std::string path;
append_path_short(mItemID, path);
apr_file_printf(fp, " <meta path=\"%s\" name=\"%s\" description=\"%s\"/>\n",
LLXMLNode::escapeXML(path).c_str(),
LLXMLNode::escapeXML(mName).c_str(),
LLXMLNode::escapeXML(mDescription).c_str());
AIArchetype archetype(this);
for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter)
{
LLVisualParam const* param = iter->second;
dump_visual_param(file, param, param->getWeight());
archetype.add(AIVisualParamIDValuePair(iter->second));
}
for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter)
{
S32 te = iter->first;
LLUUID const& image_id = iter->second->getID();
apr_file_printf(fp, " <texture te=\"%i\" uuid=\"%s\"/>\n", te, image_id.asString().c_str());
archetype.add(AITextureIDUUIDPair(iter->first, iter->second->getID()));
}
apr_file_printf(fp, "\n");
return archetype;
}
// Avatar parameter and texture definitions can change over time.

View File

@@ -29,6 +29,7 @@
#include "llwearable.h"
#include "llavatarappearancedefines.h"
#include "aixmllindengenepool.h"
class LLVOAvatar;
class LLAPRFile;
@@ -67,8 +68,9 @@ public:
/*virtual*/ EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp );
void archetypeExport(LLAPRFile& file) const;
// Singu extension.
AIArchetype getArchetype(void) const;
void setParamsToDefaults();
void setTexturesToDefaults();

View File

@@ -112,6 +112,8 @@
#include "llfloaterexploreanimations.h"
#include "aihttptimeoutpolicy.h"
#include "aixmllindengenepool.h"
#include "aifile.h"
#include "llavatarname.h"
@@ -7672,29 +7674,10 @@ bool LLVOAvatar::visualParamWeightsAreDefault()
void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value)
{
std::string type_string = "unknown";
if (dynamic_cast<LLTexLayerParamAlpha const*>(viewer_param))
type_string = "param_alpha";
if (dynamic_cast<LLTexLayerParamColor const*>(viewer_param))
type_string = "param_color";
if (dynamic_cast<LLDriverParam const*>(viewer_param))
type_string = "param_driver";
if (dynamic_cast<LLPolyMorphTarget const*>(viewer_param))
type_string = "param_morph";
if (dynamic_cast<LLPolySkeletalDistortion const*>(viewer_param))
type_string = "param_skeleton";
S32 wtype = -1;
LLViewerVisualParam const* vparam = dynamic_cast<LLViewerVisualParam const*>(viewer_param);
if (vparam)
{
wtype = vparam->getWearableType();
}
S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight());
apr_file_printf(file.getFileHandle(), " <param id=\"%d\" name=\"%s\" value=\"%.3f\" u8=\"%d\" type=\"%s\" wearable=\"%s\"/>\n",
viewer_param->getID(), viewer_param->getName().c_str(), value, u8_value, type_string.c_str(),
LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str()
// param_location_name(vparam->getParamLocation()).c_str()
);
viewer_param->getID(), viewer_param->getName().c_str(), value, u8_value, viewer_param->getTypeString(),
viewer_param->getDumpWearableTypeName().c_str());
}
void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix,
@@ -8352,127 +8335,83 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara
dumpArchetypeXML_cont(fullpath, group_by_wearables);
}
// metaversion 1.0
// ===============
//
// Added as child of <linden_genepool>:
//
// <meta gridnick="secondlife" date="2013-07-16T16:49:00.40Z"/>
//
// Optionally, as child of <archetype>, the following node may appear:
//
// <meta path="clothing/jackets" name="Purple jacket" description="A jacket with mainly the color purple">
//
// Furthermore, metaversion 1.0 and higher allow the occurance of one or more <archetype> blocks.
// If this is used then it is strongly advised to use one <archetype> per wearable, so that
// the the <meta> node makes sense (it then refers to the wearable of that <archetype>).
//
// The reason for this clumsy way to link wearable to extra meta data is to stay
// compatible with the older format (no metaversion).
//
//static
void LLVOAvatar::dumpArchetypeXML_header(LLAPRFile& file, std::string const& archetype_name)
{
apr_file_t* fp = file.getFileHandle();
apr_file_printf(fp, "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>\n");
apr_file_printf(fp, "<linden_genepool version=\"1.0\" metaversion=\"1.0\">\n");
apr_file_printf(fp, " <meta gridnick=\"%s\" date=\"%s\"/>\n",
LLXMLNode::escapeXML(gHippoGridManager->getConnectedGrid()->getGridNick()).c_str(),
LLDate::now().asString().c_str());
apr_file_printf(fp, " <archetype name=\"%s\">\n", archetype_name.c_str());
}
//static
void LLVOAvatar::dumpArchetypeXML_footer(LLAPRFile& file)
{
apr_file_t* fp = file.getFileHandle();
apr_file_printf(fp, " </archetype>\n");
apr_file_printf(fp, "</linden_genepool>\n");
}
void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_by_wearables)
{
LLAPRFile outfile;
outfile.open(fullpath, LL_APR_WB );
apr_file_t* file = outfile.getFileHandle();
if (!file)
try
{
return;
AIFile outfile(fullpath, "wb");
AIXMLLindenGenepool linden_genepool(outfile);
if (group_by_wearables)
{
for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++)
{
AIArchetype archetype((LLWearableType::EType)type);
for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam())
{
LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param;
if( (viewer_param->getWearableType() == type) &&
(viewer_param->isTweakable() ) )
{
archetype.add(AIVisualParamIDValuePair(param));
}
}
for (U8 te = 0; te < TEX_NUM_INDICES; te++)
{
if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type)
{
// MULTIPLE_WEARABLES: extend to multiple wearables?
LLViewerTexture* te_image = getImage((ETextureIndex)te, 0);
if( te_image )
{
archetype.add(AITextureIDUUIDPair(te, te_image->getID()));
}
}
}
linden_genepool.child(archetype);
}
}
else
{
// Just dump all params sequentially.
AIArchetype archetype; // Legacy: Type is set to WT_NONE and will result in <archetype name="???">.
for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam())
{
archetype.add(AIVisualParamIDValuePair(param));
}
for (U8 te = 0; te < TEX_NUM_INDICES; te++)
{
{
// MULTIPLE_WEARABLES: extend to multiple wearables?
LLViewerTexture* te_image = getImage((ETextureIndex)te, 0);
if( te_image )
{
archetype.add(AITextureIDUUIDPair(te, te_image->getID()));
}
}
}
linden_genepool.child(archetype);
}
#if 0 // Wasn't used anyway.
bool ultra_verbose = false;
if (isSelf() && ultra_verbose)
{
// show the cloned params inside the wearables as well.
gAgentAvatarp->dumpWearableInfo(outfile);
}
#endif
}
else
catch (AIAlert::Error const& error)
{
llinfos << "xmlfile write handle obtained : " << fullpath << llendl;
AIAlert::add_modal("AIXMLdumpArchetypeXMLError", AIArgs("[FILE]", fullpath), error);
}
LLVOAvatar::dumpArchetypeXML_header(outfile);
if (group_by_wearables)
{
for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++)
{
const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type);
apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() );
for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam())
{
LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param;
if( (viewer_param->getWearableType() == type) &&
(viewer_param->isTweakable() ) )
{
dump_visual_param(outfile, viewer_param, viewer_param->getWeight());
}
}
for (U8 te = 0; te < TEX_NUM_INDICES; te++)
{
if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type)
{
// MULTIPLE_WEARABLES: extend to multiple wearables?
LLViewerTexture* te_image = getImage((ETextureIndex)te, 0);
if( te_image )
{
std::string uuid_str;
te_image->getID().toString( uuid_str );
apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", te, uuid_str.c_str());
}
}
}
}
}
else
{
// Just dump all params sequentially.
for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam())
{
LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param;
dump_visual_param(outfile, viewer_param, viewer_param->getWeight());
}
for (U8 te = 0; te < TEX_NUM_INDICES; te++)
{
{
// MULTIPLE_WEARABLES: extend to multiple wearables?
LLViewerTexture* te_image = getImage((ETextureIndex)te, 0);
if( te_image )
{
std::string uuid_str;
te_image->getID().toString( uuid_str );
apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", te, uuid_str.c_str());
}
}
}
}
LLVOAvatar::dumpArchetypeXML_footer(outfile);
bool ultra_verbose = false;
if (isSelf() && ultra_verbose)
{
// show the cloned params inside the wearables as well.
gAgentAvatarp->dumpWearableInfo(outfile);
}
// File will close when handle goes out of scope
}
void LLVOAvatar::setVisibilityRank(U32 rank)

View File

@@ -69,25 +69,6 @@
</form>
</template>
<notification name="AIXMLExportWriteError">Export Failure: could not open file "[FILE]" for writing.</notification>
<notification name="AIXMLImportGridMismatch">Import Warning: could not apply textures: [FILE] was exported on grid "[GRIDNAME]" while the currentgrid is "[CURGRID]".</notification>
<notification name="AIXMLImportParseError">Import Failure: could not read or parse wearable import file "[FILE]".</notification>
<notification name="AIXMLImportRootTypeError">Import Failure: the file "[FILE]" is not a linden_genepool XML file.</notification>
<notification name="AIXMLImportRootVersionError">Import Failure: the file "[FILE]" contains linden_genepool XML data with the wrong [TAG]. Version "[VERSIONMAJOR].0" or less is required.</notification>
<notification name="AIXMLImportInvalidError">Import Failure: the file "[FILE]" contains invalid data.</notification>
<notification name="AIXMLImportDifferentGrid">Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have NOT been applied!</notification>
<notification name="AIXMLImportMixedGrid">Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have been applied but might not exist here!</notification>
<notification name="AIXMLImportWearableTypeMismatch">Import Warning: the file "[FILE]" does not contain a wearable of type [TYPE].
It contains an archetype of type [ARCHETYPENAME]. Please select the correct type before importing.</notification>
<notification name="MediaAlert">Der Besitzer der Parzelle m&#xF6;chte Ihren Viewer anweisen die folgende [TYPE] URL zu laden:[URL]Sie k&#xF6;nnen die korrespondierende Dom&#xE4;ne oder In-Welt Objekt-Skript-Server erlauben oder ablehnen."Erlauben" und "Verweigern" gelten nur f&#xFC;r die aktuelle Sitzung, w&#xE4;hrend "Immer sperren" bzw. "Immer erlauben" dann immer gelten.<form name="form">
<button name="Allow" text="erlauben"/>
<button name="Deny" text="verbieten"/>

View File

@@ -133,68 +133,18 @@
</form>
</template>
<notification
icon="alertmodal.tga"
name="AIXMLExportWriteError"
type="alertmodal">
Export Failure: could not open file &quot;[FILE]&quot; for writing.
</notification>
<notification
icon="alert.tga"
name="AIXMLImportGridMismatch"
name="AIAlert"
type="alert">
Import Warning: could not apply textures: [FILE] was exported on grid &quot;[GRIDNAME]&quot; while the currentgrid is &quot;[CURGRID]&quot;.
[PAYLOAD]
</notification>
<notification
icon="alertmodal.tga"
name="AIXMLImportParseError"
name="AIAlertModal"
type="alertmodal">
Import Failure: could not read or parse wearable import file &quot;[FILE]&quot;.
</notification>
<notification
icon="alertmodal.tga"
name="AIXMLImportRootTypeError"
type="alertmodal">
Import Failure: the file &quot;[FILE]&quot; is not a linden_genepool XML file.
</notification>
<notification
icon="alertmodal.tga"
name="AIXMLImportRootVersionError"
type="alertmodal">
Import Failure: the file &quot;[FILE]&quot; contains linden_genepool XML data with the wrong [TAG]. Version &quot;[VERSIONMAJOR].0&quot; or less is required.
</notification>
<notification
icon="alertmodal.tga"
name="AIXMLImportInvalidError"
type="alertmodal">
Import Failure: the file &quot;[FILE]&quot; contains invalid data.
</notification>
<notification
icon="alertmodal.tga"
name="AIXMLImportDifferentGrid"
type="alertmodal">
Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have NOT been applied!
</notification>
<notification
icon="alertmodal.tga"
name="AIXMLImportMixedGrid"
type="alertmodal">
Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have been applied but might not exist here!
</notification>
<notification
icon="alert.tga"
name="AIXMLImportWearableTypeMismatch"
type="alert">
Import Warning: the file &quot;[FILE]&quot; does not contain a wearable of type [TYPE].
It contains an archetype of type [ARCHETYPENAME]. Please select the correct type before importing.
[PAYLOAD]
</notification>
<notification

View File

@@ -4367,4 +4367,55 @@ Try enclosing path to the editor with double quotes.
<!-- teleport_strings.xml's strings we need -->
<string name="completed_from">Teleport completed from</string>
<!-- AIAlert messages -->
<string name="AIPrefix">"[PREFIX]: "</string>
<!-- AIFile exception alerts -->
<string name="AIFile_mkdir_Failed_to_create_DIRNAME">Failed to create folder [DIRNAME]: [ERROR]</string>
<string name="AIFile_rmdir_Failed_to_remove_DIRNAME">Failed to remove folder [DIRNAME]: [ERROR]</string>
<string name="AIFile_fopen_Failed_to_open_FILENAME">Failed to open file "[FILENAME]": [ERROR]</string>
<string name="AIFile_close_Failed_to_close_file">Failed to close file: [ERROR]</string>
<string name="AIFile_remove_Failed_to_remove_FILENAME">Failed to remove file [FILENAME]: [ERROR]</string>
<string name="AIFile_rename_Failed_to_rename_FILE_to_NEWFILE">Failed to rename file [FILE] to [NEWFILE]: [ERROR]</string>
<!-- AIXMLElement exception alerts -->
<string name="AIXMLElement_attribute_Failed_to_write_DATA">Failed to write '[DATA]', writing attribute data.</string>
<string name="AIXMLElement_child_Bad_ostream">ostream not good after calling child.toXML</string>
<string name="AIXMLElement_write_child_Failed_to_write_DATA">Failed to write '[DATA]', writing child data.</string>
<string name="AIXMLElement_Failed_to_write_DATA">Failed to write '[DATA]', opening new child.</string>
<string name="AIXMLElement_closing_child_Failed_to_write_DATA">Failed to write '[DATA]', closing previous child.</string>
<!-- AIXMLStream exception alerts -->
<string name="AIXMLStream_fprintf_failed_to_write_xml_header">Failed to write XML header.</string>
<!-- AIXMLParser exception alerts -->
<string name="AIXMLParser_Cannot_parse_FILEDESC_FILENAME">Cannot parse [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_No_root_node_found_in_FILEDESC_FILENAME">No root node found in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_Missing_header_NAME_invalid_FILEDESC_FILENAME">Missing header '[NAME]' ; invalid [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_Invalid_or_missing_NAME_version_attribute_in_FILEDESC_FILENAME">Invalid or missing [NAME] 'version' attribute in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_Incompatible_NAME_version_MAJOR_MINOR_in">Incompatible '[NAME]' version, [MAJOR].[MINOR], in [FILEDESC] "[FILENAME]".</string>
<!-- AIXMLElementParser exception alerts -->
<string name="AIXMLElementParser_read_string_Invalid_MD5_VALUE_in_FILEDESC_FILENAME">Invalid MD5 ([VALUE]) in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_read_string_Invalid_boolean_VALUE_in_FILEDESC_FILENAME">Invalid boolean ([VALUE]) in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_attribute_Missing_NAME_attribute_in_NODENAME_of_FILEDESC_FILENAME">Missing '[NAME]' attribute in [NODENAME] of [FILEDESC] "[FILENAME]".</string>"
<string name="AIXMLElementParser_attribute_Invalid_NAME_attribute_should_be_REQUIRED_in_NODENAME_of_FILEDESC_FILENAME">Invalid '[NAME]' attribute (should be '[REQUIRED]') in [NODENAME] of [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_read_child_Invalid_uuid_in_FILEDESC_FILENAME">Invalid UUID in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_read_child_Invalid_date_DATE_in_FILEDESC_FILENAME">Invalid DATE ([DATE]) in [FILEDESC] "[FILENAME]".</string>
<!-- AIArchetype exception alerts -->
<string name="AIArchetype_archetype_has_no_meta">archetype has no &lt;meta&gt; element.</string>
<string name="AIArchetype_MetaData_archetype_meta_has_no_ATTRIBUTE">archetype &lt;meta&gt; element has no '[ATTRIBUTE]' attribute.</string>
<string name="AIXMLdumpArchetypeXMLError">Failure dumping archetype to "[FILE]":</string>
<string name="AIXMLExportSuccess">Successfully exported wearable to "[FILE]".</string>
<string name="AIXMLExportWriteError">The export to file "[FILE]" failed:</string>
<string name="AIXMLImportRootVersionError">Import Failure: the file "[FILE]" contains linden_genepool XML data with the wrong [TAG]. Version "[VERSIONMAJOR].0" or less is required.</string>
<string name="AIXMLImportDifferentGrid">Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have NOT been applied!</string>
<string name="AIXMLImportMixedGrid">Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have been applied but might not exist here!</string>
<string name="AIXMLImportEmptyArchetype">Import warning: the file "[FILE]" contains a wearable of the selected type ([TYPE]), but contains no parameters or textures for that type. Nothing was imported.</string>
<string name="AIXMLImportWearableTypeMismatch">Import warning: the file "[FILE]" does not contain a wearable of type [TYPE]. It contains an archetype of type [ARCHETYPENAME]. Please select the correct type before importing.</string>
<string name="AIXMLImportError">Failed to import the [TYPE] wearable:</string>
<string name="AIXMLImportNoArchetypeError">No archetype found in wearable import file "[FILE]".</string>
</strings>

View File

@@ -73,44 +73,7 @@
</form>
</template>
<notification name="AIXMLExportWriteError">
Fallo de Exportación: no se puede abrir el archivo &quot;[FILE]&quot; para escritura.
</notification>
<notification name="AIXMLImportGridMismatch">
Aviso de Importación: No se pueden aplicar las texturas: El [FILE] fue exportado en el grid &quot;[GRIDNAME]&quot; mientras que el grid actual es &quot;[CURGRID]&quot;.
</notification>
<notification name="AIXMLImportParseError">
Fallo de Importación: no se puede leer o analizar el archivo de vestimenta para importar &quot;[FILE]&quot;.
</notification>
<notification name="AIXMLImportRootTypeError">
Fallo de Importación: el archivo &quot;[FILE]&quot; no es un archivo linden_genepool XML.
</notification>
<notification name="AIXMLImportRootVersionError">
Fallo de Importación: el archivo &quot;[FILE]&quot; contiene datos linden_genepool XML con [TAG] erróneo. Se requiere Versión &quot;[VERSIONMAJOR].0&quot; o inferior.
</notification>
<notification name="AIXMLImportInvalidError">
Fallo de Importación: el archivo &quot;[FILE]&quot; contiene datos inválidos.
</notification>
<notification name="AIXMLImportDifferentGrid">
La importación se ha realizado con exito, pero ten presente que el objeto vestible fue exportado desde el grid [EXPORTGRID] (y el grid actual es [CURRENTGRID]). ¡No se aplicaron las UUIDs de las Texturas!
</notification>
<notification name="AIXMLImportMixedGrid">
La importación se ha realizado con exito, pero ten presente que el objeto vestible fue exportado desde el grid [EXPORTGRID] (y el grid actual es [CURRENTGRID]).¡Se aplicaron las UUIDs de la Texturas pero quizás no existan aquí!
</notification>
<notification name="AIXMLImportWearableTypeMismatch">
Aviso de Importación: el archivo &quot;[FILE]&quot; no contiene un objeto vestible de tipo [TYPE].
Éste contiene un arquetipo de tipo [ARCHETYPENAME]. Por favor, selecciona el tipo correcto antes de comenzar la importación.
</notification>
<notification name="MediaAlert">
El propietario de esta parcela ha solicitado que el siguiente URL de [TYPE] sea cargado en tu visor:

View File

@@ -4836,5 +4836,58 @@ Intenta entrecomillando el camino al editor.
<!-- teleport_strings.xml's strings we need -->
<string name="completed_from">Teleporte completado desde</string>
<!-- ************ EVERYTHING BELOW STILL NEEDS TRANSLATION! ************** -->
<!-- AIAlert messages -->
<string name="AIPrefix">"[PREFIX]: "</string>
<!-- AIFile exception alerts -->
<string name="AIFile_mkdir_Failed_to_create_DIRNAME">Failed to create folder [DIRNAME]: [ERROR]</string>
<string name="AIFile_rmdir_Failed_to_remove_DIRNAME">Failed to remove folder [DIRNAME]: [ERROR]</string>
<string name="AIFile_fopen_Failed_to_open_FILENAME">Failed to open file "[FILENAME]": [ERROR]</string>
<string name="AIFile_close_Failed_to_close_file">Failed to close file: [ERROR]</string>
<string name="AIFile_remove_Failed_to_remove_FILENAME">Failed to remove file [FILENAME]: [ERROR]</string>
<string name="AIFile_rename_Failed_to_rename_FILE_to_NEWFILE">Failed to rename file [FILE] to [NEWFILE]: [ERROR]</string>
<!-- AIXMLElement exception alerts -->
<string name="AIXMLElement_attribute_Failed_to_write_DATA">Failed to write '[DATA]', writing attribute data.</string>
<string name="AIXMLElement_child_Bad_ostream">ostream not good after calling child.toXML</string>
<string name="AIXMLElement_write_child_Failed_to_write_DATA">Failed to write '[DATA]', writing child data.</string>
<string name="AIXMLElement_Failed_to_write_DATA">Failed to write '[DATA]', opening new child.</string>
<string name="AIXMLElement_closing_child_Failed_to_write_DATA">Failed to write '[DATA]', closing previous child.</string>
<!-- AIXMLStream exception alerts -->
<string name="AIXMLStream_fprintf_failed_to_write_xml_header">Failed to write XML header.</string>
<!-- AIXMLParser exception alerts -->
<string name="AIXMLParser_Cannot_parse_FILEDESC_FILENAME">Cannot parse [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_No_root_node_found_in_FILEDESC_FILENAME">No root node found in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_Missing_header_NAME_invalid_FILEDESC_FILENAME">Missing header '[NAME]' ; invalid [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_Invalid_or_missing_NAME_version_attribute_in_FILEDESC_FILENAME">Invalid or missing [NAME] 'version' attribute in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_Incompatible_NAME_version_MAJOR_MINOR_in">Incompatible '[NAME]' version, [MAJOR].[MINOR], in [FILEDESC] "[FILENAME]".</string>
<!-- AIXMLElementParser exception alerts -->
<string name="AIXMLElementParser_read_string_Invalid_MD5_VALUE_in_FILEDESC_FILENAME">Invalid MD5 ([VALUE]) in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_read_string_Invalid_boolean_VALUE_in_FILEDESC_FILENAME">Invalid boolean ([VALUE]) in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_attribute_Missing_NAME_attribute_in_NODENAME_of_FILEDESC_FILENAME">Missing '[NAME]' attribute in [NODENAME] of [FILEDESC] "[FILENAME]".</string>"
<string name="AIXMLElementParser_attribute_Invalid_NAME_attribute_should_be_REQUIRED_in_NODENAME_of_FILEDESC_FILENAME">Invalid '[NAME]' attribute (should be '[REQUIRED]') in [NODENAME] of [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_read_child_Invalid_uuid_in_FILEDESC_FILENAME">Invalid UUID in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_read_child_Invalid_date_DATE_in_FILEDESC_FILENAME">Invalid DATE ([DATE]) in [FILEDESC] "[FILENAME]".</string>
<!-- AIArchetype exception alerts -->
<string name="AIArchetype_archetype_has_no_meta">archetype has no &lt;meta&gt; element.</string>
<string name="AIArchetype_MetaData_archetype_meta_has_no_ATTRIBUTE">archetype &lt;meta&gt; element has no '[ATTRIBUTE]' attribute.</string>
<string name="AIXMLdumpArchetypeXMLError">Failure dumping archetype to "[FILE]":</string>
<string name="AIXMLExportSuccess">Successfully exported wearable to "[FILE]".</string>
<string name="AIXMLExportWriteError">The export to file "[FILE]" failed:</string>
<string name="AIXMLImportRootVersionError">Fallo de Importación: el archivo "[FILE]" contiene datos linden_genepool XML con [TAG] erróneo. Se requiere Versión "[VERSIONMAJOR].0" o inferior.</string>
<string name="AIXMLImportDifferentGrid">La importación se ha realizado con exito, pero ten presente que el objeto vestible fue exportado desde el grid [EXPORTGRID] (y el grid actual es [CURRENTGRID]). ¡No se aplicaron las UUIDs de las Texturas!</string>
<string name="AIXMLImportMixedGrid">La importación se ha realizado con exito, pero ten presente que el objeto vestible fue exportado desde el grid [EXPORTGRID] (y el grid actual es [CURRENTGRID]).¡Se aplicaron las UUIDs de la Texturas pero quizás no existan aquí!</string>
<string name="AIXMLImportEmptyArchetype">Import warning: the file "[FILE]" contains a wearable of the selected type ([TYPE]), but contains no parameters or textures for that type. Nothing was imported.</string>
<string name="AIXMLImportWearableTypeMismatch">Aviso de Importación: el archivo "[FILE]" no contiene un objeto vestible de tipo [TYPE]. Éste contiene un arquetipo de tipo [ARCHETYPENAME]. Por favor, selecciona el tipo correcto antes de comenzar la importación.</string>
<string name="AIXMLImportError">Failed to import the [TYPE] wearable:</string>
<string name="AIXMLImportNoArchetypeError">No archetype found in wearable import file "[FILE]".</string>
</strings>