diff options
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/CMakeLists.txt | 75 | ||||
| -rw-r--r-- | indra/llcommon/apply.h | 115 | ||||
| -rw-r--r-- | indra/llcommon/llapp.cpp | 43 | ||||
| -rw-r--r-- | indra/llcommon/llcoros.cpp | 74 | ||||
| -rw-r--r-- | indra/llcommon/llcoros.h | 6 | ||||
| -rw-r--r-- | indra/llcommon/llerror.cpp | 2 | ||||
| -rw-r--r-- | indra/llcommon/llprocess.cpp | 8 | ||||
| -rw-r--r-- | indra/llcommon/llsd.h | 12 | ||||
| -rw-r--r-- | indra/llcommon/llsdjson.h | 2 | ||||
| -rw-r--r-- | indra/llcommon/llsdserialize.cpp | 125 | ||||
| -rw-r--r-- | indra/llcommon/llsdserialize.h | 8 | ||||
| -rw-r--r-- | indra/llcommon/llstl.h | 81 | ||||
| -rw-r--r-- | indra/llcommon/lluuid.cpp | 30 | ||||
| -rw-r--r-- | indra/llcommon/lluuid.h | 8 | ||||
| -rw-r--r-- | indra/llcommon/stringize.h | 2 | ||||
| -rw-r--r-- | indra/llcommon/tests/llleap_test.cpp | 9 | ||||
| -rw-r--r-- | indra/llcommon/threadsafeschedule.h | 2 | 
17 files changed, 296 insertions, 306 deletions
| diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 54b025b74f..54020a4231 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -14,19 +14,6 @@ include(ZLIBNG)  include(URIPARSER)  include(Tracy) -include_directories( -    ${EXPAT_INCLUDE_DIRS} -    ${LLCOMMON_INCLUDE_DIRS} -    ${JSONCPP_INCLUDE_DIR} -    ${ZLIBNG_INCLUDE_DIRS} -    ${URIPARSER_INCLUDE_DIRS} -    ${TRACY_INCLUDE_DIR} -    ) - -# add_executable(lltreeiterators lltreeiterators.cpp) -#  -# target_link_libraries(lltreeiterators -#     ${LLCOMMON_LIBRARIES})  set(llcommon_SOURCE_FILES      indra_constants.cpp @@ -273,52 +260,25 @@ if (DARWIN)    list(APPEND llcommon_SOURCE_FILES llsys_objc.mm)  endif (DARWIN) -set_source_files_properties(${llcommon_HEADER_FILES} -                            PROPERTIES HEADER_FILE_ONLY TRUE) - -if (USE_BUGSPLAT) -  set_source_files_properties(${llcommon_SOURCE_FILES} -    PROPERTIES COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") -endif (USE_BUGSPLAT) -  list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) -if(LLCOMMON_LINK_SHARED) -  add_library (llcommon SHARED ${llcommon_SOURCE_FILES}) -  if(NOT ADDRESS_SIZE EQUAL 32) -    if(WINDOWS) -      ##add_definitions(/FIXED:NO) -    else(WINDOWS) # not windows therefore gcc LINUX and DARWIN -      add_definitions(-fPIC) -    endif(WINDOWS) -  endif(NOT ADDRESS_SIZE EQUAL 32) -  if(WINDOWS) -    # always generate llcommon.pdb, even for "Release" builds -    set_target_properties(llcommon PROPERTIES LINK_FLAGS "/DEBUG") -  endif(WINDOWS) -  ll_stage_sharedlib(llcommon) -else(LLCOMMON_LINK_SHARED) -    add_library (llcommon ${llcommon_SOURCE_FILES}) -endif(LLCOMMON_LINK_SHARED) +add_library (llcommon ${llcommon_SOURCE_FILES})  target_link_libraries( -    llcommon -    ${APRUTIL_LIBRARIES} -    ${APR_LIBRARIES} -    ${EXPAT_LIBRARIES} -    ${JSONCPP_LIBRARIES} -    ${ZLIBNG_LIBRARIES} -    ${WINDOWS_LIBRARIES} -    ${BOOST_FIBER_LIBRARY} -    ${BOOST_CONTEXT_LIBRARY} -    ${BOOST_PROGRAM_OPTIONS_LIBRARY} -    ${BOOST_REGEX_LIBRARY} -    ${BOOST_SYSTEM_LIBRARY} -    ${GOOGLE_PERFTOOLS_LIBRARIES} -    ${URIPARSER_LIBRARIES} -    ${TRACY_LIBRARY} +        llcommon +        ll::apr +        ll::expat +        ll::jsoncpp +        ll::zlib-ng +        ll::boost +        ll::uriparser +        ll::oslibraries +        ll::tracy      ) +target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(llcommon PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +  add_dependencies(llcommon stage_third_party_libs)  if (LL_TESTS) @@ -329,14 +289,7 @@ if (LL_TESTS)    LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")    #set(TEST_DEBUG on) -  set(test_libs llcommon  -      ${LLCOMMON_LIBRARIES}  -      ${WINDOWS_LIBRARIES}  -      ${GOOGLEMOCK_LIBRARIES}  -      ${BOOST_FIBER_LIBRARY}  -      ${BOOST_CONTEXT_LIBRARY}  -      ${BOOST_THREAD_LIBRARY}  -      ${BOOST_SYSTEM_LIBRARY}) +  set(test_libs llcommon)    LL_ADD_INTEGRATION_TEST(bitpack "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(classic_callback "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}") diff --git a/indra/llcommon/apply.h b/indra/llcommon/apply.h new file mode 100644 index 0000000000..7c58d63bc0 --- /dev/null +++ b/indra/llcommon/apply.h @@ -0,0 +1,115 @@ +/** + * @file   apply.h + * @author Nat Goodspeed + * @date   2022-06-18 + * @brief  C++14 version of std::apply() + *  + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Copyright (c) 2022, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_APPLY_H) +#define LL_APPLY_H + +#include <boost/type_traits/function_traits.hpp> +#include <tuple> + +namespace LL +{ + +/** + * USAGE NOTE: + * https://stackoverflow.com/a/40523474/5533635 + * + * If you're trying to pass apply() a variadic function, the compiler + * complains that it can't deduce the callable type, presumably because it + * doesn't know which arity to reify to pass. + * + * But it works to wrap the variadic function in a generic lambda, e.g.: + * + * @CODE + * LL::apply( + *     [](auto&&... args) + *     { + *         return variadic(std::forward<decltype(args)>(args)...); + *     }, + *     args); + * @ENDCODE + * + * Presumably this is because there's only one instance of the generic lambda + * @em type, with a variadic <tt>operator()()</tt>. + * + * It's pointless to provide a wrapper @em function that implicitly supplies + * the generic lambda. You couldn't pass your variadic function to our wrapper + * function, for the same original reason! + * + * Instead we provide a wrapper @em macro. Sorry, Dr. Stroustrup. + */ +#define VAPPLY(FUNC, ARGS)                                          \ +    LL::apply(                                                      \ +        [](auto&&... args)                                          \ +        {                                                           \ +            return (FUNC)(std::forward<decltype(args)>(args)...);   \ +        },                                                          \ +        (ARGS)) + +#if __cplusplus >= 201703L + +// C++17 implementation +using std::apply; + +#else // C++14 + +// Derived from https://stackoverflow.com/a/20441189 +// and https://en.cppreference.com/w/cpp/utility/apply +template <typename CALLABLE, typename TUPLE, std::size_t... I> +auto apply_impl(CALLABLE&& func, TUPLE&& args, std::index_sequence<I...>) +{ +    // call func(unpacked args) +    return std::forward<CALLABLE>(func)(std::move(std::get<I>(args))...); +} + +template <typename CALLABLE, typename... ARGS> +auto apply(CALLABLE&& func, const std::tuple<ARGS...>& args) +{ +    // std::index_sequence_for is the magic sauce here, generating an argument +    // pack of indexes for each entry in args. apply_impl() can then pass +    // those to std::get() to unpack args into individual arguments. +    return apply_impl(std::forward<CALLABLE>(func), +                      args, +                      std::index_sequence_for<ARGS...>{}); +} + +// per https://stackoverflow.com/a/57510428/5533635 +template <typename CALLABLE, typename T, size_t SIZE> +auto apply(CALLABLE&& func, const std::array<T, SIZE>& args) +{ +    return apply(std::forward<CALLABLE>(func), std::tuple_cat(args)); +} + +// per https://stackoverflow.com/a/28411055/5533635 +template <typename CALLABLE, typename T, std::size_t... I> +auto apply_impl(CALLABLE&& func, const std::vector<T>& args, std::index_sequence<I...>) +{ +    return apply_impl(std::forward<CALLABLE>(func), +                      std::make_tuple(std::forward<T>(args[I])...), +                      I...); +} + +// this goes beyond C++17 std::apply() +template <typename CALLABLE, typename T> +auto apply(CALLABLE&& func, const std::vector<T>& args) +{ +    constexpr auto arity = boost::function_traits<CALLABLE>::arity; +    assert(args.size() == arity); +    return apply_impl(std::forward<CALLABLE>(func), +                      args, +                      std::make_index_sequence<arity>()); +} + +#endif // C++14 + +} // namespace LL + +#endif /* ! defined(LL_APPLY_H) */ diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index c658075a31..d839b19c99 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -68,10 +68,6 @@ void setup_signals();  void default_unix_signal_handler(int signum, siginfo_t *info, void *);  #if LL_LINUX -#include "google_breakpad/minidump_descriptor.h" -static bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc,  -                                   void* context,  -                                   bool succeeded);  #else  // Called by breakpad exception handler after the minidump has been generated.  bool unix_post_minidump_callback(const char *dump_dir, @@ -856,47 +852,8 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)  }  #if LL_LINUX -bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded) -{ -	// Copy minidump file path into fixed buffer in the app instance to avoid -	// heap allocations in a crash handler. -	 -	// path format: <dump_dir>/<minidump_id>.dmp -	 -	//HACK:  *path points to the buffer in getMiniDumpFilename which has already allocated space -	//to avoid doing allocation during crash. -	char * path = LLApp::instance()->getMiniDumpFilename(); -	int dir_path_len = strlen(path); -	 -	// The path must not be truncated. -	S32 remaining =  LLApp::MAX_MINDUMP_PATH_LENGTH - dir_path_len; - -	llassert( (remaining - strlen(minidump_desc.path())) > 5); -	 -	path += dir_path_len; - -	if (dir_path_len > 0 && path[-1] != '/') -	{ -		*path++ = '/'; -		--remaining; -	} - -	strncpy(path, minidump_desc.path(), remaining); -	 -	LL_INFOS("CRASHREPORT") << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL; -	LLApp::runErrorHandler(); -	 -#ifndef LL_RELEASE_FOR_DOWNLOAD -	clear_signals(); -	return false; -#else -	return true;  #endif -} -#endif - -  bool unix_post_minidump_callback(const char *dump_dir,  					  const char *minidump_id,  					  void *context, bool succeeded) diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 14bfb98629..70d8dfc8b9 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -288,25 +288,15 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl      return name;  } +namespace +{ +  #if LL_WINDOWS  static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name) +U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)  { -    // C++ exceptions were logged in toplevelTryWrapper, but not SEH -    // log SEH exceptions here, to make sure it gets into bugsplat's  -    // report and because __try won't allow std::string operations -    if (code != STATUS_MSC_EXCEPTION) -    { -        LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL; -    } -    // Handle bugsplat here, since GetExceptionInformation() can only be -    // called from within filter for __except(filter), not from __except's {} -    // Bugsplat should get all exceptions, C++ and SEH -    LLApp::instance()->reportCrashToBugsplat(exception_infop); - -    // Only convert non C++ exceptions.      if (code == STATUS_MSC_EXCEPTION)      {          // C++ exception, go on @@ -319,28 +309,38 @@ U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop,      }  } -void LLCoros::sehHandle(const std::string& name, const LLCoros::callable_t& callable) +void sehandle(const LLCoros::callable_t& callable)  {      __try      { -        LLCoros::toplevelTryWrapper(name, callable); +        callable();      } -    __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name)) +    __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))      { -        // convert to C++ styled exception for handlers other than bugsplat +        // convert to C++ styled exception          // Note: it might be better to use _se_set_translator          // if you want exception to inherit full callstack -        // -        // in case of bugsplat this will get to exceptionTerminateHandler and -        // looks like fiber will terminate application after that          char integer_string[512]; -        sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode()); +        sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());          throw std::exception(integer_string);      }  } -#endif -void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable) +#else  // ! LL_WINDOWS + +inline void sehandle(const LLCoros::callable_t& callable) +{ +    callable(); +} + +#endif // ! LL_WINDOWS + +} // anonymous namespace + +// Top-level wrapper around caller's coroutine callable. +// Normally we like to pass strings and such by const reference -- but in this +// case, we WANT to copy both the name and the callable to our local stack! +void LLCoros::toplevel(std::string name, callable_t callable)  {      // keep the CoroData on this top-level function's stack frame      CoroData corodata(name); @@ -350,12 +350,12 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call      // run the code the caller actually wants in the coroutine      try      { -        callable(); +        sehandle(callable);      }      catch (const Stop& exc)      {          LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " -            << exc.what() << LL_ENDL; +                            << exc.what() << LL_ENDL;      }      catch (const LLContinueError&)      { @@ -366,36 +366,14 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call      }      catch (...)      { -#if LL_WINDOWS -        // Any OTHER kind of uncaught exception will cause the viewer to -        // crash, SEH handling should catch it and report to bugsplat. -        LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); -        // to not modify callstack -        throw; -#else          // Stash any OTHER kind of uncaught exception in the rethrow() queue          // to be rethrown by the main fiber.          LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine "                              << name << LL_ENDL;          LLCoros::instance().saveException(name, std::current_exception()); -#endif      }  } -// Top-level wrapper around caller's coroutine callable. -// Normally we like to pass strings and such by const reference -- but in this -// case, we WANT to copy both the name and the callable to our local stack! -void LLCoros::toplevel(std::string name, callable_t callable) -{ -#if LL_WINDOWS -    // Because SEH can's have unwinding, need to call a wrapper -    // 'try' is inside SEH handling to not catch LLContinue -    sehHandle(name, callable); -#else -    toplevelTryWrapper(name, callable); -#endif -} -  //static  void LLCoros::checkStop()  { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index dbff921f16..966ce03296 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -307,11 +307,7 @@ public:  private:      std::string generateDistinctName(const std::string& prefix) const; -    void toplevelTryWrapper(const std::string& name, const callable_t& callable); -#if LL_WINDOWS -    void sehHandle(const std::string& name, const callable_t& callable); // calls toplevelTryWrapper -#endif -    void toplevel(std::string name, callable_t callable); // calls sehHandle or toplevelTryWrapper +    void toplevel(std::string name, callable_t callable);      struct CoroData;      static CoroData& get_CoroData(const std::string& caller);      void saveException(const std::string& name, std::exception_ptr exc); diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 310da2c9f0..02cb186275 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -941,7 +941,7 @@ namespace LLError              for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a)              {                  const LLSD& entry = *a; -                if (entry.isMap() && !entry.emptyMap()) +                if (entry.isMap() && entry.size() != 0)                  {                      ELevel level = decodeLevel(entry["level"]); diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 23936f0526..97a38ea992 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -272,6 +272,14 @@ public:  					boost::bind(&ReadPipeImpl::tick, this, _1));  	} +    ~ReadPipeImpl() +    { +        if (mConnection.connected()) +        { +            mConnection.disconnect(); +        } +    } +  	// Much of the implementation is simply connecting the abstract virtual  	// methods with implementation data concealed from the base class.  	virtual std::istream& get_istream() { return mStream; } diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index c1406cf73f..4e9fcc77ee 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -447,42 +447,42 @@ public:  	static std::string		typeString(Type type);		// Return human-readable type as a string  }; -struct llsd_select_bool : public std::unary_function<LLSD, LLSD::Boolean> +struct llsd_select_bool  {  	LLSD::Boolean operator()(const LLSD& sd) const  	{  		return sd.asBoolean();  	}  }; -struct llsd_select_integer : public std::unary_function<LLSD, LLSD::Integer> +struct llsd_select_integer  {  	LLSD::Integer operator()(const LLSD& sd) const  	{  		return sd.asInteger();  	}  }; -struct llsd_select_real : public std::unary_function<LLSD, LLSD::Real> +struct llsd_select_real  {  	LLSD::Real operator()(const LLSD& sd) const  	{  		return sd.asReal();  	}  }; -struct llsd_select_float : public std::unary_function<LLSD, F32> +struct llsd_select_float  {  	F32 operator()(const LLSD& sd) const  	{  		return (F32)sd.asReal();  	}  }; -struct llsd_select_uuid : public std::unary_function<LLSD, LLSD::UUID> +struct llsd_select_uuid  {  	LLSD::UUID operator()(const LLSD& sd) const  	{  		return sd.asUUID();  	}  }; -struct llsd_select_string : public std::unary_function<LLSD, LLSD::String> +struct llsd_select_string  {  	LLSD::String operator()(const LLSD& sd) const  	{ diff --git a/indra/llcommon/llsdjson.h b/indra/llcommon/llsdjson.h index 2be7112404..e56cf03b45 100644 --- a/indra/llcommon/llsdjson.h +++ b/indra/llcommon/llsdjson.h @@ -34,7 +34,7 @@  #include "stdtypes.h"  #include "llsd.h" -#include "value.h" +#include "json/value.h"  /// Convert a parsed JSON structure into LLSD maintaining member names and   /// array indexes. diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 046523dbb1..e7482b601d 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -34,6 +34,9 @@  #include <iostream>  #include "apr_base64.h" +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> +  #ifdef LL_USESYSTEMLIBS  # include <zlib.h>  #else @@ -2177,7 +2180,9 @@ std::string zip_llsd(LLSD& data)  		{ //copy result into output  			if (strm.avail_out >= CHUNK)  			{ -				free(output); +				deflateEnd(&strm); +				if(output) +					free(output);  				LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;  				return std::string();  			} @@ -2200,7 +2205,9 @@ std::string zip_llsd(LLSD& data)  		}  		else   		{ -			free(output); +			deflateEnd(&strm); +			if(output) +				free(output);  			LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;  			return std::string();  		} @@ -2211,7 +2218,8 @@ std::string zip_llsd(LLSD& data)  	std::string result((char*) output, size);  	deflateEnd(&strm); -	free(output); +	if(output) +		free(output);  	return result;  } @@ -2221,53 +2229,66 @@ std::string zip_llsd(LLSD& data)  // and deserializes from that copy using LLSDSerialize  LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size)  { +	std::unique_ptr<U8[]> in = std::unique_ptr<U8[]>(new(std::nothrow) U8[size]); +	if (!in) +	{ +		return ZR_MEM_ERROR; +	} +	is.read((char*) in.get(), size);  + +	return unzip_llsd(data, in.get(), size); +} + +LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size) +{  	U8* result = NULL; -	llssize cur_size = 0; +	U32 cur_size = 0;  	z_stream strm; -	const U32 CHUNK = 65536; +	constexpr U32 CHUNK = 1024 * 512; -	U8 *in = new(std::nothrow) U8[size]; -	if (!in) +	static thread_local std::unique_ptr<U8[]> out; +	if (!out)  	{ -		return ZR_MEM_ERROR; +		out = std::unique_ptr<U8[]>(new(std::nothrow) U8[CHUNK]);  	} -	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; +	strm.next_in = const_cast<U8*>(in);  	S32 ret = inflateInit(&strm);  	do  	{  		strm.avail_out = CHUNK; -		strm.next_out = out; +		strm.next_out = out.get();  		ret = inflate(&strm, Z_NO_FLUSH); -		if (ret == Z_STREAM_ERROR) +		switch (ret) +		{ +		case Z_NEED_DICT: +		case Z_DATA_ERROR:  		{  			inflateEnd(&strm);  			free(result); -			delete [] in;  			return ZR_DATA_ERROR;  		} -		 -		switch (ret) +		case Z_STREAM_ERROR: +		case Z_BUF_ERROR:  		{ -		case Z_NEED_DICT: -			ret = Z_DATA_ERROR; -		case Z_DATA_ERROR: +			inflateEnd(&strm); +			free(result); +			return ZR_BUFFER_ERROR; +		} +  		case Z_MEM_ERROR: +		{  			inflateEnd(&strm);  			free(result); -			delete [] in;  			return ZR_MEM_ERROR; -			break; +		}  		}  		U32 have = CHUNK-strm.avail_out; @@ -2280,17 +2301,15 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,  			{  				free(result);  			} -			delete[] in;  			return ZR_MEM_ERROR;  		}  		result = new_result; -		memcpy(result+cur_size, out, have); +		memcpy(result+cur_size, out.get(), have);  		cur_size += have; -	} while (ret == Z_OK); +	} while (ret == Z_OK && ret != Z_STREAM_END);  	inflateEnd(&strm); -	delete [] in;  	if (ret != Z_STREAM_END)  	{ @@ -2300,37 +2319,11 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,  	//result now points to the decompressed LLSD block  	{ -		std::istringstream istr; -		// Since we are using this for meshes, data we are dealing with tend to be large. -		// So string can potentially fail to allocate, make sure this won't cause problems -		try -		{ -			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(); - -			istr.str(res_str); -		} -#ifdef LL_WINDOWS -		catch (std::length_error) -		{ -			free(result); -			return ZR_SIZE_ERROR; -		} -#endif -		catch (std::bad_alloc&) -		{ -			free(result); -			return ZR_MEM_ERROR; -		} +		char* result_ptr = strip_deprecated_header((char*)result, cur_size); -		if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH)) +		boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size); +		 +		if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH))  		{  			free(result);  			return ZR_PARSE_ERROR; @@ -2443,3 +2436,23 @@ U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size  	return result;  } + +char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size) +{ +	const char* deprecated_header = "<? LLSD/Binary ?>"; +	constexpr size_t deprecated_header_size = 17; + +	if (cur_size > deprecated_header_size +		&& memcmp(in, deprecated_header, deprecated_header_size) == 0) +	{ +		in = in + deprecated_header_size; +		cur_size = cur_size - deprecated_header_size; +		if (header_size) +		{ +			*header_size = deprecated_header_size + 1; +		} +	} + +	return in; +} + diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index bd5ef668c0..cf6c1ab73a 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -858,14 +858,20 @@ public:          ZR_SIZE_ERROR,          ZR_DATA_ERROR,          ZR_PARSE_ERROR, +		ZR_BUFFER_ERROR, +		ZR_VERSION_ERROR      } EZipRresult;      // return OK or reason for failure      static EZipRresult unzip_llsd(LLSD& data, std::istream& is, S32 size); +	static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size);  };  //dirty little zip functions -- yell at davep  LL_COMMON_API std::string zip_llsd(LLSD& data); -LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, size_t& outsize,std::istream& is, S32 size); +LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size); + +// returns a pointer to the array or past the array if the deprecated header exists +LL_COMMON_API char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size = nullptr);  #endif // LL_LLSDSERIALIZE_H diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index a90c2c7e08..25131291f9 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -142,7 +142,7 @@ struct DeletePairedPointerArray  //                     llselect2nd<map_type::value_type>()));  template<typename T> -struct DeletePointerFunctor : public std::unary_function<T*, bool> +struct DeletePointerFunctor  {  	bool operator()(T* ptr) const  	{ @@ -153,7 +153,7 @@ struct DeletePointerFunctor : public std::unary_function<T*, bool>  // See notes about DeleteArray for why you should consider avoiding this.  template<typename T> -struct DeleteArrayFunctor : public std::unary_function<T*, bool> +struct DeleteArrayFunctor  {  	bool operator()(T* ptr) const  	{ @@ -395,16 +395,17 @@ OutputIter ll_transform_n(  // select... with the stl. Look up usage on the sgi website.  template <class _Pair> -struct _LLSelect1st : public std::unary_function<_Pair, typename _Pair::first_type> { -  const typename _Pair::first_type& operator()(const _Pair& __x) const { +struct _LLSelect1st +{ +  const auto& operator()(const _Pair& __x) const {      return __x.first;    }  };  template <class _Pair> -struct _LLSelect2nd : public std::unary_function<_Pair, typename _Pair::second_type> +struct _LLSelect2nd  { -  const typename _Pair::second_type& operator()(const _Pair& __x) const { +  const auto& operator()(const _Pair& __x) const {      return __x.second;    }  }; @@ -416,9 +417,7 @@ template <class _Pair> struct llselect2nd : public _LLSelect2nd<_Pair> {};  // compose... with the stl. Look up usage on the sgi website.  template <class _Operation1, class _Operation2> -class ll_unary_compose : -	public std::unary_function<typename _Operation2::argument_type, -							   typename _Operation1::result_type> +class ll_unary_compose  {  protected:    _Operation1 __op1; @@ -426,8 +425,9 @@ protected:  public:    ll_unary_compose(const _Operation1& __x, const _Operation2& __y)      : __op1(__x), __op2(__y) {} -  typename _Operation1::result_type -  operator()(const typename _Operation2::argument_type& __x) const { +  template <typename _Op2Arg> +  auto +  operator()(const _Op2Arg& __x) const {      return __op1(__op2(__x));    }  }; @@ -441,8 +441,7 @@ llcompose1(const _Operation1& __op1, const _Operation2& __op2)  template <class _Operation1, class _Operation2, class _Operation3>  class ll_binary_compose -  : public std::unary_function<typename _Operation2::argument_type, -							   typename _Operation1::result_type> { +{  protected:    _Operation1 _M_op1;    _Operation2 _M_op2; @@ -451,8 +450,9 @@ public:    ll_binary_compose(const _Operation1& __x, const _Operation2& __y,  					const _Operation3& __z)      : _M_op1(__x), _M_op2(__y), _M_op3(__z) { } -  typename _Operation1::result_type -  operator()(const typename _Operation2::argument_type& __x) const { +  template<typename OP2ARG> +  auto +  operator()(const OP2ARG& __x) const {      return _M_op1(_M_op2(__x), _M_op3(__x));    }  }; @@ -468,54 +468,51 @@ llcompose2(const _Operation1& __op1, const _Operation2& __op2,  // helpers to deal with the fact that MSDev does not package  // bind... with the stl. Again, this is from sgi. -template <class _Operation> -class llbinder1st : -	public std::unary_function<typename _Operation::second_argument_type, -							   typename _Operation::result_type> { +template <class _Operation, typename _Arg1> +class llbinder1st +{  protected:    _Operation op; -  typename _Operation::first_argument_type value; +  _Arg1 value;  public: -  llbinder1st(const _Operation& __x, -			  const typename _Operation::first_argument_type& __y) +  llbinder1st(const _Operation& __x, const _Arg1& __y)        : op(__x), value(__y) {} -	typename _Operation::result_type -	operator()(const typename _Operation::second_argument_type& __x) const { -		return op(value, __x); -	} +    template <typename _Arg2> +    auto +    operator()(const _Arg2& __x) const { +        return op(value, __x); +    }  };  template <class _Operation, class _Tp> -inline llbinder1st<_Operation> +inline auto  llbind1st(const _Operation& __oper, const _Tp& __x)  { -  typedef typename _Operation::first_argument_type _Arg1_type; -  return llbinder1st<_Operation>(__oper, _Arg1_type(__x)); +  return llbinder1st<_Operation, _Tp>(__oper, __x);  } -template <class _Operation> +template <class _Operation, typename _Arg2>  class llbinder2nd -	: public std::unary_function<typename _Operation::first_argument_type, -								 typename _Operation::result_type> { +{  protected:  	_Operation op; -	typename _Operation::second_argument_type value; +	_Arg2 value;  public:  	llbinder2nd(const _Operation& __x, -				const typename _Operation::second_argument_type& __y) +				const _Arg2& __y)  		: op(__x), value(__y) {} -	typename _Operation::result_type -	operator()(const typename _Operation::first_argument_type& __x) const { +	template <typename _Arg1> +	auto +	operator()(const _Arg1& __x) const {  		return op(__x, value);  	}  };  template <class _Operation, class _Tp> -inline llbinder2nd<_Operation> +inline auto  llbind2nd(const _Operation& __oper, const _Tp& __x)  { -  typedef typename _Operation::second_argument_type _Arg2_type; -  return llbinder2nd<_Operation>(__oper, _Arg2_type(__x)); +  return llbinder2nd<_Operation, _Tp>(__oper, __x);  }  /** @@ -548,8 +545,7 @@ bool before(const std::type_info* lhs, const std::type_info* rhs)  namespace std  {  	template <> -	struct less<const std::type_info*>: -		public std::binary_function<const std::type_info*, const std::type_info*, bool> +	struct less<const std::type_info*>  	{  		bool operator()(const std::type_info* lhs, const std::type_info* rhs) const  		{ @@ -558,8 +554,7 @@ namespace std  	};  	template <> -	struct less<std::type_info*>: -		public std::binary_function<std::type_info*, std::type_info*, bool> +	struct less<std::type_info*>  	{  		bool operator()(std::type_info* lhs, std::type_info* rhs) const  		{ diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index adf31b2d28..5655e8e2f2 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -1003,36 +1003,6 @@ LLUUID::LLUUID()  	return !(word[0] | word[1] | word[2] | word[3]);  } -// Copy constructor - LLUUID::LLUUID(const LLUUID& rhs) -{ -	U32 *tmp = (U32 *)mData; -	U32 *rhstmp = (U32 *)rhs.mData; -	tmp[0] = rhstmp[0]; -	tmp[1] = rhstmp[1]; -	tmp[2] = rhstmp[2]; -	tmp[3] = rhstmp[3]; -} - - LLUUID::~LLUUID() -{ -} - -// Assignment - LLUUID& LLUUID::operator=(const LLUUID& rhs) -{ -	// No need to check the case where this==&rhs.  The branch is slower than the write. -	U32 *tmp = (U32 *)mData; -	U32 *rhstmp = (U32 *)rhs.mData; -	tmp[0] = rhstmp[0]; -	tmp[1] = rhstmp[1]; -	tmp[2] = rhstmp[2]; -	tmp[3] = rhstmp[3]; -	 -	return *this; -} - -   LLUUID::LLUUID(const char *in_string)  {  	if (!in_string || in_string[0] == 0) diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index 0d4896ee97..80597fa186 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -55,10 +55,7 @@ public:  	LLUUID();  	explicit LLUUID(const char *in_string); // Convert from string.  	explicit LLUUID(const std::string& in_string); // Convert from string. -	LLUUID(const LLUUID &in); -	LLUUID &operator=(const LLUUID &rhs); - -	~LLUUID(); +	~LLUUID() = default;  	//  	// MANIPULATORS @@ -139,6 +136,9 @@ public:  	U8 mData[UUID_BYTES];  }; +static_assert(std::is_trivially_copyable<LLUUID>::value, "LLUUID must be trivial copy"); +static_assert(std::is_trivially_move_assignable<LLUUID>::value, "LLUUID must be trivial move"); +static_assert(std::is_standard_layout<LLUUID>::value, "LLUUID must be a standard layout type");  typedef std::vector<LLUUID> uuid_vec_t;  typedef std::set<LLUUID> uuid_set_t; diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h index 12df693910..c0b13135f9 100644 --- a/indra/llcommon/stringize.h +++ b/indra/llcommon/stringize.h @@ -30,7 +30,7 @@  #define LL_STRINGIZE_H  #include <sstream> -#include <llstring.h> +#include "llstring.h"  #include <boost/call_traits.hpp>  /** diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index 6c799b7993..3ae48a2532 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -15,10 +15,10 @@  #include "llleap.h"  // STL headers  // std headers +#include <functional>  // external library headers  #include <boost/assign/list_of.hpp>  #include <boost/phoenix/core/argument.hpp> -#include <boost/foreach.hpp>  // other Linden headers  #include "../test/lltut.h"  #include "../test/namedtempfile.h" @@ -29,7 +29,6 @@  #include "llstring.h"  #include "stringize.h"  #include "StringVec.h" -#include <functional>  using boost::assign::list_of; @@ -241,9 +240,9 @@ namespace tut                               "import sys\n"                               "sys.stderr.write('''Hello from Python!\n"                               "note partial line''')\n"); +        StringVec vcommand{ PYTHON, script.getName() };          CaptureLog log(LLError::LEVEL_INFO); -        waitfor(LLLeap::create(get_test_name(), -                               sv(list_of(PYTHON)(script.getName())))); +        waitfor(LLLeap::create(get_test_name(), vcommand));          log.messageWith("Hello from Python!");          log.messageWith("note partial line");      } @@ -531,7 +530,7 @@ namespace tut          result.ensure();      } -    struct TestLargeMessage: public std::binary_function<size_t, size_t, bool> +    struct TestLargeMessage      {          TestLargeMessage(const std::string& PYTHON_, const std::string& reader_module_,                           const std::string& test_name_): diff --git a/indra/llcommon/threadsafeschedule.h b/indra/llcommon/threadsafeschedule.h index 2d82d6a15e..92bc7da940 100644 --- a/indra/llcommon/threadsafeschedule.h +++ b/indra/llcommon/threadsafeschedule.h @@ -248,7 +248,7 @@ namespace LL                  TimePoint until = TimePoint::clock::now() + std::chrono::hours(24);                  pop_result popped = tryPopUntil_(lock, until, tt);                  if (popped == POPPED) -                    return std::move(tt); +                    return tt;                  // DONE: throw, just as super::pop() does                  if (popped == DONE) | 
