Wrap json writer the same way I did reader. More RAII for json writing so I'm less likely to mess it up again.
This commit is contained in:
parent
e69f9fbf71
commit
98852fba82
2 changed files with 117 additions and 110 deletions
|
@ -2,8 +2,6 @@
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "discord-rpc.h"
|
#include "discord-rpc.h"
|
||||||
|
|
||||||
MallocAllocator MallocAllocatorInst;
|
|
||||||
|
|
||||||
// it's ever so slightly faster to not have to strlen the key
|
// it's ever so slightly faster to not have to strlen the key
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void WriteKey(JsonWriter& w, T& k)
|
void WriteKey(JsonWriter& w, T& k)
|
||||||
|
@ -11,6 +9,35 @@ void WriteKey(JsonWriter& w, T& k)
|
||||||
w.Key(k, sizeof(T) - 1);
|
w.Key(k, sizeof(T) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct WriteObject {
|
||||||
|
JsonWriter& writer;
|
||||||
|
WriteObject(JsonWriter& w)
|
||||||
|
: writer(w)
|
||||||
|
{
|
||||||
|
writer.StartObject();
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
WriteObject(JsonWriter& w, T& name)
|
||||||
|
: writer(w)
|
||||||
|
{
|
||||||
|
WriteKey(writer, name);
|
||||||
|
writer.StartObject();
|
||||||
|
}
|
||||||
|
~WriteObject() { writer.EndObject(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WriteArray {
|
||||||
|
JsonWriter& writer;
|
||||||
|
template <typename T>
|
||||||
|
WriteArray(JsonWriter& w, T& name)
|
||||||
|
: writer(w)
|
||||||
|
{
|
||||||
|
WriteKey(writer, name);
|
||||||
|
writer.StartArray();
|
||||||
|
}
|
||||||
|
~WriteArray() { writer.EndArray(); }
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void WriteOptionalString(JsonWriter& w, T& k, const char* value)
|
void WriteOptionalString(JsonWriter& w, T& k, const char* value)
|
||||||
{
|
{
|
||||||
|
@ -28,150 +55,115 @@ void JsonWriteNonce(JsonWriter& writer, int nonce)
|
||||||
writer.String(nonceBuffer);
|
writer.String(nonceBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriteCommandStart(JsonWriter& writer, int nonce, const char* cmd)
|
|
||||||
{
|
|
||||||
writer.StartObject();
|
|
||||||
|
|
||||||
JsonWriteNonce(writer, nonce);
|
|
||||||
|
|
||||||
WriteKey(writer, "cmd");
|
|
||||||
writer.String(cmd);
|
|
||||||
|
|
||||||
WriteKey(writer, "args");
|
|
||||||
writer.StartObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriteCommandEnd(JsonWriter& writer)
|
|
||||||
{
|
|
||||||
writer.EndObject(); // args
|
|
||||||
writer.EndObject(); // top level
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t JsonWriteRichPresenceObj(char* dest,
|
size_t JsonWriteRichPresenceObj(char* dest,
|
||||||
size_t maxLen,
|
size_t maxLen,
|
||||||
int nonce,
|
int nonce,
|
||||||
int pid,
|
int pid,
|
||||||
const DiscordRichPresence* presence)
|
const DiscordRichPresence* presence)
|
||||||
{
|
{
|
||||||
DirectStringBuffer sb(dest, maxLen);
|
JsonWriter writer(dest, maxLen);
|
||||||
StackAllocator wa;
|
|
||||||
JsonWriter writer(sb, &wa, WriterNestingLevels);
|
|
||||||
|
|
||||||
JsonWriteCommandStart(writer, nonce, "SET_ACTIVITY");
|
{
|
||||||
|
WriteObject top(writer);
|
||||||
|
|
||||||
WriteKey(writer, "pid");
|
JsonWriteNonce(writer, nonce);
|
||||||
writer.Int(pid);
|
|
||||||
|
|
||||||
WriteKey(writer, "activity");
|
WriteKey(writer, "cmd");
|
||||||
writer.StartObject();
|
writer.String("SET_ACTIVITY");
|
||||||
|
|
||||||
WriteOptionalString(writer, "state", presence->state);
|
{
|
||||||
WriteOptionalString(writer, "details", presence->details);
|
WriteObject args(writer, "args");
|
||||||
|
|
||||||
if (presence->startTimestamp || presence->endTimestamp) {
|
WriteKey(writer, "pid");
|
||||||
WriteKey(writer, "timestamps");
|
writer.Int(pid);
|
||||||
writer.StartObject();
|
|
||||||
|
|
||||||
if (presence->startTimestamp) {
|
{
|
||||||
WriteKey(writer, "start");
|
WriteObject activity(writer, "activity");
|
||||||
writer.Int64(presence->startTimestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (presence->endTimestamp) {
|
WriteOptionalString(writer, "state", presence->state);
|
||||||
WriteKey(writer, "end");
|
WriteOptionalString(writer, "details", presence->details);
|
||||||
writer.Int64(presence->endTimestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.EndObject();
|
if (presence->startTimestamp || presence->endTimestamp) {
|
||||||
}
|
WriteObject timestamps(writer, "timestamps");
|
||||||
|
|
||||||
if (presence->largeImageKey || presence->largeImageText || presence->smallImageKey ||
|
if (presence->startTimestamp) {
|
||||||
presence->smallImageText) {
|
WriteKey(writer, "start");
|
||||||
WriteKey(writer, "assets");
|
writer.Int64(presence->startTimestamp);
|
||||||
writer.StartObject();
|
}
|
||||||
|
|
||||||
WriteOptionalString(writer, "large_image", presence->largeImageKey);
|
if (presence->endTimestamp) {
|
||||||
WriteOptionalString(writer, "large_text", presence->largeImageText);
|
WriteKey(writer, "end");
|
||||||
WriteOptionalString(writer, "small_image", presence->smallImageKey);
|
writer.Int64(presence->endTimestamp);
|
||||||
WriteOptionalString(writer, "small_text", presence->smallImageText);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writer.EndObject();
|
if (presence->largeImageKey || presence->largeImageText ||
|
||||||
}
|
presence->smallImageKey || presence->smallImageText) {
|
||||||
|
WriteObject assets(writer, "assets");
|
||||||
|
WriteOptionalString(writer, "large_image", presence->largeImageKey);
|
||||||
|
WriteOptionalString(writer, "large_text", presence->largeImageText);
|
||||||
|
WriteOptionalString(writer, "small_image", presence->smallImageKey);
|
||||||
|
WriteOptionalString(writer, "small_text", presence->smallImageText);
|
||||||
|
}
|
||||||
|
|
||||||
if (presence->partyId || presence->partySize || presence->partyMax) {
|
if (presence->partyId || presence->partySize || presence->partyMax) {
|
||||||
WriteKey(writer, "party");
|
WriteObject party(writer, "party");
|
||||||
writer.StartObject();
|
WriteOptionalString(writer, "id", presence->partyId);
|
||||||
|
if (presence->partySize) {
|
||||||
|
WriteArray size(writer, "size");
|
||||||
|
writer.Int(presence->partySize);
|
||||||
|
if (0 < presence->partyMax) {
|
||||||
|
writer.Int(presence->partyMax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WriteOptionalString(writer, "id", presence->partyId);
|
if (presence->matchSecret || presence->joinSecret || presence->spectateSecret) {
|
||||||
if (presence->partySize) {
|
WriteObject secrets(writer, "secrets");
|
||||||
WriteKey(writer, "size");
|
WriteOptionalString(writer, "match", presence->matchSecret);
|
||||||
writer.StartArray();
|
WriteOptionalString(writer, "join", presence->joinSecret);
|
||||||
|
WriteOptionalString(writer, "spectate", presence->spectateSecret);
|
||||||
|
}
|
||||||
|
|
||||||
writer.Int(presence->partySize);
|
writer.Key("instance");
|
||||||
if (0 < presence->partyMax) {
|
writer.Bool(presence->instance != 0);
|
||||||
writer.Int(presence->partyMax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.EndArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.EndObject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (presence->matchSecret || presence->joinSecret || presence->spectateSecret) {
|
return writer.Size();
|
||||||
WriteKey(writer, "secrets");
|
|
||||||
writer.StartObject();
|
|
||||||
|
|
||||||
WriteOptionalString(writer, "match", presence->matchSecret);
|
|
||||||
WriteOptionalString(writer, "join", presence->joinSecret);
|
|
||||||
WriteOptionalString(writer, "spectate", presence->spectateSecret);
|
|
||||||
|
|
||||||
writer.EndObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.Key("instance");
|
|
||||||
writer.Bool(presence->instance != 0);
|
|
||||||
|
|
||||||
writer.EndObject(); // activity
|
|
||||||
|
|
||||||
JsonWriteCommandEnd(writer);
|
|
||||||
|
|
||||||
return sb.GetSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
|
size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
|
||||||
{
|
{
|
||||||
DirectStringBuffer sb(dest, maxLen);
|
JsonWriter writer(dest, maxLen);
|
||||||
StackAllocator wa;
|
|
||||||
JsonWriter writer(sb, &wa, WriterNestingLevels);
|
|
||||||
|
|
||||||
writer.StartObject();
|
{
|
||||||
WriteKey(writer, "v");
|
WriteObject obj(writer);
|
||||||
writer.Int(version);
|
WriteKey(writer, "v");
|
||||||
WriteKey(writer, "client_id");
|
writer.Int(version);
|
||||||
writer.String(applicationId);
|
WriteKey(writer, "client_id");
|
||||||
writer.EndObject();
|
writer.String(applicationId);
|
||||||
|
}
|
||||||
|
|
||||||
return sb.GetSize();
|
return writer.Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
|
size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
|
||||||
{
|
{
|
||||||
DirectStringBuffer sb(dest, maxLen);
|
JsonWriter writer(dest, maxLen);
|
||||||
StackAllocator wa;
|
|
||||||
JsonWriter writer(sb, &wa, WriterNestingLevels);
|
|
||||||
|
|
||||||
writer.StartObject();
|
{
|
||||||
|
WriteObject obj(writer);
|
||||||
|
|
||||||
JsonWriteNonce(writer, nonce);
|
JsonWriteNonce(writer, nonce);
|
||||||
|
|
||||||
WriteKey(writer, "cmd");
|
WriteKey(writer, "cmd");
|
||||||
writer.String("SUBSCRIBE");
|
writer.String("SUBSCRIBE");
|
||||||
|
|
||||||
WriteKey(writer, "evt");
|
WriteKey(writer, "evt");
|
||||||
writer.String(evtName);
|
writer.String(evtName);
|
||||||
|
}
|
||||||
|
|
||||||
writer.EndObject();
|
return writer.Size();
|
||||||
|
|
||||||
return sb.GetSize();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,8 +120,23 @@ using UTF8 = rapidjson::UTF8<char>;
|
||||||
// Writer appears to need about 16 bytes per nested object level (with 64bit size_t)
|
// Writer appears to need about 16 bytes per nested object level (with 64bit size_t)
|
||||||
using StackAllocator = FixedLinearAllocator<2048>;
|
using StackAllocator = FixedLinearAllocator<2048>;
|
||||||
constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t));
|
constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t));
|
||||||
using JsonWriter =
|
using JsonWriterBase =
|
||||||
rapidjson::Writer<DirectStringBuffer, UTF8, UTF8, StackAllocator, rapidjson::kWriteNoFlags>;
|
rapidjson::Writer<DirectStringBuffer, UTF8, UTF8, StackAllocator, rapidjson::kWriteNoFlags>;
|
||||||
|
class JsonWriter : public JsonWriterBase {
|
||||||
|
public:
|
||||||
|
DirectStringBuffer stringBuffer_;
|
||||||
|
StackAllocator stackAlloc_;
|
||||||
|
|
||||||
|
JsonWriter(char* dest, size_t maxLen)
|
||||||
|
: JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels)
|
||||||
|
, stringBuffer_(dest, maxLen)
|
||||||
|
, stackAlloc_()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Size() const { return stringBuffer_.GetSize(); }
|
||||||
|
};
|
||||||
|
|
||||||
using JsonDocumentBase = rapidjson::GenericDocument<UTF8, PoolAllocator, StackAllocator>;
|
using JsonDocumentBase = rapidjson::GenericDocument<UTF8, PoolAllocator, StackAllocator>;
|
||||||
class JsonDocument : public JsonDocumentBase {
|
class JsonDocument : public JsonDocumentBase {
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in a new issue