Merge pull request from G10h4ck/RsMemoryWrapper_JSON_fixup

Change raw memory JSON representation
This commit is contained in:
G10h4ck 2020-05-29 19:16:00 +02:00 committed by GitHub
commit 97a60865b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 53 deletions

@ -503,8 +503,16 @@ bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/,
// Binary blocks // // Binary blocks //
//============================================================================// //============================================================================//
#if __cplusplus < 201703L
/* Solve weird undefined reference error with C++ < 17 see:
* https://stackoverflow.com/questions/8016780/undefined-reference-to-static-constexpr-char
*/
/*static*/ decltype(RsTypeSerializer::RawMemoryWrapper::base64_key) constexpr
RsTypeSerializer::RawMemoryWrapper::base64_key;
/*static*/ /* without this Android compilation breaks */ /*static*/ /* without this Android compilation breaks */
constexpr uint32_t RsTypeSerializer::RawMemoryWrapper::MAX_SERIALIZED_CHUNK_SIZE; constexpr uint32_t RsTypeSerializer::RawMemoryWrapper::MAX_SERIALIZED_CHUNK_SIZE;
#endif
/*static*/ /*static*/
void RsTypeSerializer::RawMemoryWrapper::serial_process( void RsTypeSerializer::RawMemoryWrapper::serial_process(
@ -542,18 +550,7 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
ctx.mOffset += second; ctx.mOffset += second;
break; break;
case RsGenericSerializer::DESERIALIZE: case RsGenericSerializer::DESERIALIZE:
if(first || second) freshMemCheck();
{
/* Items are created anew before deserialization so buffer pointer
* must be null and size 0 at this point */
RsWarn() << __PRETTY_FUNCTION__ << " DESERIALIZE got uninitialized "
<< " or pre-allocated buffer! Buffer pointer: " << first
<< " must be null and size: " << second << " must be 0 at "
<< "this point. Does your item costructor initialize them "
<< "properly?" << std::endl;
print_stacktrace();
}
RS_SERIAL_PROCESS(second); RS_SERIAL_PROCESS(second);
if(!ctx.mOk) break; if(!ctx.mOk) break;
@ -597,44 +594,33 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
if(!ctx.mOk) break; if(!ctx.mOk) break;
std::string encodedValue; std::string encodedValue;
RsBase64::encode(first, second, encodedValue, true, false); RsBase64::encode(first, second, encodedValue, true, false);
ctx.mJson.SetString( ctx.mOk = ctx.mOk &&
encodedValue.data(), RsTypeSerializer::to_JSON(base64_key, encodedValue, ctx.mJson);
static_cast<rapidjson::SizeType>(encodedValue.length()),
ctx.mJson.GetAllocator());
break; break;
} }
case RsGenericSerializer::FROM_JSON: case RsGenericSerializer::FROM_JSON:
{ {
const bool yelding = !!( freshMemCheck();
RsSerializationFlags::YIELDING & ctx.mFlags );
if(!(ctx.mOk || yelding))
{
clear();
break;
}
if(!ctx.mJson.IsString())
{
RsErr() << __PRETTY_FUNCTION__ << " "
<< std::errc::invalid_argument << std::endl;
print_stacktrace();
ctx.mOk = false; const auto failure = [&]() -> void { ctx.mOk = false; clear(); };
clear(); const bool yielding = !!(
break; RsSerializationFlags::YIELDING & ctx.mFlags );
} if(!(ctx.mOk || yielding)) return failure();
if( ctx.mJson.GetStringLength() >
std::string encodedValue;
if(!RsTypeSerializer::from_JSON(
base64_key, encodedValue, ctx.mJson )) return failure();
if( encodedValue.length() >
RsBase64::encodedSize(MAX_SERIALIZED_CHUNK_SIZE, true) ) RsBase64::encodedSize(MAX_SERIALIZED_CHUNK_SIZE, true) )
{ {
RsErr() << __PRETTY_FUNCTION__ << " " RsErr() << __PRETTY_FUNCTION__ << " "
<< std::errc::message_size << std::endl; << std::errc::message_size << std::endl;
print_stacktrace(); print_stacktrace();
ctx.mOk = false; return failure();
clear();
break;
} }
std::string encodedValue = ctx.mJson.GetString();
std::vector<uint8_t> decoded; std::vector<uint8_t> decoded;
auto ec = RsBase64::decode(encodedValue, decoded); auto ec = RsBase64::decode(encodedValue, decoded);
if(ec) if(ec)
@ -642,9 +628,7 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl; RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl;
print_stacktrace(); print_stacktrace();
ctx.mOk = false; return failure();
clear();
break;
} }
const auto decodedSize = decoded.size(); const auto decodedSize = decoded.size();
@ -655,11 +639,8 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
break; break;
} }
if(decodedSize != second) first = reinterpret_cast<uint8_t*>(malloc(decodedSize));
{ second = static_cast<uint32_t>(decodedSize);
first = reinterpret_cast<uint8_t*>(realloc(first, decodedSize));
second = static_cast<uint32_t>(decodedSize);
}
memcpy(first, decoded.data(), second); memcpy(first, decoded.data(), second);
break; break;
@ -675,6 +656,24 @@ void RsTypeSerializer::RawMemoryWrapper::clear()
second = 0; second = 0;
} }
bool RsTypeSerializer::RawMemoryWrapper::freshMemCheck()
{
if(first || second)
{
/* Items are created anew before deserialization so buffer pointer
* must be null and size 0 at this point */
RsWarn() << __PRETTY_FUNCTION__ << " got uninitialized "
<< " or pre-allocated buffer! Buffer pointer: " << first
<< " must be null and size: " << second << " must be 0 at "
<< "this point. Does your item costructor initialize them "
<< "properly?" << std::endl;
print_stacktrace();
return false;
}
return true;
}
//============================================================================// //============================================================================//
// std::error_condition // // std::error_condition //
//============================================================================// //============================================================================//

