PageRenderTime 141ms CodeModel.GetById 14ms app.highlight 117ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llmessage/lldatapacker.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1961 lines | 1521 code | 298 blank | 142 comment | 191 complexity | d27022382cb92e817a5d083a3dc90193 MD5 | raw file
   1/** 
   2 * @file lldatapacker.cpp
   3 * @brief Data packer implementation.
   4 *
   5 * $LicenseInfo:firstyear=2006&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "linden_common.h"
  28
  29#include "lldatapacker.h"
  30#include "llerror.h"
  31
  32#include "message.h"
  33
  34#include "v4color.h"
  35#include "v4coloru.h"
  36#include "v2math.h"
  37#include "v3math.h"
  38#include "v4math.h"
  39#include "lluuid.h"
  40
  41// *NOTE: there are functions below which use sscanf and rely on this
  42// particular value of DP_BUFSIZE. Search for '511' (DP_BUFSIZE - 1)
  43// to find them if you change this number.
  44const S32 DP_BUFSIZE = 512;
  45
  46static char DUMMY_BUFFER[128]; /*Flawfinder: ignore*/
  47
  48LLDataPacker::LLDataPacker() : mPassFlags(0), mWriteEnabled(FALSE)
  49{
  50}
  51
  52//virtual
  53void LLDataPacker::reset()
  54{
  55	llerrs << "Using unimplemented datapacker reset!" << llendl;
  56}
  57
  58//virtual
  59void LLDataPacker::dumpBufferToLog()
  60{
  61	llerrs << "dumpBufferToLog not implemented for this type!" << llendl;
  62}
  63
  64BOOL LLDataPacker::packFixed(const F32 value, const char *name,
  65							 const BOOL is_signed, const U32 int_bits, const U32 frac_bits)
  66{
  67	BOOL success = TRUE;
  68	S32 unsigned_bits = int_bits + frac_bits;
  69	S32 total_bits = unsigned_bits;
  70
  71	if (is_signed)
  72	{
  73		total_bits++;
  74	}
  75
  76	S32 min_val;
  77	U32 max_val;
  78	if (is_signed)
  79	{
  80		min_val = 1 << int_bits;
  81		min_val *= -1;
  82	}
  83	else
  84	{
  85		min_val = 0;
  86	}
  87	max_val = 1 << int_bits;
  88
  89	// Clamp to be within range
  90	F32 fixed_val = llclamp(value, (F32)min_val, (F32)max_val);
  91	if (is_signed)
  92	{
  93		fixed_val += max_val;
  94	}
  95	fixed_val *= 1 << frac_bits;
  96
  97	if (total_bits <= 8)
  98	{
  99		packU8((U8)fixed_val, name);
 100	}
 101	else if (total_bits <= 16)
 102	{
 103		packU16((U16)fixed_val, name);
 104	}
 105	else if (total_bits <= 31)
 106	{
 107		packU32((U32)fixed_val, name);
 108	}
 109	else
 110	{
 111		llerrs << "Using fixed-point packing of " << total_bits << " bits, why?!" << llendl;
 112	}
 113	return success;
 114}
 115
 116BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,
 117							   const BOOL is_signed, const U32 int_bits, const U32 frac_bits)
 118{
 119	//BOOL success = TRUE;
 120	//llinfos << "unpackFixed:" << name << " int:" << int_bits << " frac:" << frac_bits << llendl;
 121	BOOL ok = FALSE;
 122	S32 unsigned_bits = int_bits + frac_bits;
 123	S32 total_bits = unsigned_bits;
 124
 125	if (is_signed)
 126	{
 127		total_bits++;
 128	}
 129
 130	S32 min_val;
 131	U32 max_val;
 132	if (is_signed)
 133	{
 134		min_val = 1 << int_bits;
 135		min_val *= -1;
 136	}
 137	max_val = 1 << int_bits;
 138
 139	F32 fixed_val;
 140	if (total_bits <= 8)
 141	{
 142		U8 fixed_8;
 143		ok = unpackU8(fixed_8, name);
 144		fixed_val = (F32)fixed_8;
 145	}
 146	else if (total_bits <= 16)
 147	{
 148		U16 fixed_16;
 149		ok = unpackU16(fixed_16, name);
 150		fixed_val = (F32)fixed_16;
 151	}
 152	else if (total_bits <= 31)
 153	{
 154		U32 fixed_32;
 155		ok = unpackU32(fixed_32, name);
 156		fixed_val = (F32)fixed_32;
 157	}
 158	else
 159	{
 160		fixed_val = 0;
 161		llerrs << "Bad bit count: " << total_bits << llendl;
 162	}
 163
 164	//llinfos << "Fixed_val:" << fixed_val << llendl;
 165
 166	fixed_val /= (F32)(1 << frac_bits);
 167	if (is_signed)
 168	{
 169		fixed_val -= max_val;
 170	}
 171	value = fixed_val;
 172	//llinfos << "Value: " << value << llendl;
 173	return ok;
 174}
 175
 176//---------------------------------------------------------------------------
 177// LLDataPackerBinaryBuffer implementation
 178//---------------------------------------------------------------------------
 179
 180BOOL LLDataPackerBinaryBuffer::packString(const std::string& value, const char *name)
 181{
 182	BOOL success = TRUE;
 183	S32 length = value.length()+1;
 184
 185	success &= verifyLength(length, name);
 186
 187	if (mWriteEnabled) 
 188	{
 189		htonmemcpy(mCurBufferp, value.c_str(), MVT_VARIABLE, length);  
 190	}
 191	mCurBufferp += length;
 192	return success;
 193}
 194
 195
 196BOOL LLDataPackerBinaryBuffer::unpackString(std::string& value, const char *name)
 197{
 198	BOOL success = TRUE;
 199	S32 length = (S32)strlen((char *)mCurBufferp) + 1; /*Flawfinder: ignore*/
 200
 201	success &= verifyLength(length, name);
 202
 203	value = std::string((char*)mCurBufferp); // We already assume NULL termination calling strlen()
 204	
 205	mCurBufferp += length;
 206	return success;
 207}
 208
 209BOOL LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const char *name)
 210{
 211	BOOL success = TRUE;
 212	success &= verifyLength(size + 4, name);
 213
 214	if (mWriteEnabled) 
 215	{ 
 216		htonmemcpy(mCurBufferp, &size, MVT_S32, 4);  
 217	}
 218	mCurBufferp += 4;
 219	if (mWriteEnabled) 
 220	{ 
 221		htonmemcpy(mCurBufferp, value, MVT_VARIABLE, size);  
 222	}
 223	mCurBufferp += size;
 224	return success;
 225}
 226
 227
 228BOOL LLDataPackerBinaryBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)
 229{
 230	BOOL success = TRUE;
 231	success &= verifyLength(4, name);
 232	htonmemcpy(&size, mCurBufferp, MVT_S32, 4);
 233	mCurBufferp += 4;
 234	success &= verifyLength(size, name);
 235	if (success)
 236	{
 237		htonmemcpy(value, mCurBufferp, MVT_VARIABLE, size);
 238		mCurBufferp += size;
 239	}
 240	else
 241	{
 242		llwarns << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << llendl;
 243		success = FALSE;
 244	}
 245	return success;
 246}
 247
 248
 249BOOL LLDataPackerBinaryBuffer::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
 250{
 251	BOOL success = TRUE;
 252	success &= verifyLength(size, name);
 253
 254	if (mWriteEnabled) 
 255	{ 
 256		htonmemcpy(mCurBufferp, value, MVT_VARIABLE, size);  
 257	}
 258	mCurBufferp += size;
 259	return success;
 260}
 261
 262
 263BOOL LLDataPackerBinaryBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
 264{
 265	BOOL success = TRUE;
 266	success &= verifyLength(size, name);
 267	htonmemcpy(value, mCurBufferp, MVT_VARIABLE, size);
 268	mCurBufferp += size;
 269	return success;
 270}
 271
 272
 273BOOL LLDataPackerBinaryBuffer::packU8(const U8 value, const char *name)
 274{
 275	BOOL success = TRUE;
 276	success &= verifyLength(sizeof(U8), name);
 277
 278	if (mWriteEnabled) 
 279	{
 280		*mCurBufferp = value;
 281	}
 282	mCurBufferp++;
 283	return success;
 284}
 285
 286
 287BOOL LLDataPackerBinaryBuffer::unpackU8(U8 &value, const char *name)
 288{
 289	BOOL success = TRUE;
 290	success &= verifyLength(sizeof(U8), name);
 291
 292	value = *mCurBufferp;
 293	mCurBufferp++;
 294	return success;
 295}
 296
 297
 298BOOL LLDataPackerBinaryBuffer::packU16(const U16 value, const char *name)
 299{
 300	BOOL success = TRUE;
 301	success &= verifyLength(sizeof(U16), name);
 302
 303	if (mWriteEnabled) 
 304	{ 
 305		htonmemcpy(mCurBufferp, &value, MVT_U16, 2);  
 306	}
 307	mCurBufferp += 2;
 308	return success;
 309}
 310
 311
 312BOOL LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)
 313{
 314	BOOL success = TRUE;
 315	success &= verifyLength(sizeof(U16), name);
 316
 317	htonmemcpy(&value, mCurBufferp, MVT_U16, 2);
 318	mCurBufferp += 2;
 319	return success;
 320}
 321
 322
 323BOOL LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)
 324{
 325	BOOL success = TRUE;
 326	success &= verifyLength(sizeof(U32), name);
 327
 328	if (mWriteEnabled) 
 329	{ 
 330		htonmemcpy(mCurBufferp, &value, MVT_U32, 4);  
 331	}
 332	mCurBufferp += 4;
 333	return success;
 334}
 335
 336
 337BOOL LLDataPackerBinaryBuffer::unpackU32(U32 &value, const char *name)
 338{
 339	BOOL success = TRUE;
 340	success &= verifyLength(sizeof(U32), name);
 341
 342	htonmemcpy(&value, mCurBufferp, MVT_U32, 4);
 343	mCurBufferp += 4;
 344	return success;
 345}
 346
 347
 348BOOL LLDataPackerBinaryBuffer::packS32(const S32 value, const char *name)
 349{
 350	BOOL success = TRUE;
 351	success &= verifyLength(sizeof(S32), name);
 352
 353	if (mWriteEnabled) 
 354	{ 
 355		htonmemcpy(mCurBufferp, &value, MVT_S32, 4); 
 356	}
 357	mCurBufferp += 4;
 358	return success;
 359}
 360
 361
 362BOOL LLDataPackerBinaryBuffer::unpackS32(S32 &value, const char *name)
 363{
 364	BOOL success = TRUE;
 365	success &= verifyLength(sizeof(S32), name);
 366
 367	htonmemcpy(&value, mCurBufferp, MVT_S32, 4);
 368	mCurBufferp += 4;
 369	return success;
 370}
 371
 372
 373BOOL LLDataPackerBinaryBuffer::packF32(const F32 value, const char *name)
 374{
 375	BOOL success = TRUE;
 376	success &= verifyLength(sizeof(F32), name);
 377
 378	if (mWriteEnabled) 
 379	{ 
 380		htonmemcpy(mCurBufferp, &value, MVT_F32, 4); 
 381	}
 382	mCurBufferp += 4;
 383	return success;
 384}
 385
 386
 387BOOL LLDataPackerBinaryBuffer::unpackF32(F32 &value, const char *name)
 388{
 389	BOOL success = TRUE;
 390	success &= verifyLength(sizeof(F32), name);
 391
 392	htonmemcpy(&value, mCurBufferp, MVT_F32, 4);
 393	mCurBufferp += 4;
 394	return success;
 395}
 396
 397
 398BOOL LLDataPackerBinaryBuffer::packColor4(const LLColor4 &value, const char *name)
 399{
 400	BOOL success = TRUE;
 401	success &= verifyLength(16, name);
 402
 403	if (mWriteEnabled) 
 404	{ 
 405		htonmemcpy(mCurBufferp, value.mV, MVT_LLVector4, 16); 
 406	}
 407	mCurBufferp += 16;
 408	return success;
 409}
 410
 411
 412BOOL LLDataPackerBinaryBuffer::unpackColor4(LLColor4 &value, const char *name)
 413{
 414	BOOL success = TRUE;
 415	success &= verifyLength(16, name);
 416
 417	htonmemcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
 418	mCurBufferp += 16;
 419	return success;
 420}
 421
 422
 423BOOL LLDataPackerBinaryBuffer::packColor4U(const LLColor4U &value, const char *name)
 424{
 425	BOOL success = TRUE;
 426	success &= verifyLength(4, name);
 427
 428	if (mWriteEnabled) 
 429	{ 
 430		htonmemcpy(mCurBufferp, value.mV, MVT_VARIABLE, 4);  
 431	}
 432	mCurBufferp += 4;
 433	return success;
 434}
 435
 436
 437BOOL LLDataPackerBinaryBuffer::unpackColor4U(LLColor4U &value, const char *name)
 438{
 439	BOOL success = TRUE;
 440	success &= verifyLength(4, name);
 441
 442	htonmemcpy(value.mV, mCurBufferp, MVT_VARIABLE, 4);
 443	mCurBufferp += 4;
 444	return success;
 445}
 446
 447
 448
 449BOOL LLDataPackerBinaryBuffer::packVector2(const LLVector2 &value, const char *name)
 450{
 451	BOOL success = TRUE;
 452	success &= verifyLength(8, name);
 453
 454	if (mWriteEnabled) 
 455	{ 
 456		htonmemcpy(mCurBufferp, &value.mV[0], MVT_F32, 4);  
 457		htonmemcpy(mCurBufferp+4, &value.mV[1], MVT_F32, 4);  
 458	}
 459	mCurBufferp += 8;
 460	return success;
 461}
 462
 463
 464BOOL LLDataPackerBinaryBuffer::unpackVector2(LLVector2 &value, const char *name)
 465{
 466	BOOL success = TRUE;
 467	success &= verifyLength(8, name);
 468
 469	htonmemcpy(&value.mV[0], mCurBufferp, MVT_F32, 4);
 470	htonmemcpy(&value.mV[1], mCurBufferp+4, MVT_F32, 4);
 471	mCurBufferp += 8;
 472	return success;
 473}
 474
 475
 476BOOL LLDataPackerBinaryBuffer::packVector3(const LLVector3 &value, const char *name)
 477{
 478	BOOL success = TRUE;
 479	success &= verifyLength(12, name);
 480
 481	if (mWriteEnabled) 
 482	{ 
 483		htonmemcpy(mCurBufferp, value.mV, MVT_LLVector3, 12);  
 484	}
 485	mCurBufferp += 12;
 486	return success;
 487}
 488
 489
 490BOOL LLDataPackerBinaryBuffer::unpackVector3(LLVector3 &value, const char *name)
 491{
 492	BOOL success = TRUE;
 493	success &= verifyLength(12, name);
 494
 495	htonmemcpy(value.mV, mCurBufferp, MVT_LLVector3, 12);
 496	mCurBufferp += 12;
 497	return success;
 498}
 499
 500BOOL LLDataPackerBinaryBuffer::packVector4(const LLVector4 &value, const char *name)
 501{
 502	BOOL success = TRUE;
 503	success &= verifyLength(16, name);
 504
 505	if (mWriteEnabled) 
 506	{ 
 507		htonmemcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);  
 508	}
 509	mCurBufferp += 16;
 510	return success;
 511}
 512
 513
 514BOOL LLDataPackerBinaryBuffer::unpackVector4(LLVector4 &value, const char *name)
 515{
 516	BOOL success = TRUE;
 517	success &= verifyLength(16, name);
 518
 519	htonmemcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
 520	mCurBufferp += 16;
 521	return success;
 522}
 523
 524BOOL LLDataPackerBinaryBuffer::packUUID(const LLUUID &value, const char *name)
 525{
 526	BOOL success = TRUE;
 527	success &= verifyLength(16, name);
 528
 529	if (mWriteEnabled) 
 530	{ 
 531		htonmemcpy(mCurBufferp, value.mData, MVT_LLUUID, 16);  
 532	}
 533	mCurBufferp += 16;
 534	return success;
 535}
 536
 537
 538BOOL LLDataPackerBinaryBuffer::unpackUUID(LLUUID &value, const char *name)
 539{
 540	BOOL success = TRUE;
 541	success &= verifyLength(16, name);
 542
 543	htonmemcpy(value.mData, mCurBufferp, MVT_LLUUID, 16);
 544	mCurBufferp += 16;
 545	return success;
 546}
 547
 548const LLDataPackerBinaryBuffer&	LLDataPackerBinaryBuffer::operator=(const LLDataPackerBinaryBuffer &a)
 549{
 550	if (a.getBufferSize() > getBufferSize())
 551	{
 552		// We've got problems, ack!
 553		llerrs << "Trying to do an assignment with not enough room in the target." << llendl;
 554	}
 555	memcpy(mBufferp, a.mBufferp, a.getBufferSize());	/*Flawfinder: ignore*/
 556	return *this;
 557}
 558
 559void LLDataPackerBinaryBuffer::dumpBufferToLog()
 560{
 561	llwarns << "Binary Buffer Dump, size: " << mBufferSize << llendl;
 562	char line_buffer[256]; /*Flawfinder: ignore*/
 563	S32 i;
 564	S32 cur_line_pos = 0;
 565
 566	S32 cur_line = 0;
 567	for (i = 0; i < mBufferSize; i++)
 568	{
 569		snprintf(line_buffer + cur_line_pos*3, sizeof(line_buffer) - cur_line_pos*3, "%02x ", mBufferp[i]); 	/* Flawfinder: ignore */
 570		cur_line_pos++;
 571		if (cur_line_pos >= 16)
 572		{
 573			cur_line_pos = 0;
 574			llwarns << "Offset:" << std::hex << cur_line*16 << std::dec << " Data:" << line_buffer << llendl;
 575			cur_line++;
 576		}
 577	}
 578	if (cur_line_pos)
 579	{
 580		llwarns << "Offset:" << std::hex << cur_line*16 << std::dec << " Data:" << line_buffer << llendl;
 581	}
 582}
 583
 584//---------------------------------------------------------------------------
 585// LLDataPackerAsciiBuffer implementation
 586//---------------------------------------------------------------------------
 587BOOL LLDataPackerAsciiBuffer::packString(const std::string& value, const char *name)
 588{
 589	BOOL success = TRUE;
 590	writeIndentedName(name);
 591	int numCopied = 0;
 592	if (mWriteEnabled) 
 593	{
 594		numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%s\n", value.c_str());		/* Flawfinder: ignore */
 595	}
 596	else
 597	{
 598		numCopied = value.length() + 1; /*Flawfinder: ignore*/
 599	}
 600
 601	// snprintf returns number of bytes that would have been written
 602	// had the output not being truncated. In that case, it will
 603	// return either -1 or value >= passed in size value . So a check needs to be added
 604	// to detect truncation, and if there is any, only account for the
 605	// actual number of bytes written..and not what could have been
 606	// written.
 607	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 608	{
 609		// *NOTE: I believe we need to mark a failure bit at this point.
 610	    numCopied = getBufferSize()-getCurrentSize();
 611		llwarns << "LLDataPackerAsciiBuffer::packString: string truncated: " << value << llendl;
 612	}
 613	mCurBufferp += numCopied;
 614	return success;
 615}
 616
 617BOOL LLDataPackerAsciiBuffer::unpackString(std::string& value, const char *name)
 618{
 619	BOOL success = TRUE;
 620	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
 621	BOOL res = getValueStr(name, valuestr, DP_BUFSIZE); // NULL terminated
 622	if (!res) // 
 623	{
 624		return FALSE;
 625	}
 626	value = valuestr;
 627	return success;
 628}
 629
 630
 631BOOL LLDataPackerAsciiBuffer::packBinaryData(const U8 *value, S32 size, const char *name)
 632{
 633	BOOL success = TRUE;
 634	writeIndentedName(name);
 635	
 636	int numCopied = 0;
 637	if (mWriteEnabled)
 638	{
 639		numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%010d ", size);	/* Flawfinder: ignore */
 640
 641		// snprintf returns number of bytes that would have been
 642		// written had the output not being truncated. In that case,
 643		// it will retuen >= passed in size value.  so a check needs
 644		// to be added to detect truncation, and if there is any, only
 645		// account for the actual number of bytes written..and not
 646		// what could have been written.
 647		if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 648		{
 649			numCopied = getBufferSize()-getCurrentSize();
 650			llwarns << "LLDataPackerAsciiBuffer::packBinaryData: number truncated: " << size << llendl;
 651		}
 652		mCurBufferp += numCopied;
 653
 654
 655		S32 i;
 656		BOOL bBufferFull = FALSE;
 657		for (i = 0; i < size && !bBufferFull; i++)
 658		{
 659			numCopied = snprintf(mCurBufferp, getBufferSize()-getCurrentSize(), "%02x ", value[i]);	/* Flawfinder: ignore */
 660			if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 661			{
 662				numCopied = getBufferSize()-getCurrentSize();
 663				llwarns << "LLDataPackerAsciiBuffer::packBinaryData: data truncated: " << llendl;
 664				bBufferFull = TRUE;
 665			}
 666			mCurBufferp += numCopied;
 667		}
 668
 669		if (!bBufferFull)
 670		{
 671			numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(), "\n");	/* Flawfinder: ignore */
 672			if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 673		    	{
 674				numCopied = getBufferSize()-getCurrentSize();
 675				llwarns << "LLDataPackerAsciiBuffer::packBinaryData: newline truncated: " << llendl;
 676		    	}
 677		    	mCurBufferp += numCopied;
 678		}
 679	}
 680	else
 681	{
 682		// why +10 ?? XXXCHECK
 683		numCopied = 10 + 1; // size plus newline
 684		numCopied += size;
 685		if (numCopied > getBufferSize()-getCurrentSize())
 686		{
 687			numCopied = getBufferSize()-getCurrentSize();
 688		}   
 689		mCurBufferp += numCopied;
 690	}
 691	
 692	return success;
 693}
 694
 695
 696BOOL LLDataPackerAsciiBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)
 697{
 698	BOOL success = TRUE;
 699	char valuestr[DP_BUFSIZE];		/* Flawfinder: ignore */
 700	if (!getValueStr(name, valuestr, DP_BUFSIZE))
 701	{
 702		return FALSE;
 703	}
 704
 705	char *cur_pos = &valuestr[0];
 706	sscanf(valuestr,"%010d", &size);
 707	cur_pos += 11;
 708
 709	S32 i;
 710	for (i = 0; i < size; i++)
 711	{
 712		S32 val;
 713		sscanf(cur_pos,"%02x", &val);
 714		value[i] = val;
 715		cur_pos += 3;
 716	}
 717	return success;
 718}
 719
 720
 721BOOL LLDataPackerAsciiBuffer::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
 722{
 723	BOOL success = TRUE;
 724	writeIndentedName(name);
 725	
 726	if (mWriteEnabled)
 727	{
 728		S32 i;
 729		int numCopied = 0;
 730		BOOL bBufferFull = FALSE;
 731		for (i = 0; i < size && !bBufferFull; i++)
 732		{
 733			numCopied = snprintf(mCurBufferp, getBufferSize()-getCurrentSize(), "%02x ", value[i]);	/* Flawfinder: ignore */
 734			if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 735			{
 736			    numCopied = getBufferSize()-getCurrentSize();
 737				llwarns << "LLDataPackerAsciiBuffer::packBinaryDataFixed: data truncated: " << llendl;
 738			    bBufferFull = TRUE;
 739			}
 740			mCurBufferp += numCopied;
 741
 742		}
 743		if (!bBufferFull)
 744		{
 745			numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(), "\n");	/* Flawfinder: ignore */
 746			if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 747			{
 748				numCopied = getBufferSize()-getCurrentSize();
 749				llwarns << "LLDataPackerAsciiBuffer::packBinaryDataFixed: newline truncated: " << llendl;
 750			}
 751			
 752			mCurBufferp += numCopied;
 753		}
 754	}
 755	else
 756	{
 757		int numCopied = 2 * size + 1; //hex bytes plus newline 
 758		if (numCopied > getBufferSize()-getCurrentSize())
 759		{
 760			numCopied = getBufferSize()-getCurrentSize();
 761		}   
 762		mCurBufferp += numCopied;
 763	}
 764	return success;
 765}
 766
 767
 768BOOL LLDataPackerAsciiBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
 769{
 770	BOOL success = TRUE;
 771	char valuestr[DP_BUFSIZE];		/* Flawfinder: ignore */		
 772	if (!getValueStr(name, valuestr, DP_BUFSIZE))
 773	{
 774		return FALSE;
 775	}
 776
 777	char *cur_pos = &valuestr[0];
 778
 779	S32 i;
 780	for (i = 0; i < size; i++)
 781	{
 782		S32 val;
 783		sscanf(cur_pos,"%02x", &val);
 784		value[i] = val;
 785		cur_pos += 3;
 786	}
 787	return success;
 788}
 789
 790
 791
 792BOOL LLDataPackerAsciiBuffer::packU8(const U8 value, const char *name)
 793{
 794	BOOL success = TRUE;
 795	writeIndentedName(name);
 796	int numCopied = 0;
 797	if (mWriteEnabled)
 798	{
 799	    	numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d\n", value);	/* Flawfinder: ignore */
 800	}
 801	else
 802	{
 803		// just do the write to a temp buffer to get the length
 804		numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value);	/* Flawfinder: ignore */
 805	}
 806
 807	// snprintf returns number of bytes that would have been written
 808	// had the output not being truncated. In that case, it will
 809	// return either -1 or value >= passed in size value . So a check needs to be added
 810	// to detect truncation, and if there is any, only account for the
 811	// actual number of bytes written..and not what could have been
 812	// written.
 813	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 814	{
 815		numCopied = getBufferSize()-getCurrentSize();
 816		llwarns << "LLDataPackerAsciiBuffer::packU8: val truncated: " << llendl;
 817	}
 818
 819	mCurBufferp += numCopied;
 820
 821	return success;
 822}
 823
 824
 825BOOL LLDataPackerAsciiBuffer::unpackU8(U8 &value, const char *name)
 826{
 827	BOOL success = TRUE;
 828	char valuestr[DP_BUFSIZE];		/* Flawfinder: ignore */
 829	if (!getValueStr(name, valuestr, DP_BUFSIZE))
 830	{
 831		return FALSE;
 832	}
 833
 834	S32 in_val;
 835	sscanf(valuestr,"%d", &in_val);
 836	value = in_val;
 837	return success;
 838}
 839
 840BOOL LLDataPackerAsciiBuffer::packU16(const U16 value, const char *name)
 841{
 842	BOOL success = TRUE;
 843	writeIndentedName(name);
 844	int numCopied = 0;
 845	if (mWriteEnabled)
 846	{
 847	    	numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d\n", value);	/* Flawfinder: ignore */
 848	}
 849	else
 850	{
 851		numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value);	/* Flawfinder: ignore */
 852	}
 853
 854	// snprintf returns number of bytes that would have been written
 855	// had the output not being truncated. In that case, it will
 856	// return either -1 or value >= passed in size value . So a check needs to be added
 857	// to detect truncation, and if there is any, only account for the
 858	// actual number of bytes written..and not what could have been
 859	// written.
 860	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 861	{
 862		numCopied = getBufferSize()-getCurrentSize();
 863		llwarns << "LLDataPackerAsciiBuffer::packU16: val truncated: " << llendl;
 864	}
 865
 866	mCurBufferp += numCopied;
 867
 868	return success;
 869}
 870
 871
 872BOOL LLDataPackerAsciiBuffer::unpackU16(U16 &value, const char *name)
 873{
 874	BOOL success = TRUE;
 875	char valuestr[DP_BUFSIZE];		/* Flawfinder: ignore */
 876	if (!getValueStr(name, valuestr, DP_BUFSIZE))
 877	{
 878		return FALSE;
 879	}
 880
 881	S32 in_val;
 882	sscanf(valuestr,"%d", &in_val);
 883	value = in_val;
 884	return success;
 885}
 886
 887
 888BOOL LLDataPackerAsciiBuffer::packU32(const U32 value, const char *name)
 889{
 890	BOOL success = TRUE;
 891	writeIndentedName(name);
 892	int numCopied = 0;
 893	if (mWriteEnabled)
 894	{
 895	    	numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%u\n", value);	/* Flawfinder: ignore */
 896	}
 897	else
 898	{
 899		numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%u\n", value);	/* Flawfinder: ignore */
 900	}
 901	// snprintf returns number of bytes that would have been written
 902	// had the output not being truncated. In that case, it will
 903	// return either -1 or value >= passed in size value . So a check needs to be added
 904	// to detect truncation, and if there is any, only account for the
 905	// actual number of bytes written..and not what could have been
 906	// written.
 907	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 908	{
 909		numCopied = getBufferSize()-getCurrentSize();
 910		llwarns << "LLDataPackerAsciiBuffer::packU32: val truncated: " << llendl;
 911	}
 912
 913	mCurBufferp += numCopied;
 914	return success;
 915}
 916
 917
 918BOOL LLDataPackerAsciiBuffer::unpackU32(U32 &value, const char *name)
 919{
 920	BOOL success = TRUE;
 921	char valuestr[DP_BUFSIZE];		/* Flawfinder: ignore */
 922	if (!getValueStr(name, valuestr, DP_BUFSIZE))
 923	{
 924		return FALSE;
 925	}
 926
 927	sscanf(valuestr,"%u", &value);
 928	return success;
 929}
 930
 931
 932BOOL LLDataPackerAsciiBuffer::packS32(const S32 value, const char *name)
 933{
 934	BOOL success = TRUE;
 935	writeIndentedName(name);
 936	int numCopied = 0;
 937	if (mWriteEnabled)
 938	{
 939	    	numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d\n", value);	/* Flawfinder: ignore */
 940	}
 941	else
 942	{
 943		numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value);		/* Flawfinder: ignore */	
 944	}
 945	// snprintf returns number of bytes that would have been written
 946	// had the output not being truncated. In that case, it will
 947	// return either -1 or value >= passed in size value . So a check needs to be added
 948	// to detect truncation, and if there is any, only account for the
 949	// actual number of bytes written..and not what could have been
 950	// written.
 951	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 952	{
 953		numCopied = getBufferSize()-getCurrentSize();
 954		llwarns << "LLDataPackerAsciiBuffer::packS32: val truncated: " << llendl;
 955	}
 956
 957	mCurBufferp += numCopied;
 958	return success;
 959}
 960
 961
 962BOOL LLDataPackerAsciiBuffer::unpackS32(S32 &value, const char *name)
 963{
 964	BOOL success = TRUE;
 965	char valuestr[DP_BUFSIZE];		/* Flawfinder: ignore */
 966	if (!getValueStr(name, valuestr, DP_BUFSIZE))
 967	{
 968		return FALSE;
 969	}
 970
 971	sscanf(valuestr,"%d", &value);
 972	return success;
 973}
 974
 975
 976BOOL LLDataPackerAsciiBuffer::packF32(const F32 value, const char *name)
 977{
 978	BOOL success = TRUE;
 979	writeIndentedName(name);
 980	int numCopied = 0;
 981	if (mWriteEnabled)
 982	{
 983	    	numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f\n", value);		/* Flawfinder: ignore */
 984	}
 985	else
 986	{
 987		numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%f\n", value);		/* Flawfinder: ignore */	
 988	}
 989	// snprintf returns number of bytes that would have been written
 990	// had the output not being truncated. In that case, it will
 991	// return either -1 or value >= passed in size value . So a check needs to be added
 992	// to detect truncation, and if there is any, only account for the
 993	// actual number of bytes written..and not what could have been
 994	// written.
 995	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
 996	{
 997		numCopied = getBufferSize()-getCurrentSize();
 998		llwarns << "LLDataPackerAsciiBuffer::packF32: val truncated: " << llendl;
 999	}
1000
1001	mCurBufferp += numCopied;
1002	return success;
1003}
1004
1005
1006BOOL LLDataPackerAsciiBuffer::unpackF32(F32 &value, const char *name)
1007{
1008	BOOL success = TRUE;
1009	char valuestr[DP_BUFSIZE];		/* Flawfinder: ignore */
1010	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1011	{
1012		return FALSE;
1013	}
1014
1015	sscanf(valuestr,"%f", &value);
1016	return success;
1017}
1018
1019
1020BOOL LLDataPackerAsciiBuffer::packColor4(const LLColor4 &value, const char *name)
1021{
1022	BOOL success = TRUE;
1023	writeIndentedName(name);
1024	int numCopied = 0;
1025	if (mWriteEnabled)
1026	{
1027	    	numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);	/* Flawfinder: ignore */
1028	}
1029	else
1030	{
1031		numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);	/* Flawfinder: ignore */
1032	}
1033	// snprintf returns number of bytes that would have been written
1034	// had the output not being truncated. In that case, it will
1035	// return either -1 or value >= passed in size value . So a check needs to be added
1036	// to detect truncation, and if there is any, only account for the
1037	// actual number of bytes written..and not what could have been
1038	// written.
1039	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
1040	{
1041		numCopied = getBufferSize()-getCurrentSize();
1042		llwarns << "LLDataPackerAsciiBuffer::packColor4: truncated: " << llendl;
1043	}
1044
1045	mCurBufferp += numCopied;
1046	return success;
1047}
1048
1049
1050BOOL LLDataPackerAsciiBuffer::unpackColor4(LLColor4 &value, const char *name)
1051{
1052	BOOL success = TRUE;
1053	char valuestr[DP_BUFSIZE];	/* Flawfinder: ignore */
1054	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1055	{
1056		return FALSE;
1057	}
1058
1059	sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
1060	return success;
1061}
1062
1063BOOL LLDataPackerAsciiBuffer::packColor4U(const LLColor4U &value, const char *name)
1064{
1065	BOOL success = TRUE;
1066	writeIndentedName(name);
1067	int numCopied = 0;
1068	if (mWriteEnabled)
1069	{
1070		numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d %d %d %d\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);	/* Flawfinder: ignore */
1071	}
1072	else
1073	{
1074		numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%d %d %d %d\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);	/* Flawfinder: ignore */
1075	}
1076	// snprintf returns number of bytes that would have been written
1077	// had the output not being truncated. In that case, it will
1078	// return either -1 or value >= passed in size value . So a check needs to be added
1079	// to detect truncation, and if there is any, only account for the
1080	// actual number of bytes written..and not what could have been
1081	// written.
1082	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
1083	{
1084		numCopied = getBufferSize()-getCurrentSize();
1085		llwarns << "LLDataPackerAsciiBuffer::packColor4U: truncated: " << llendl;
1086	}
1087
1088	mCurBufferp += numCopied;
1089	return success;
1090}
1091
1092
1093BOOL LLDataPackerAsciiBuffer::unpackColor4U(LLColor4U &value, const char *name)
1094{
1095	BOOL success = TRUE;
1096	char valuestr[DP_BUFSIZE];	 /* Flawfinder: ignore */ 
1097	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1098	{
1099		return FALSE;
1100	}
1101
1102	S32 r, g, b, a;
1103
1104	sscanf(valuestr,"%d %d %d %d", &r, &g, &b, &a);
1105	value.mV[0] = r;
1106	value.mV[1] = g;
1107	value.mV[2] = b;
1108	value.mV[3] = a;
1109	return success;
1110}
1111
1112
1113BOOL LLDataPackerAsciiBuffer::packVector2(const LLVector2 &value, const char *name)
1114{
1115	BOOL success = TRUE;
1116	writeIndentedName(name);
1117	int numCopied = 0;
1118	if (mWriteEnabled)
1119	{
1120	    	numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f\n", value.mV[0], value.mV[1]);	/* Flawfinder: ignore */
1121	}
1122	else
1123	{
1124		numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f\n", value.mV[0], value.mV[1]);		/* Flawfinder: ignore */
1125	}
1126	// snprintf returns number of bytes that would have been written
1127	// had the output not being truncated. In that case, it will
1128	// return either -1 or value >= passed in size value . So a check needs to be added
1129	// to detect truncation, and if there is any, only account for the
1130	// actual number of bytes written..and not what could have been
1131	// written.
1132	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
1133	{
1134		numCopied = getBufferSize()-getCurrentSize();
1135		llwarns << "LLDataPackerAsciiBuffer::packVector2: truncated: " << llendl;
1136	}
1137
1138	mCurBufferp += numCopied;
1139	return success;
1140}
1141
1142
1143BOOL LLDataPackerAsciiBuffer::unpackVector2(LLVector2 &value, const char *name)
1144{
1145	BOOL success = TRUE;
1146	char valuestr[DP_BUFSIZE];	 /* Flawfinder: ignore */ 
1147	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1148	{
1149		return FALSE;
1150	}
1151
1152	sscanf(valuestr,"%f %f", &value.mV[0], &value.mV[1]);
1153	return success;
1154}
1155
1156
1157BOOL LLDataPackerAsciiBuffer::packVector3(const LLVector3 &value, const char *name)
1158{
1159	BOOL success = TRUE;
1160	writeIndentedName(name);
1161	int numCopied = 0;
1162	if (mWriteEnabled)
1163	{
1164	    	numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f %f\n", value.mV[0], value.mV[1], value.mV[2]);	/* Flawfinder: ignore */
1165	}
1166	else
1167	{
1168		numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f %f\n", value.mV[0], value.mV[1], value.mV[2]);	/* Flawfinder: ignore */
1169	}
1170	// snprintf returns number of bytes that would have been written
1171	// had the output not being truncated. In that case, it will
1172	// return either -1 or value >= passed in size value . So a check needs to be added
1173	// to detect truncation, and if there is any, only account for the
1174	// actual number of bytes written..and not what could have been
1175	// written.
1176	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
1177	{
1178	    numCopied = getBufferSize()-getCurrentSize();
1179		llwarns << "LLDataPackerAsciiBuffer::packVector3: truncated: " << llendl;
1180	}
1181
1182	mCurBufferp += numCopied;
1183	return success;
1184}
1185
1186
1187BOOL LLDataPackerAsciiBuffer::unpackVector3(LLVector3 &value, const char *name)
1188{
1189	BOOL success = TRUE;
1190	char valuestr[DP_BUFSIZE];	/* Flawfinder: ignore */ 
1191	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1192	{
1193		return FALSE;
1194	}
1195
1196	sscanf(valuestr,"%f %f %f", &value.mV[0], &value.mV[1], &value.mV[2]);
1197	return success;
1198}
1199
1200BOOL LLDataPackerAsciiBuffer::packVector4(const LLVector4 &value, const char *name)
1201{
1202	BOOL success = TRUE;
1203	writeIndentedName(name);
1204	int numCopied = 0;
1205	if (mWriteEnabled)
1206	{
1207	    	numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);	/* Flawfinder: ignore */
1208	}
1209	else
1210	{
1211		numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);	/* Flawfinder: ignore */
1212	}
1213	// snprintf returns number of bytes that would have been written
1214	// had the output not being truncated. In that case, it will
1215	// return either -1 or value >= passed in size value . So a check needs to be added
1216	// to detect truncation, and if there is any, only account for the
1217	// actual number of bytes written..and not what could have been
1218	// written.
1219	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
1220	{
1221	    numCopied = getBufferSize()-getCurrentSize();
1222		llwarns << "LLDataPackerAsciiBuffer::packVector4: truncated: " << llendl;
1223	}
1224
1225	mCurBufferp += numCopied;
1226	return success;
1227}
1228
1229
1230BOOL LLDataPackerAsciiBuffer::unpackVector4(LLVector4 &value, const char *name)
1231{
1232	BOOL success = TRUE;
1233	char valuestr[DP_BUFSIZE];	/* Flawfinder: ignore */ 
1234	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1235	{
1236		return FALSE;
1237	}
1238
1239	sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
1240	return success;
1241}
1242
1243
1244BOOL LLDataPackerAsciiBuffer::packUUID(const LLUUID &value, const char *name)
1245{
1246	BOOL success = TRUE;
1247	writeIndentedName(name);
1248
1249	int numCopied = 0;
1250	if (mWriteEnabled)
1251	{
1252		std::string tmp_str;
1253		value.toString(tmp_str);
1254		numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%s\n", tmp_str.c_str());	/* Flawfinder: ignore */
1255	}
1256	else
1257	{
1258		numCopied = 64 + 1; // UUID + newline
1259	}
1260	// snprintf returns number of bytes that would have been written
1261	// had the output not being truncated. In that case, it will
1262	// return either -1 or value >= passed in size value . So a check needs to be added
1263	// to detect truncation, and if there is any, only account for the
1264	// actual number of bytes written..and not what could have been
1265	// written.
1266	if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
1267	{
1268	    numCopied = getBufferSize()-getCurrentSize();
1269		llwarns << "LLDataPackerAsciiBuffer::packUUID: truncated: " << llendl;
1270		success = FALSE;
1271	}
1272	mCurBufferp += numCopied;
1273	return success;
1274}
1275
1276
1277BOOL LLDataPackerAsciiBuffer::unpackUUID(LLUUID &value, const char *name)
1278{
1279	BOOL success = TRUE;
1280	char valuestr[DP_BUFSIZE];	/* Flawfinder: ignore */
1281	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1282	{
1283		return FALSE;
1284	}
1285
1286	char tmp_str[64];	/* Flawfinder: ignore */
1287	sscanf(valuestr, "%63s", tmp_str);	/* Flawfinder: ignore */
1288	value.set(tmp_str);
1289
1290	return success;
1291}
1292
1293void LLDataPackerAsciiBuffer::dump()
1294{
1295	llinfos << "Buffer: " << mBufferp << llendl;
1296}
1297
1298void LLDataPackerAsciiBuffer::writeIndentedName(const char *name)
1299{
1300	if (mIncludeNames)
1301	{
1302		int numCopied = 0;
1303		if (mWriteEnabled)
1304		{
1305			numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%s\t", name);	/* Flawfinder: ignore */
1306		}
1307		else
1308		{
1309			numCopied = (S32)strlen(name) + 1; 	/* Flawfinder: ignore */ //name + tab  	
1310		}
1311
1312		// snprintf returns number of bytes that would have been written
1313		// had the output not being truncated. In that case, it will
1314		// return either -1 or value >= passed in size value . So a check needs to be added
1315		// to detect truncation, and if there is any, only account for the
1316		// actual number of bytes written..and not what could have been
1317		// written.
1318		if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
1319		{
1320			numCopied = getBufferSize()-getCurrentSize();
1321			llwarns << "LLDataPackerAsciiBuffer::writeIndentedName: truncated: " << llendl;
1322		}
1323
1324		mCurBufferp += numCopied;
1325	}
1326}
1327
1328BOOL LLDataPackerAsciiBuffer::getValueStr(const char *name, char *out_value, S32 value_len)
1329{
1330	BOOL success = TRUE;
1331	char buffer[DP_BUFSIZE];	/* Flawfinder: ignore */
1332	char keyword[DP_BUFSIZE];	/* Flawfinder: ignore */
1333	char value[DP_BUFSIZE];	/* Flawfinder: ignore */
1334
1335	buffer[0] = '\0';
1336	keyword[0] = '\0';
1337	value[0] = '\0';
1338
1339	if (mIncludeNames)
1340	{
1341		// Read both the name and the value, and validate the name.
1342		sscanf(mCurBufferp, "%511[^\n]", buffer);
1343		// Skip the \n
1344		mCurBufferp += (S32)strlen(buffer) + 1;	/* Flawfinder: ignore */
1345
1346		sscanf(buffer, "%511s %511[^\n]", keyword, value);	/* Flawfinder: ignore */
1347
1348		if (strcmp(keyword, name))
1349		{
1350			llwarns << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << llendl;
1351			return FALSE;
1352		}
1353	}
1354	else
1355	{
1356		// Just the value exists
1357		sscanf(mCurBufferp, "%511[^\n]", value);
1358		// Skip the \n
1359		mCurBufferp += (S32)strlen(value) + 1;	/* Flawfinder: ignore */
1360	}
1361
1362	S32 in_value_len = (S32)strlen(value)+1;	/* Flawfinder: ignore */
1363	S32 min_len = llmin(in_value_len, value_len);
1364	memcpy(out_value, value, min_len);	/* Flawfinder: ignore */
1365	out_value[min_len-1] = 0;
1366
1367	return success;
1368}
1369
1370// helper function used by LLDataPackerAsciiFile
1371// to convert F32 into a string. This is to avoid
1372// << operator writing F32 value into a stream 
1373// since it does not seem to preserve the float value
1374std::string convertF32ToString(F32 val)
1375{
1376	std::string str;
1377	char  buf[20];
1378	snprintf(buf, 20, "%f", val);
1379	str = buf;
1380	return str;
1381}
1382
1383//---------------------------------------------------------------------------
1384// LLDataPackerAsciiFile implementation
1385//---------------------------------------------------------------------------
1386BOOL LLDataPackerAsciiFile::packString(const std::string& value, const char *name)
1387{
1388	BOOL success = TRUE;
1389	writeIndentedName(name);
1390	if (mFP)
1391	{
1392		fprintf(mFP,"%s\n", value.c_str());	
1393	}
1394	else if (mOutputStream)
1395	{
1396		*mOutputStream << value << "\n";
1397	}
1398	return success;
1399}
1400
1401BOOL LLDataPackerAsciiFile::unpackString(std::string& value, const char *name)
1402{
1403	BOOL success = TRUE;
1404	char valuestr[DP_BUFSIZE];	/* Flawfinder: ignore */
1405	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1406	{
1407		return FALSE;
1408	}
1409	value = valuestr;
1410	return success;
1411}
1412
1413
1414BOOL LLDataPackerAsciiFile::packBinaryData(const U8 *value, S32 size, const char *name)
1415{
1416	BOOL success = TRUE;
1417	writeIndentedName(name);
1418	
1419	if (mFP)
1420	{
1421		fprintf(mFP, "%010d ", size);
1422
1423		S32 i;
1424		for (i = 0; i < size; i++)
1425		{
1426			fprintf(mFP, "%02x ", value[i]);
1427		}
1428		fprintf(mFP, "\n");
1429	}
1430	else if (mOutputStream)
1431	{
1432		char buffer[32];	/* Flawfinder: ignore */
1433		snprintf(buffer,sizeof(buffer), "%010d ", size);	/* Flawfinder: ignore */
1434		*mOutputStream << buffer;
1435
1436		S32 i;
1437		for (i = 0; i < size; i++)
1438		{
1439			snprintf(buffer, sizeof(buffer), "%02x ", value[i]);	/* Flawfinder: ignore */
1440			*mOutputStream << buffer;
1441		}
1442		*mOutputStream << "\n";
1443	}
1444	return success;
1445}
1446
1447
1448BOOL LLDataPackerAsciiFile::unpackBinaryData(U8 *value, S32 &size, const char *name)
1449{
1450	BOOL success = TRUE;
1451	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
1452	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1453	{
1454		return FALSE;
1455	}
1456
1457	char *cur_pos = &valuestr[0];
1458	sscanf(valuestr,"%010d", &size);
1459	cur_pos += 11;
1460
1461	S32 i;
1462	for (i = 0; i < size; i++)
1463	{
1464		S32 val;
1465		sscanf(cur_pos,"%02x", &val);
1466		value[i] = val;
1467		cur_pos += 3;
1468	}
1469	return success;
1470}
1471
1472
1473BOOL LLDataPackerAsciiFile::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
1474{
1475	BOOL success = TRUE;
1476	writeIndentedName(name);
1477	
1478	if (mFP)
1479	{
1480		S32 i;
1481		for (i = 0; i < size; i++)
1482		{
1483			fprintf(mFP, "%02x ", value[i]);
1484		}
1485		fprintf(mFP, "\n");
1486	}
1487	else if (mOutputStream)
1488	{
1489		char buffer[32]; /*Flawfinder: ignore*/
1490		S32 i;
1491		for (i = 0; i < size; i++)
1492		{
1493			snprintf(buffer, sizeof(buffer), "%02x ", value[i]);	/* Flawfinder: ignore */
1494			*mOutputStream << buffer;
1495		}
1496		*mOutputStream << "\n";
1497	}
1498	return success;
1499}
1500
1501
1502BOOL LLDataPackerAsciiFile::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
1503{
1504	BOOL success = TRUE;
1505	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
1506	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1507	{
1508		return FALSE;
1509	}
1510
1511	char *cur_pos = &valuestr[0];
1512
1513	S32 i;
1514	for (i = 0; i < size; i++)
1515	{
1516		S32 val;
1517		sscanf(cur_pos,"%02x", &val);
1518		value[i] = val;
1519		cur_pos += 3;
1520	}
1521	return success;
1522}
1523
1524
1525
1526BOOL LLDataPackerAsciiFile::packU8(const U8 value, const char *name)
1527{
1528	BOOL success = TRUE;
1529	writeIndentedName(name);
1530	if (mFP)
1531	{
1532		fprintf(mFP,"%d\n", value);	
1533	}
1534	else if (mOutputStream)
1535	{
1536		// We have to cast this to an integer because streams serialize
1537		// bytes as bytes - not as text.
1538		*mOutputStream << (S32)value << "\n";
1539	}
1540	return success;
1541}
1542
1543
1544BOOL LLDataPackerAsciiFile::unpackU8(U8 &value, const char *name)
1545{
1546	BOOL success = TRUE;
1547	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1548	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1549	{
1550		return FALSE;
1551	}
1552
1553	S32 in_val;
1554	sscanf(valuestr,"%d", &in_val);
1555	value = in_val;
1556	return success;
1557}
1558
1559BOOL LLDataPackerAsciiFile::packU16(const U16 value, const char *name)
1560{
1561	BOOL success = TRUE;
1562	writeIndentedName(name);
1563	if (mFP)
1564	{
1565		fprintf(mFP,"%d\n", value);	
1566	}
1567	else if (mOutputStream)
1568	{
1569		*mOutputStream <<"" << value << "\n";
1570	}
1571	return success;
1572}
1573
1574
1575BOOL LLDataPackerAsciiFile::unpackU16(U16 &value, const char *name)
1576{
1577	BOOL success = TRUE;
1578	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1579	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1580	{
1581		return FALSE;
1582	}
1583
1584	S32 in_val;
1585	sscanf(valuestr,"%d", &in_val);
1586	value = in_val;
1587	return success;
1588}
1589
1590
1591BOOL LLDataPackerAsciiFile::packU32(const U32 value, const char *name)
1592{
1593	BOOL success = TRUE;
1594	writeIndentedName(name);
1595	if (mFP)
1596	{
1597		fprintf(mFP,"%u\n", value);	
1598	}
1599	else if (mOutputStream)
1600	{
1601		*mOutputStream <<"" << value << "\n";
1602	}
1603	return success;
1604}
1605
1606
1607BOOL LLDataPackerAsciiFile::unpackU32(U32 &value, const char *name)
1608{
1609	BOOL success = TRUE;
1610	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1611	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1612	{
1613		return FALSE;
1614	}
1615
1616	sscanf(valuestr,"%u", &value);
1617	return success;
1618}
1619
1620
1621BOOL LLDataPackerAsciiFile::packS32(const S32 value, const char *name)
1622{
1623	BOOL success = TRUE;
1624	writeIndentedName(name);
1625	if (mFP)
1626	{
1627		fprintf(mFP,"%d\n", value);	
1628	}
1629	else if (mOutputStream)
1630	{
1631		*mOutputStream <<"" << value << "\n";
1632	}
1633	return success;
1634}
1635
1636
1637BOOL LLDataPackerAsciiFile::unpackS32(S32 &value, const char *name)
1638{
1639	BOOL success = TRUE;
1640	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1641	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1642	{
1643		return FALSE;
1644	}
1645
1646	sscanf(valuestr,"%d", &value);
1647	return success;
1648}
1649
1650
1651BOOL LLDataPackerAsciiFile::packF32(const F32 value, const char *name)
1652{
1653	BOOL success = TRUE;
1654	writeIndentedName(name);
1655	if (mFP)
1656	{
1657		fprintf(mFP,"%f\n", value);	
1658	}
1659	else if (mOutputStream)
1660	{
1661		*mOutputStream <<"" << convertF32ToString(value) << "\n";
1662	}
1663	return success;
1664}
1665
1666
1667BOOL LLDataPackerAsciiFile::unpackF32(F32 &value, const char *name)
1668{
1669	BOOL success = TRUE;
1670	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1671	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1672	{
1673		return FALSE;
1674	}
1675
1676	sscanf(valuestr,"%f", &value);
1677	return success;
1678}
1679
1680
1681BOOL LLDataPackerAsciiFile::packColor4(const LLColor4 &value, const char *name)
1682{
1683	BOOL success = TRUE;
1684	writeIndentedName(name);
1685	if (mFP)
1686	{
1687		fprintf(mFP,"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);	
1688	}
1689	else if (mOutputStream)
1690	{
1691		*mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << " " << convertF32ToString(value.mV[2]) << " " << convertF32ToString(value.mV[3]) << "\n";
1692	}
1693	return success;
1694}
1695
1696
1697BOOL LLDataPackerAsciiFile::unpackColor4(LLColor4 &value, const char *name)
1698{
1699	BOOL success = TRUE;
1700	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1701	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1702	{
1703		return FALSE;
1704	}
1705
1706	sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
1707	return success;
1708}
1709
1710BOOL LLDataPackerAsciiFile::packColor4U(const LLColor4U &value, const char *name)
1711{
1712	BOOL success = TRUE;
1713	writeIndentedName(name);
1714	if (mFP)
1715	{
1716		fprintf(mFP,"%d %d %d %d\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);	
1717	}
1718	else if (mOutputStream)
1719	{
1720		*mOutputStream << (S32)(value.mV[0]) << " " << (S32)(value.mV[1]) << " " << (S32)(value.mV[2]) << " " << (S32)(value.mV[3]) << "\n";
1721	}
1722	return success;
1723}
1724
1725
1726BOOL LLDataPackerAsciiFile::unpackColor4U(LLColor4U &value, const char *name)
1727{
1728	BOOL success = TRUE;
1729	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1730	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1731	{
1732		return FALSE;
1733	}
1734
1735	S32 r, g, b, a;
1736
1737	sscanf(valuestr,"%d %d %d %d", &r, &g, &b, &a);
1738	value.mV[0] = r;
1739	value.mV[1] = g;
1740	value.mV[2] = b;
1741	value.mV[3] = a;
1742	return success;
1743}
1744
1745
1746BOOL LLDataPackerAsciiFile::packVector2(const LLVector2 &value, const char *name)
1747{
1748	BOOL success = TRUE;
1749	writeIndentedName(name);
1750	if (mFP)
1751	{
1752		fprintf(mFP,"%f %f\n", value.mV[0], value.mV[1]);	
1753	}
1754	else if (mOutputStream)
1755	{
1756		*mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << "\n";
1757	}
1758	return success;
1759}
1760
1761
1762BOOL LLDataPackerAsciiFile::unpackVector2(LLVector2 &value, const char *name)
1763{
1764	BOOL success = TRUE;
1765	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1766	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1767	{
1768		return FALSE;
1769	}
1770
1771	sscanf(valuestr,"%f %f", &value.mV[0], &value.mV[1]);
1772	return success;
1773}
1774
1775
1776BOOL LLDataPackerAsciiFile::packVector3(const LLVector3 &value, const char *name)
1777{
1778	BOOL success = TRUE;
1779	writeIndentedName(name);
1780	if (mFP)
1781	{
1782		fprintf(mFP,"%f %f %f\n", value.mV[0], value.mV[1], value.mV[2]);	
1783	}
1784	else if (mOutputStream)
1785	{
1786		*mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << " " << convertF32ToString(value.mV[2]) << "\n";
1787	}
1788	return success;
1789}
1790
1791
1792BOOL LLDataPackerAsciiFile::unpackVector3(LLVector3 &value, const char *name)
1793{
1794	BOOL success = TRUE;
1795	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1796	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1797	{
1798		return FALSE;
1799	}
1800
1801	sscanf(valuestr,"%f %f %f", &value.mV[0], &value.mV[1], &value.mV[2]);
1802	return success;
1803}
1804
1805BOOL LLDataPackerAsciiFile::packVector4(const LLVector4 &value, const char *name)
1806{
1807	BOOL success = TRUE;
1808	writeIndentedName(name);
1809	if (mFP)
1810	{
1811		fprintf(mFP,"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);	
1812	}
1813	else if (mOutputStream)
1814	{
1815		*mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << " " << convertF32ToString(value.mV[2]) << " " << convertF32ToString(value.mV[3]) << "\n";
1816	}
1817	return success;
1818}
1819
1820
1821BOOL LLDataPackerAsciiFile::unpackVector4(LLVector4 &value, const char *name)
1822{
1823	BOOL success = TRUE;
1824	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1825	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1826	{
1827		return FALSE;
1828	}
1829
1830	sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
1831	return success;
1832}
1833
1834
1835BOOL LLDataPackerAsciiFile::packUUID(const LLUUID &value, const char *name)
1836{
1837	BOOL success = TRUE;
1838	writeIndentedName(name);
1839	std::string tmp_str;
1840	value.toString(tmp_str);
1841	if (mFP)
1842	{
1843		fprintf(mFP,"%s\n", tmp_str.c_str());
1844	}
1845	else if (mOutputStream)
1846	{
1847		*mOutputStream <<"" << tmp_str << "\n";
1848	}
1849	return success;
1850}
1851
1852
1853BOOL LLDataPackerAsciiFile::unpackUUID(LLUUID &value, const char *name)
1854{
1855	BOOL success = TRUE;
1856	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
1857	if (!getValueStr(name, valuestr, DP_BUFSIZE))
1858	{
1859		return FALSE;
1860	}
1861
1862	char tmp_str[64]; /*Flawfinder: ignore */
1863	sscanf(valuestr,"%63s",tmp_str);	/* Flawfinder: ignore */
1864	value.set(tmp_str);
1865
1866	return success;
1867}
1868
1869
1870void LLDataPackerAsciiFile::writeIndentedName(const char *name)
1871{
1872	std::string indent_buf;
1873	indent_buf.reserve(mIndent+1);
1874
1875	S32 i;
1876	for(i = 0; i < mIndent; i++)
1877	{
1878		indent_buf[i] = '\t';
1879	}
1880	indent_buf[i] = 0;
1881	if (mFP)
1882	{
1883		fprintf(mFP,"%s%s\t",indent_buf.c_str(), name);		
1884	}
1885	else if (mOutputStream)
1886	{
1887		*mOutputStream << indent_buf << name << "\t";
1888	}
1889}
1890
1891BOOL LLDataPackerAsciiFile::getValueStr(const char *name, char *out_value, S32 value_len)
1892{
1893	BOOL success = FALSE;
1894	char buffer[DP_BUFSIZE]; /*Flawfinder: ignore*/
1895	char keyword[DP_BUFSIZE]; /*Flawfinder: ignore*/
1896	char value[DP_BUFSIZE]; /*Flawfinder: ignore*/
1897
1898	buffer[0] = '\0';
1899	keyword[0] = '\0';
1900	value[0] = '\0';
1901
1902	if (mFP)
1903	{
1904		fpos_t last_pos;
1905		if (0 != fgetpos(mFP, &last_pos)) // 0==success for fgetpos
1906		{
1907			llwarns << "Data packer failed to fgetpos" << llendl;
1908			return FALSE;
1909		}
1910
1911		if (fgets(buffer, DP_BUFSIZE, mFP) == NULL)
1912		{
1913			buffer[0] = '\0';
1914		}
1915	
1916		sscanf(buffer, "%511s %511[^\n]", keyword, value);	/* Flawfinder: ignore */
1917	
1918		if (!keyword[0])
1919		{
1920			llwarns << "Data packer could not get the keyword!" << llendl;
1921			fsetpos(mFP, &last_pos);
1922			return FALSE;
1923		}
1924		if (strcmp(keyword, name))
1925		{
1926			llwarns << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << llendl;
1927			fsetpos(mFP, &last_pos);
1928			return FALSE;
1929		}
1930
1931		S32 in_value_len = (S32)strlen(value)+1; /*Flawfinder: ignore*/
1932		S32 min_len = llmin(in_value_len, value_len);
1933		memcpy(out_value, value, min_len); /*Flawfinder: ignore*/
1934		out_value[min_len-1] = 0;
1935		success = TRUE;
1936	}
1937	else if (mInputStream)
1938	{
1939		mInputStream->getline(buffer, DP_BUFSIZE);
1940	
1941		sscanf(buffer, "%511s %511[^\n]", keyword, value);	/* Flawfinder: ignore */
1942		if (!keyword[0])
1943		{
1944			llwarns << "Data packer could not get the keyword!" << llendl;
1945			return FALSE;
1946		}
1947		if (strcmp(keyword, name))
1948		{
1949			llwarns << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << llendl;
1950			return FALSE;
1951		}
1952
1953		S32 in_value_len = (S32)strlen(value)+1; /*Flawfinder: ignore*/
1954		S32 min_len = llmin(in_value_len, value_len);
1955		memcpy(out_value, value, min_len); /*Flawfinder: ignore*/
1956		out_value[min_len-1] = 0;
1957		success = TRUE;
1958	}
1959
1960	return success;
1961}