diff options
Diffstat (limited to 'indra/llcommon/llsdserialize.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/llcommon/llsdserialize.cpp | 446 |
1 files changed, 374 insertions, 72 deletions
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index cf337be161..d49ff0feb5 100644..100755 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -4,31 +4,25 @@ * @date 2006-03-05 * @brief Implementation of LLSD parsers and formatters * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * 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 + * Copyright (C) 2010, Linden Research, Inc. * - * 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 + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -40,6 +34,12 @@ #include <iostream> #include "apr_base64.h" +#ifdef LL_USESYSTEMLIBS +# include <zlib.h> +#else +# include "zlib/zlib.h" // for davep's dirty little zip functions +#endif + #if !LL_WINDOWS #include <netinet/in.h> // htonl & ntohl #endif @@ -55,6 +55,10 @@ static const char LEGACY_NON_HEADER[] = "<llsd>"; const std::string LLSD_BINARY_HEADER("LLSD/Binary"); const std::string LLSD_XML_HEADER("LLSD/XML"); +//used to deflate a gzipped asset (currently used for navmeshes) +#define windowBits 15 +#define ENABLE_ZLIB_GZIP 32 + /** * LLSDSerialize */ @@ -77,7 +81,7 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize break; default: - llwarns << "serialize request for unkown ELLSD_Serialize" << llendl; + LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL; } if (f.notNull()) @@ -110,7 +114,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ { legacy_no_header = true; - inbuf = str.gcount(); + inbuf = (int)str.gcount(); } else { @@ -165,7 +169,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) } else { - llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl; + LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL; } if (p.notNull()) @@ -175,7 +179,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) } fail: - llwarns << "deserialize LLSD parse failure" << llendl; + LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL; return false; } @@ -343,7 +347,7 @@ std::istream& LLSDParser::get( char delim) const { istr.get(s, n, delim); - if(mCheckLimits) mMaxBytesLeft -= istr.gcount(); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); return istr; } @@ -353,7 +357,7 @@ std::istream& LLSDParser::get( char delim) const { istr.get(sb, delim); - if(mCheckLimits) mMaxBytesLeft -= istr.gcount(); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); return istr; } @@ -377,7 +381,7 @@ std::istream& LLSDParser::read( std::streamsize n) const { istr.read(s, n); - if(mCheckLimits) mMaxBytesLeft -= istr.gcount(); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); return istr; } @@ -441,7 +445,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading map." << llendl; + LL_INFOS() << "STREAM FAILURE reading map." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -460,7 +464,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading array." << llendl; + LL_INFOS() << "STREAM FAILURE reading array." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -496,7 +500,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading boolean." << llendl; + LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -522,7 +526,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading boolean." << llendl; + LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -535,7 +539,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const data = integer; if(istr.fail()) { - llinfos << "STREAM FAILURE reading integer." << llendl; + LL_INFOS() << "STREAM FAILURE reading integer." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -549,7 +553,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const data = real; if(istr.fail()) { - llinfos << "STREAM FAILURE reading real." << llendl; + LL_INFOS() << "STREAM FAILURE reading real." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -563,7 +567,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const data = id; if(istr.fail()) { - llinfos << "STREAM FAILURE reading uuid." << llendl; + LL_INFOS() << "STREAM FAILURE reading uuid." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -578,7 +582,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading string." << llendl; + LL_INFOS() << "STREAM FAILURE reading string." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -600,7 +604,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading link." << llendl; + LL_INFOS() << "STREAM FAILURE reading link." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -623,7 +627,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading date." << llendl; + LL_INFOS() << "STREAM FAILURE reading date." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -636,15 +640,15 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading data." << llendl; + LL_INFOS() << "STREAM FAILURE reading data." << LL_ENDL; parse_count = PARSE_FAILURE; } break; default: parse_count = PARSE_FAILURE; - llinfos << "Unrecognized character while parsing: int(" << (int)c - << ")" << llendl; + LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c + << ")" << LL_ENDL; break; } if(PARSE_FAILURE == parse_count) @@ -789,7 +793,7 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const if(len) { value.resize(len); - account(fullread(istr, (char *)&value[0], len)); + account((int)fullread(istr, (char *)&value[0], len)); } c = get(istr); // strip off the trailing double-quote data = value; @@ -869,7 +873,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const { /** * Undefined: '!'<br> - * Boolean: 't' for true 'f' for false<br> + * Boolean: '1' for true '0' for false<br> * Integer: 'i' + 4 bytes network byte order<br> * Real: 'r' + 8 bytes IEEE double<br> * UUID: 'u' + 16 byte unsigned integer<br> @@ -905,7 +909,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary map." << llendl; + LL_INFOS() << "STREAM FAILURE reading binary map." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -924,7 +928,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary array." << llendl; + LL_INFOS() << "STREAM FAILURE reading binary array." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -949,7 +953,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const data = (S32)ntohl(value_nbo); if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary integer." << llendl; + LL_INFOS() << "STREAM FAILURE reading binary integer." << LL_ENDL; } break; } @@ -961,7 +965,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const data = ll_ntohd(real_nbo); if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary real." << llendl; + LL_INFOS() << "STREAM FAILURE reading binary real." << LL_ENDL; } break; } @@ -973,7 +977,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const data = id; if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary uuid." << llendl; + LL_INFOS() << "STREAM FAILURE reading binary uuid." << LL_ENDL; } break; } @@ -994,8 +998,8 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary (notation-style) string." - << llendl; + LL_INFOS() << "STREAM FAILURE reading binary (notation-style) string." + << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -1014,7 +1018,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary string." << llendl; + LL_INFOS() << "STREAM FAILURE reading binary string." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -1033,7 +1037,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const } if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary link." << llendl; + LL_INFOS() << "STREAM FAILURE reading binary link." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -1046,7 +1050,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const data = LLDate(real); if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary date." << llendl; + LL_INFOS() << "STREAM FAILURE reading binary date." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -1069,13 +1073,13 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const if(size > 0) { value.resize(size); - account(fullread(istr, (char*)&value[0], size)); + account((int)fullread(istr, (char*)&value[0], size)); } data = value; } if(istr.fail()) { - llinfos << "STREAM FAILURE reading binary." << llendl; + LL_INFOS() << "STREAM FAILURE reading binary." << LL_ENDL; parse_count = PARSE_FAILURE; } break; @@ -1083,8 +1087,8 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const default: parse_count = PARSE_FAILURE; - llinfos << "Unrecognized character while parsing: int(" << (int)c - << ")" << llendl; + LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c + << ")" << LL_ENDL; break; } if(PARSE_FAILURE == parse_count) @@ -1200,7 +1204,7 @@ bool LLSDBinaryParser::parseString( if(size) { buf.resize(size); - account(fullread(istr, &buf[0], size)); + account((int)fullread(istr, &buf[0], size)); value.assign(buf.begin(), buf.end()); } return true; @@ -1257,12 +1261,37 @@ std::string LLSDNotationFormatter::escapeString(const std::string& in) // virtual S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const { + S32 rv = format_impl(data, ostr, options, 0); + return rv; +} + +S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const +{ S32 format_count = 1; + std::string pre; + std::string post; + + if (options & LLSDFormatter::OPTIONS_PRETTY) + { + for (U32 i = 0; i < level; i++) + { + pre += " "; + } + post = "\n"; + } + switch(data.type()) { case LLSD::TypeMap: { + if (0 != level) ostr << post << pre; ostr << "{"; + std::string inner_pre; + if (options & LLSDFormatter::OPTIONS_PRETTY) + { + inner_pre = pre + " "; + } + bool need_comma = false; LLSD::map_const_iterator iter = data.beginMap(); LLSD::map_const_iterator end = data.endMap(); @@ -1270,18 +1299,18 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti { if(need_comma) ostr << ","; need_comma = true; - ostr << '\''; + ostr << post << inner_pre << '\''; serialize_string((*iter).first, ostr); ostr << "':"; - format_count += format((*iter).second, ostr); + format_count += format_impl((*iter).second, ostr, options, level + 2); } - ostr << "}"; + ostr << post << pre << "}"; break; } case LLSD::TypeArray: { - ostr << "["; + ostr << post << pre << "["; bool need_comma = false; LLSD::array_const_iterator iter = data.beginArray(); LLSD::array_const_iterator end = data.endArray(); @@ -1289,7 +1318,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti { if(need_comma) ostr << ","; need_comma = true; - format_count += format(*iter, ostr); + format_count += format_impl(*iter, ostr, options, level + 1); } ostr << "]"; break; @@ -1339,7 +1368,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti case LLSD::TypeString: ostr << '\''; - serialize_string(data.asString(), ostr); + serialize_string(data.asStringRef(), ostr); ostr << '\''; break; @@ -1356,9 +1385,26 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti case LLSD::TypeBinary: { // *FIX: memory inefficient. - std::vector<U8> buffer = data.asBinary(); + const std::vector<U8>& buffer = data.asBinary(); ostr << "b(" << buffer.size() << ")\""; - if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); + if(buffer.size()) + { + if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY) + { + std::ios_base::fmtflags old_flags = ostr.flags(); + ostr.setf( std::ios::hex, std::ios::basefield ); + ostr << "0x"; + for (int i = 0; i < buffer.size(); i++) + { + ostr << (int) buffer[i]; + } + ostr.flags(old_flags); + } + else + { + ostr.write((const char*)&buffer[0], buffer.size()); + } + } ostr << "\""; break; } @@ -1447,13 +1493,16 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option } case LLSD::TypeUUID: + { ostr.put('u'); - ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES); + LLUUID temp = data.asUUID(); + ostr.write((const char*)(&(temp.mData)), UUID_BYTES); break; + } case LLSD::TypeString: ostr.put('s'); - formatString(data.asString(), ostr); + formatString(data.asStringRef(), ostr); break; case LLSD::TypeDate: @@ -1471,9 +1520,8 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option case LLSD::TypeBinary: { - // *FIX: memory inefficient. ostr.put('b'); - std::vector<U8> buffer = data.asBinary(); + const std::vector<U8>& buffer = data.asBinary(); U32 size_nbo = htonl(buffer.size()); ostr.write((const char*)(&size_nbo), sizeof(U32)); if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); @@ -1642,7 +1690,7 @@ int deserialize_string_raw( const S32 BUF_LEN = 20; char buf[BUF_LEN]; /* Flawfinder: ignore */ istr.get(buf, BUF_LEN - 1, ')'); - count += istr.gcount(); + count += (int)istr.gcount(); int c = istr.get(); c = istr.get(); count += 2; @@ -1657,7 +1705,7 @@ int deserialize_string_raw( if(len) { buf.resize(len); - count += fullread(istr, (char *)&buf[0], len); + count += (int)fullread(istr, (char *)&buf[0], len); value.assign(buf.begin(), buf.end()); } c = istr.get(); @@ -1989,3 +2037,257 @@ std::ostream& operator<<(std::ostream& s, const LLSD& llsd) return s; } + +//dirty little zippers -- yell at davep if these are horrid + +//return a string containing gzipped bytes of binary serialized LLSD +// VERY inefficient -- creates several copies of LLSD block in memory +std::string zip_llsd(LLSD& data) +{ + std::stringstream llsd_strm; + + LLSDSerialize::toBinary(data, llsd_strm); + + const U32 CHUNK = 65536; + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION); + if (ret != Z_OK) + { + LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; + return std::string(); + } + + std::string source = llsd_strm.str(); + + U8 out[CHUNK]; + + strm.avail_in = source.size(); + strm.next_in = (U8*) source.data(); + U8* output = NULL; + + U32 cur_size = 0; + + U32 have = 0; + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + + ret = deflate(&strm, Z_FINISH); + if (ret == Z_OK || ret == Z_STREAM_END) + { //copy result into output + if (strm.avail_out >= CHUNK) + { + free(output); + LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; + return std::string(); + } + + have = CHUNK-strm.avail_out; + output = (U8*) realloc(output, cur_size+have); + memcpy(output+cur_size, out, have); + cur_size += have; + } + else + { + free(output); + LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; + return std::string(); + } + } + while (ret == Z_OK); + + std::string::size_type size = cur_size; + + std::string result((char*) output, size); + deflateEnd(&strm); + free(output); + +#if 0 //verify results work with unzip_llsd + std::istringstream test(result); + LLSD test_sd; + if (!unzip_llsd(test_sd, test, result.size())) + { + LL_ERRS() << "Invalid compression result!" << LL_ENDL; + } +#endif + + return result; +} + +//decompress a block of LLSD from provided istream +// not very efficient -- creats a copy of decompressed LLSD block in memory +// and deserializes from that copy using LLSDSerialize +bool unzip_llsd(LLSD& data, std::istream& is, S32 size) +{ + U8* result = NULL; + U32 cur_size = 0; + z_stream strm; + + const U32 CHUNK = 65536; + + U8 *in = new U8[size]; + is.read((char*) in, size); + + U8 out[CHUNK]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = size; + strm.next_in = in; + + S32 ret = inflateInit(&strm); + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) + { + inflateEnd(&strm); + free(result); + delete [] in; + return false; + } + + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&strm); + free(result); + delete [] in; + return false; + break; + } + + U32 have = CHUNK-strm.avail_out; + + result = (U8*) realloc(result, cur_size + have); + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (ret == Z_OK); + + inflateEnd(&strm); + delete [] in; + + if (ret != Z_STREAM_END) + { + free(result); + return false; + } + + //result now points to the decompressed LLSD block + { + std::string res_str((char*) result, cur_size); + + std::string deprecated_header("<? LLSD/Binary ?>"); + + if (res_str.substr(0, deprecated_header.size()) == deprecated_header) + { + res_str = res_str.substr(deprecated_header.size()+1, cur_size); + } + cur_size = res_str.size(); + + std::istringstream istr(res_str); + + if (!LLSDSerialize::fromBinary(data, istr, cur_size)) + { + LL_WARNS() << "Failed to unzip LLSD block" << LL_ENDL; + free(result); + return false; + } + } + + free(result); + return true; +} +//This unzip function will only work with a gzip header and trailer - while the contents +//of the actual compressed data is the same for either format (gzip vs zlib ), the headers +//and trailers are different for the formats. +U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size ) +{ + U8* result = NULL; + U32 cur_size = 0; + z_stream strm; + + const U32 CHUNK = 0x4000; + + U8 *in = new U8[size]; + is.read((char*) in, size); + + U8 out[CHUNK]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = size; + strm.next_in = in; + + + S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) + { + inflateEnd(&strm); + free(result); + delete [] in; + valid = false; + } + + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&strm); + free(result); + delete [] in; + valid = false; + break; + } + + U32 have = CHUNK-strm.avail_out; + + result = (U8*) realloc(result, cur_size + have); + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (ret == Z_OK); + + inflateEnd(&strm); + delete [] in; + + if (ret != Z_STREAM_END) + { + free(result); + valid = false; + return NULL; + } + + //result now points to the decompressed LLSD block + { + outsize= cur_size; + valid = true; + } + + return result; +} + + |