@ -59,12 +59,17 @@ struct RsTypeSerializer
/// Maximum supported size 10MB /// Maximum supported size 10MB
static constexpr uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024; static constexpr uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024;
/** Key used for JSON serialization.
* @note Changing this value breaks JSON API retro-compatibility */
static constexpr char base64_key[] = "base64";
/// @see RsSerializable /// @see RsSerializable
void serial_process( void serial_process(
RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx ) override; RsGenericSerializer::SerializeContext& ctx ) override;
private: private:
void clear(); void clear();
bool freshMemCheck();
}; };
/// Most types are not valid sequence containers /// Most types are not valid sequence containers
@ -777,9 +782,9 @@ struct RsTypeSerializer
{ {
if(!yielding) if(!yielding)
{ {
std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName
<< "\" not found in JSON:" << std::endl << "\" not found in JSON:" << std::endl
<< jDoc << std::endl << std::endl; << jDoc << std::endl << std::endl;
print_stacktrace(); print_stacktrace();
} }
ctx.mOk = false; ctx.mOk = false;
@ -790,9 +795,9 @@ struct RsTypeSerializer
if(!v.IsObject()) if(!v.IsObject())
{ {
std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName
<< "\" has wrong type in JSON, object expected, got:" << "\" has wrong type in JSON, object expected, got:"
<< std::endl << jDoc << std::endl << std::endl; << std::endl << jDoc << std::endl << std::endl;
print_stacktrace(); print_stacktrace();
ctx.mOk = false; ctx.mOk = false;
break; break;

@ -32,6 +32,8 @@ std::ostream &operator<<(std::ostream& out, const std::error_condition& err);
# include <sstream> # include <sstream>
# include <string> # include <string>
# include "util/rsjson.h"
enum class RsLoggerCategories enum class RsLoggerCategories
{ {
DEBUG = ANDROID_LOG_DEBUG, DEBUG = ANDROID_LOG_DEBUG,
@ -55,6 +57,10 @@ struct t_RsLogger
inline stream_type& operator<<(const T& val) inline stream_type& operator<<(const T& val)
{ ostr << val; return *this; } { ostr << val; return *this; }
template<typename T>
inline stream_type& operator<<(const RsJson& val)
{ ostr << val; return *this; }
/// needed for manipulators and things like std::endl /// needed for manipulators and things like std::endl
stream_type& operator<<(std::ostream& (*pf)(std::ostream&)) stream_type& operator<<(std::ostream& (*pf)(std::ostream&))
{ {
@ -111,7 +117,7 @@ struct t_RsLogger
const auto now = system_clock::now(); const auto now = system_clock::now();
const auto sec = time_point_cast<seconds>(now); const auto sec = time_point_cast<seconds>(now);
const auto msec = duration_cast<milliseconds>(now - sec); const auto msec = duration_cast<milliseconds>(now - sec);
std::stringstream tstream; std::ostringstream tstream;
tstream << static_cast<char>(CATEGORY) << " " tstream << static_cast<char>(CATEGORY) << " "
<< sec.time_since_epoch().count() << "." << sec.time_since_epoch().count() << "."
<< std::setfill('0') << std::setw(3) << msec.count() << std::setfill('0') << std::setw(3) << msec.count()

@ -29,7 +29,7 @@
typedef rapidjson::Document RsJson; typedef rapidjson::Document RsJson;
/** /**
* Print out RsJson to a stream, use std::stringstream to get the string * Print out RsJson to a stream, use std::ostringstream to get the string
* @param[out] out output stream * @param[out] out output stream
* @param[in] jDoc JSON document to print * @param[in] jDoc JSON document to print
* @return same output stream passed as out parameter * @return same output stream passed as out parameter