Files
SingularityViewer/indra/llinventory/llsaleinfo.cpp
Aleric Inglewood 474acdbff9 Add support for libcwd.
This patch has no influence if you don't have libcwd installed.
Note that libcwd (http://libcwd.sourceforge.net/) is only
available for linux.

A default compile of libcwd does memory allocation tracking,
which is too slow for everyday usage of the viewer (usable,
but notably slower) and we don't need that. Configure your
libcwd as follows:

./configure --prefix=/sl/usr --disable-alloc --enable-optimize

Or whatever prefix you prefer (add --enable-maintainer-mode
if you're compiling it from the SVN repository), add
--disable-nonthreading to compile twice as fast.

If you have it installed you can activate it's use by setting a
few environment variables:

CXXFLAGS="$(pkg-config --cflags libcwd_r)"
LDFLAGS="$(pkg-config --libs libcwd_r) -lpthread"

and then reconfiguring the viewer.

The -lpthread is needed when using ld.gold, however, if you
leave it out you might get an LDFLAGS that ends on trailing
whitespaces, which doesn't work for some reason.

Also, if you installed it in a non-standard place (/sl/usr
above) then you need this to run the viewer (and tests):

export LD_LIBRARY_PATH="/sl/usr/lib"
2011-05-08 17:08:48 +02:00

425 lines
10 KiB
C++

/**
* @file llsaleinfo.cpp
* @brief
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* 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, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include <iostream>
#include "llsaleinfo.h"
#include "llerror.h"
#include "message.h"
#include "llsdutil.h"
// use this to avoid temporary object creation
const LLSaleInfo LLSaleInfo::DEFAULT;
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
const char* FOR_SALE_NAMES[] =
{
"not",
"orig",
"copy",
"cntn"
};
///----------------------------------------------------------------------------
/// Class llsaleinfo
///----------------------------------------------------------------------------
// Default constructor
LLSaleInfo::LLSaleInfo() :
mSaleType(LLSaleInfo::FS_NOT),
mSalePrice(DEFAULT_PRICE)
{
}
LLSaleInfo::LLSaleInfo(EForSale sale_type, S32 sale_price) :
mSaleType(sale_type),
mSalePrice(sale_price)
{
mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
}
BOOL LLSaleInfo::isForSale() const
{
return (FS_NOT != mSaleType);
}
U32 LLSaleInfo::getCRC32() const
{
U32 rv = (U32)mSalePrice;
rv += (mSaleType * 0x07073096);
return rv;
}
BOOL LLSaleInfo::exportFile(LLFILE* fp) const
{
fprintf(fp, "\tsale_info\t0\n\t{\n");
fprintf(fp, "\t\tsale_type\t%s\n", lookup(mSaleType));
fprintf(fp, "\t\tsale_price\t%d\n", mSalePrice);
fprintf(fp,"\t}\n");
return TRUE;
}
BOOL LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const
{
output_stream << "\tsale_info\t0\n\t{\n";
output_stream << "\t\tsale_type\t" << lookup(mSaleType) << "\n";
output_stream << "\t\tsale_price\t" << mSalePrice << "\n";
output_stream <<"\t}\n";
return TRUE;
}
LLSD LLSaleInfo::asLLSD() const
{
LLSD sd = LLSD();
sd["sale_type"] = lookup(mSaleType);
sd["sale_price"] = mSalePrice;
return sd;
}
bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask)
{
const char *w;
if (sd["sale_type"].isString())
{
mSaleType = lookup(sd["sale_type"].asString().c_str());
}
else if(sd["sale_type"].isInteger())
{
S8 type = (U8)sd["sale_type"].asInteger();
mSaleType = static_cast<LLSaleInfo::EForSale>(type);
}
mSalePrice = llclamp(sd["sale_price"].asInteger(), 0, S32_MAX);
w = "perm_mask";
if (sd.has(w))
{
has_perm_mask = TRUE;
perm_mask = ll_U32_from_sd(sd[w]);
}
return true;
}
LLXMLNode *LLSaleInfo::exportFileXML() const
{
LLXMLNode *ret = new LLXMLNode("sale_info", FALSE);
std::string type_str = ll_safe_string( lookup(mSaleType));
ret->createChild("type", TRUE)->setStringValue(1, &type_str);
ret->createChild("price", TRUE)->setIntValue(1, &mSalePrice);
return ret;
}
BOOL LLSaleInfo::importXML(LLXMLNode* node)
{
BOOL success = FALSE;
if (node)
{
success = TRUE;
LLXMLNodePtr sub_node;
if (node->getChild("type", sub_node))
{
mSaleType = lookup(sub_node->getValue().c_str());
}
if (node->getChild("price", sub_node))
{
success &= (1 == sub_node->getIntValue(1, &mSalePrice));
}
if (!success)
{
lldebugs << "LLSaleInfo::importXML() failed for node named '"
<< node->getName() << "'" << llendl;
}
}
return success;
}
BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask)
{
has_perm_mask = FALSE;
// *NOTE: Changing the buffer size will require changing the scanf
// calls below.
char buffer[MAX_STRING]; /* Flawfinder: ignore */
char keyword[MAX_STRING]; /* Flawfinder: ignore */
char valuestr[MAX_STRING]; /* Flawfinder: ignore */
BOOL success = TRUE;
keyword[0] = '\0';
valuestr[0] = '\0';
while(success && (!feof(fp)))
{
if (fgets(buffer, MAX_STRING, fp) == NULL)
{
buffer[0] = '\0';
}
sscanf( /* Flawfinder: ignore */
buffer,
" %254s %254s",
keyword, valuestr);
if(!keyword[0])
{
continue;
}
if(0 == strcmp("{",keyword))
{
continue;
}
if(0 == strcmp("}", keyword))
{
break;
}
else if(0 == strcmp("sale_type", keyword))
{
mSaleType = lookup(valuestr);
}
else if(0 == strcmp("sale_price", keyword))
{
sscanf(valuestr, "%d", &mSalePrice);
mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
}
else if (!strcmp("perm_mask", keyword))
{
//llinfos << "found deprecated keyword perm_mask" << llendl;
has_perm_mask = TRUE;
sscanf(valuestr, "%x", &perm_mask);
}
else
{
llwarns << "unknown keyword '" << keyword
<< "' in sale info import" << llendl;
}
}
return success;
}
BOOL LLSaleInfo::importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask)
{
has_perm_mask = FALSE;
// *NOTE: Changing the buffer size will require changing the scanf
// calls below.
char buffer[MAX_STRING]; /* Flawfinder: ignore */
char keyword[MAX_STRING]; /* Flawfinder: ignore */
char valuestr[MAX_STRING]; /* Flawfinder: ignore */
BOOL success = TRUE;
keyword[0] = '\0';
valuestr[0] = '\0';
while(success && input_stream.good())
{
input_stream.getline(buffer, MAX_STRING);
sscanf( /* Flawfinder: ignore */
buffer,
" %254s %254s",
keyword, valuestr);
if(!keyword[0])
{
continue;
}
if(0 == strcmp("{",keyword))
{
continue;
}
if(0 == strcmp("}", keyword))
{
break;
}
else if(0 == strcmp("sale_type", keyword))
{
mSaleType = lookup(valuestr);
}
else if(0 == strcmp("sale_price", keyword))
{
sscanf(valuestr, "%d", &mSalePrice);
mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
}
else if (!strcmp("perm_mask", keyword))
{
//llinfos << "found deprecated keyword perm_mask" << llendl;
has_perm_mask = TRUE;
sscanf(valuestr, "%x", &perm_mask);
}
else
{
llwarns << "unknown keyword '" << keyword
<< "' in sale info import" << llendl;
}
}
return success;
}
void LLSaleInfo::setSalePrice(S32 price)
{
mSalePrice = price;
mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
}
LLSD LLSaleInfo::packMessage() const
{
LLSD result;
U8 sale_type = static_cast<U8>(mSaleType);
result["sale-type"] = (U8)sale_type;
result["sale-price"] = (S32)mSalePrice;
//result[_PREHASH_NextOwnerMask] = mNextOwnerPermMask;
return result;
}
void LLSaleInfo::packMessage(LLMessageSystem* msg) const
{
U8 sale_type = static_cast<U8>(mSaleType);
msg->addU8Fast(_PREHASH_SaleType, sale_type);
msg->addS32Fast(_PREHASH_SalePrice, mSalePrice);
//msg->addU32Fast(_PREHASH_NextOwnerMask, mNextOwnerPermMask);
}
void LLSaleInfo::unpackMessage(LLSD sales)
{
U8 sale_type = (U8)sales["sale-type"].asInteger();
mSaleType = static_cast<EForSale>(sale_type);
mSalePrice = (S32)sales["sale-price"].asInteger();
mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
//msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask);
}
void LLSaleInfo::unpackMessage(LLMessageSystem* msg, const char* block)
{
U8 sale_type;
msg->getU8Fast(block, _PREHASH_SaleType, sale_type);
mSaleType = static_cast<EForSale>(sale_type);
msg->getS32Fast(block, _PREHASH_SalePrice, mSalePrice);
mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
//msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask);
}
void LLSaleInfo::unpackMultiMessage(LLMessageSystem* msg, const char* block,
S32 block_num)
{
U8 sale_type;
msg->getU8Fast(block, _PREHASH_SaleType, sale_type, block_num);
mSaleType = static_cast<EForSale>(sale_type);
msg->getS32Fast(block, _PREHASH_SalePrice, mSalePrice, block_num);
mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
//msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask, block_num);
}
LLSaleInfo::EForSale LLSaleInfo::lookup(const char* name)
{
for(S32 i = 0; i < FS_COUNT; i++)
{
if(0 == strcmp(name, FOR_SALE_NAMES[i]))
{
// match
return (EForSale)i;
}
}
return FS_NOT;
}
const char* LLSaleInfo::lookup(EForSale type)
{
if((type >= 0) && (type < FS_COUNT))
{
return FOR_SALE_NAMES[S32(type)];
}
else
{
return NULL;
}
}
// Allow accumulation of sale info. The price of each is added,
// conflict in sale type results in FS_NOT, and the permissions are
// tightened.
void LLSaleInfo::accumulate(const LLSaleInfo& sale_info)
{
if(mSaleType != sale_info.mSaleType)
{
mSaleType = FS_NOT;
}
mSalePrice += sale_info.mSalePrice;
//mNextOwnerPermMask &= sale_info.mNextOwnerPermMask;
}
bool LLSaleInfo::operator==(const LLSaleInfo &rhs) const
{
return (
(mSaleType == rhs.mSaleType) &&
(mSalePrice == rhs.mSalePrice)
);
}
bool LLSaleInfo::operator!=(const LLSaleInfo &rhs) const
{
return (
(mSaleType != rhs.mSaleType) ||
(mSalePrice != rhs.mSalePrice)
);
}
///----------------------------------------------------------------------------
/// Local function definitions
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
/// exported functions
///----------------------------------------------------------------------------
static const std::string ST_TYPE_LABEL("sale_type");
static const std::string ST_PRICE_LABEL("sale_price");
LLSD ll_create_sd_from_sale_info(const LLSaleInfo& sale)
{
LLSD rv;
const char* type = LLSaleInfo::lookup(sale.getSaleType());
if(!type) type = LLSaleInfo::lookup(LLSaleInfo::FS_NOT);
rv[ST_TYPE_LABEL] = type;
rv[ST_PRICE_LABEL] = sale.getSalePrice();
return rv;
}
LLSaleInfo ll_sale_info_from_sd(const LLSD& sd)
{
LLSaleInfo rv;
rv.setSaleType(LLSaleInfo::lookup(sd[ST_TYPE_LABEL].asString().c_str()));
rv.setSalePrice(llclamp((S32)sd[ST_PRICE_LABEL], 0, S32_MAX));
return rv;
}