mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Change raw memory JSON representation
Fix bug reported by b1rdG The new way permits to add more formats in the future without breaking retro-compatibility again. Add support for RsJson in rsdebug for Android
This commit is contained in:
parent
968f234bfd
commit
c1c303218c
@ -503,8 +503,16 @@ bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/,
|
||||
// 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 */
|
||||
constexpr uint32_t RsTypeSerializer::RawMemoryWrapper::MAX_SERIALIZED_CHUNK_SIZE;
|
||||
#endif
|
||||
|
||||
/*static*/
|
||||
void RsTypeSerializer::RawMemoryWrapper::serial_process(
|
||||
@ -542,18 +550,7 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
|
||||
ctx.mOffset += second;
|
||||
break;
|
||||
case RsGenericSerializer::DESERIALIZE:
|
||||
if(first || second)
|
||||
{
|
||||
/* 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();
|
||||
}
|
||||
freshMemCheck();
|
||||
|
||||
RS_SERIAL_PROCESS(second);
|
||||
if(!ctx.mOk) break;
|
||||
@ -597,44 +594,33 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
|
||||
if(!ctx.mOk) break;
|
||||
std::string encodedValue;
|
||||
RsBase64::encode(first, second, encodedValue, true, false);
|
||||
ctx.mJson.SetString(
|
||||
encodedValue.data(),
|
||||
static_cast<rapidjson::SizeType>(encodedValue.length()),
|
||||
ctx.mJson.GetAllocator());
|
||||
ctx.mOk = ctx.mOk &&
|
||||
RsTypeSerializer::to_JSON(base64_key, encodedValue, ctx.mJson);
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::FROM_JSON:
|
||||
{
|
||||
const bool yelding = !!(
|
||||
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();
|
||||
freshMemCheck();
|
||||
|
||||
ctx.mOk = false;
|
||||
clear();
|
||||
break;
|
||||
}
|
||||
if( ctx.mJson.GetStringLength() >
|
||||
const auto failure = [&]() -> void { ctx.mOk = false; clear(); };
|
||||
const bool yielding = !!(
|
||||
RsSerializationFlags::YIELDING & ctx.mFlags );
|
||||
if(!(ctx.mOk || yielding)) return failure();
|
||||
|
||||
std::string encodedValue;
|
||||
if(!RsTypeSerializer::from_JSON(
|
||||
base64_key, encodedValue, ctx.mJson )) return failure();
|
||||
|
||||
if( encodedValue.length() >
|
||||
RsBase64::encodedSize(MAX_SERIALIZED_CHUNK_SIZE, true) )
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " "
|
||||
<< std::errc::message_size << std::endl;
|
||||
print_stacktrace();
|
||||
|
||||
ctx.mOk = false;
|
||||
clear();
|
||||
break;
|
||||
return failure();
|
||||
}
|
||||
|
||||
std::string encodedValue = ctx.mJson.GetString();
|
||||
std::vector<uint8_t> decoded;
|
||||
auto ec = RsBase64::decode(encodedValue, decoded);
|
||||
if(ec)
|
||||
@ -642,9 +628,7 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
|
||||
RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl;
|
||||
print_stacktrace();
|
||||
|
||||
ctx.mOk = false;
|
||||
clear();
|
||||
break;
|
||||
return failure();
|
||||
}
|
||||
|
||||
const auto decodedSize = decoded.size();
|
||||
@ -655,11 +639,8 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
|
||||
break;
|
||||
}
|
||||
|
||||
if(decodedSize != second)
|
||||
{
|
||||
first = reinterpret_cast<uint8_t*>(realloc(first, decodedSize));
|
||||
first = reinterpret_cast<uint8_t*>(malloc(decodedSize));
|
||||
second = static_cast<uint32_t>(decodedSize);
|
||||
}
|
||||
|
||||
memcpy(first, decoded.data(), second);
|
||||
break;
|
||||
@ -675,6 +656,24 @@ void RsTypeSerializer::RawMemoryWrapper::clear()
|
||||
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 //
|
||||
//============================================================================//
|
||||
|
@ -59,12 +59,17 @@ struct RsTypeSerializer
|
||||
/// Maximum supported size 10MB
|
||||
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
|
||||
void serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx ) override;
|
||||
private:
|
||||
void clear();
|
||||
bool freshMemCheck();
|
||||
};
|
||||
|
||||
/// Most types are not valid sequence containers
|
||||
@ -777,7 +782,7 @@ struct RsTypeSerializer
|
||||
{
|
||||
if(!yielding)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName
|
||||
RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName
|
||||
<< "\" not found in JSON:" << std::endl
|
||||
<< jDoc << std::endl << std::endl;
|
||||
print_stacktrace();
|
||||
@ -790,7 +795,7 @@ struct RsTypeSerializer
|
||||
|
||||
if(!v.IsObject())
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName
|
||||
RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName
|
||||
<< "\" has wrong type in JSON, object expected, got:"
|
||||
<< std::endl << jDoc << std::endl << std::endl;
|
||||
print_stacktrace();
|
||||
|
@ -32,6 +32,8 @@ std::ostream &operator<<(std::ostream& out, const std::error_condition& err);
|
||||
# include <sstream>
|
||||
# include <string>
|
||||
|
||||
# include "util/rsjson.h"
|
||||
|
||||
enum class RsLoggerCategories
|
||||
{
|
||||
DEBUG = ANDROID_LOG_DEBUG,
|
||||
@ -55,6 +57,10 @@ struct t_RsLogger
|
||||
inline stream_type& operator<<(const T& val)
|
||||
{ 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
|
||||
stream_type& operator<<(std::ostream& (*pf)(std::ostream&))
|
||||
{
|
||||
@ -111,7 +117,7 @@ struct t_RsLogger
|
||||
const auto now = system_clock::now();
|
||||
const auto sec = time_point_cast<seconds>(now);
|
||||
const auto msec = duration_cast<milliseconds>(now - sec);
|
||||
std::stringstream tstream;
|
||||
std::ostringstream tstream;
|
||||
tstream << static_cast<char>(CATEGORY) << " "
|
||||
<< sec.time_since_epoch().count() << "."
|
||||
<< std::setfill('0') << std::setw(3) << msec.count()
|
||||
|
@ -29,7 +29,7 @@
|
||||
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[in] jDoc JSON document to print
|
||||
* @return same output stream passed as out parameter
|
||||
|
Loading…
Reference in New Issue
Block a user