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 "discord-rpc.h"
|
||||
|
||||
MallocAllocator MallocAllocatorInst;
|
||||
|
||||
// it's ever so slightly faster to not have to strlen the key
|
||||
template <typename T>
|
||||
void WriteKey(JsonWriter& w, T& k)
|
||||
|
@ -11,6 +9,35 @@ void WriteKey(JsonWriter& w, T& k)
|
|||
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>
|
||||
void WriteOptionalString(JsonWriter& w, T& k, const char* value)
|
||||
{
|
||||
|
@ -28,150 +55,115 @@ void JsonWriteNonce(JsonWriter& writer, int nonce)
|
|||
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 maxLen,
|
||||
int nonce,
|
||||
int pid,
|
||||
const DiscordRichPresence* presence)
|
||||
{
|
||||
DirectStringBuffer sb(dest, maxLen);
|
||||
StackAllocator wa;
|
||||
JsonWriter writer(sb, &wa, WriterNestingLevels);
|
||||
JsonWriter writer(dest, maxLen);
|
||||
|
||||
JsonWriteCommandStart(writer, nonce, "SET_ACTIVITY");
|
||||
{
|
||||
WriteObject top(writer);
|
||||
|
||||
WriteKey(writer, "pid");
|
||||
writer.Int(pid);
|
||||
JsonWriteNonce(writer, nonce);
|
||||
|
||||
WriteKey(writer, "activity");
|
||||
writer.StartObject();
|
||||
WriteKey(writer, "cmd");
|
||||
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, "timestamps");
|
||||
writer.StartObject();
|
||||
WriteKey(writer, "pid");
|
||||
writer.Int(pid);
|
||||
|
||||
if (presence->startTimestamp) {
|
||||
WriteKey(writer, "start");
|
||||
writer.Int64(presence->startTimestamp);
|
||||
}
|
||||
{
|
||||
WriteObject activity(writer, "activity");
|
||||
|
||||
if (presence->endTimestamp) {
|
||||
WriteKey(writer, "end");
|
||||
writer.Int64(presence->endTimestamp);
|
||||
}
|
||||
WriteOptionalString(writer, "state", presence->state);
|
||||
WriteOptionalString(writer, "details", presence->details);
|
||||
|
||||
writer.EndObject();
|
||||
}
|
||||
if (presence->startTimestamp || presence->endTimestamp) {
|
||||
WriteObject timestamps(writer, "timestamps");
|
||||
|
||||
if (presence->largeImageKey || presence->largeImageText || presence->smallImageKey ||
|
||||
presence->smallImageText) {
|
||||
WriteKey(writer, "assets");
|
||||
writer.StartObject();
|
||||
if (presence->startTimestamp) {
|
||||
WriteKey(writer, "start");
|
||||
writer.Int64(presence->startTimestamp);
|
||||
}
|
||||
|
||||
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->endTimestamp) {
|
||||
WriteKey(writer, "end");
|
||||
writer.Int64(presence->endTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
WriteKey(writer, "party");
|
||||
writer.StartObject();
|
||||
if (presence->partyId || presence->partySize || presence->partyMax) {
|
||||
WriteObject party(writer, "party");
|
||||
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->partySize) {
|
||||
WriteKey(writer, "size");
|
||||
writer.StartArray();
|
||||
if (presence->matchSecret || presence->joinSecret || presence->spectateSecret) {
|
||||
WriteObject secrets(writer, "secrets");
|
||||
WriteOptionalString(writer, "match", presence->matchSecret);
|
||||
WriteOptionalString(writer, "join", presence->joinSecret);
|
||||
WriteOptionalString(writer, "spectate", presence->spectateSecret);
|
||||
}
|
||||
|
||||
writer.Int(presence->partySize);
|
||||
if (0 < presence->partyMax) {
|
||||
writer.Int(presence->partyMax);
|
||||
writer.Key("instance");
|
||||
writer.Bool(presence->instance != 0);
|
||||
}
|
||||
|
||||
writer.EndArray();
|
||||
}
|
||||
|
||||
writer.EndObject();
|
||||
}
|
||||
|
||||
if (presence->matchSecret || presence->joinSecret || presence->spectateSecret) {
|
||||
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();
|
||||
return writer.Size();
|
||||
}
|
||||
|
||||
size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
|
||||
{
|
||||
DirectStringBuffer sb(dest, maxLen);
|
||||
StackAllocator wa;
|
||||
JsonWriter writer(sb, &wa, WriterNestingLevels);
|
||||
JsonWriter writer(dest, maxLen);
|
||||
|
||||
writer.StartObject();
|
||||
WriteKey(writer, "v");
|
||||
writer.Int(version);
|
||||
WriteKey(writer, "client_id");
|
||||
writer.String(applicationId);
|
||||
writer.EndObject();
|
||||
{
|
||||
WriteObject obj(writer);
|
||||
WriteKey(writer, "v");
|
||||
writer.Int(version);
|
||||
WriteKey(writer, "client_id");
|
||||
writer.String(applicationId);
|
||||
}
|
||||
|
||||
return sb.GetSize();
|
||||
return writer.Size();
|
||||
}
|
||||
|
||||
size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
|
||||
{
|
||||
DirectStringBuffer sb(dest, maxLen);
|
||||
StackAllocator wa;
|
||||
JsonWriter writer(sb, &wa, WriterNestingLevels);
|
||||
JsonWriter writer(dest, maxLen);
|
||||
|
||||
writer.StartObject();
|
||||
{
|
||||
WriteObject obj(writer);
|
||||
|
||||
JsonWriteNonce(writer, nonce);
|
||||
JsonWriteNonce(writer, nonce);
|
||||
|
||||
WriteKey(writer, "cmd");
|
||||
writer.String("SUBSCRIBE");
|
||||
WriteKey(writer, "cmd");
|
||||
writer.String("SUBSCRIBE");
|
||||
|
||||
WriteKey(writer, "evt");
|
||||
writer.String(evtName);
|
||||
WriteKey(writer, "evt");
|
||||
writer.String(evtName);
|
||||
}
|
||||
|
||||
writer.EndObject();
|
||||
|
||||
return sb.GetSize();
|
||||
return writer.Size();
|
||||
}
|
||||
|
|
|
@ -120,8 +120,23 @@ using UTF8 = rapidjson::UTF8<char>;
|
|||
// Writer appears to need about 16 bytes per nested object level (with 64bit size_t)
|
||||
using StackAllocator = FixedLinearAllocator<2048>;
|
||||
constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t));
|
||||
using JsonWriter =
|
||||
using JsonWriterBase =
|
||||
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>;
|
||||
class JsonDocument : public JsonDocumentBase {
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue