#include "vsjson.h"
#include <charconv>
static bool isAsciiPrintable(const std::string &s) {
for (const auto c : s)
if (c < 0x20 || c > 0x7E)
return false;
return true;
}
static std::string doubleToString(double v) {
char buffer[100];
auto res = std::to_chars(buffer, buffer + sizeof(buffer), v, std::chars_format::fixed);
return std::string(buffer, res.ptr - buffer);
}
std::string escapeJSONString(const std::string &s) {
std::string result;
result.reserve(s.length() * 2 + 2);
for (auto c : s) {
if (c == '\\')
result += "\\\\";
else if (c == '\0')
result += "\\x00";
else if (c == '\b')
result += "\\b";
else if (c == '\f')
result += "\\f";
else if (c == '\n')
result += "\\n";
else if (c == '\r')
result += "\\r";
else if (c == '\t')
result += "\\t";
else if (c == '\v')
result += "\\v";
else if (c == '"')
result += "\\\"";
else
result += c;
}
return "\"" + result + "\"";
}
std::string convertVSMapToJSON(const VSMap *map, const VSAPI *vsapi) {
int numKeys = vsapi->mapNumKeys(map);
std::string jsonStr = "{";
for (int i = 0; i < numKeys; i++) {
const char *key = vsapi->mapGetKey(map, i);
int numElems = vsapi->mapNumElements(map, key);
if (i)
jsonStr += ", ";
jsonStr += escapeJSONString(key) + ": ";
if (numElems == 0) {
jsonStr += "null";
} else {
if (numElems > 1)
jsonStr += "[";
switch (vsapi->mapGetType(map, key)) {
case ptInt:
for (int j = 0; j < numElems; j++)
jsonStr += (j ? ", " : "") + std::to_string(vsapi->mapGetInt(map, key, j, nullptr));
break;
case ptFloat:
for (int j = 0; j < numElems; j++)
jsonStr += (j ? ", " : "") + doubleToString(vsapi->mapGetFloat(map, key, j, nullptr));
break;
case ptData:
for (int j = 0; j < numElems; j++) {
int typeHint = vsapi->mapGetDataTypeHint(map, key, j, nullptr);
jsonStr += (j ? ", " : "");
if (typeHint == dtUtf8 || (typeHint == dtUnknown && vsapi->mapGetDataSize(map, key, j, nullptr) < 200 && isAsciiPrintable(std::string(vsapi->mapGetData(map, key, j, nullptr), vsapi->mapGetDataSize(map, key, j, nullptr)))))
jsonStr += escapeJSONString(vsapi->mapGetData(map, key, j, nullptr));
else
jsonStr += "\"[binary data size: " + std::to_string(vsapi->mapGetDataSize(map, key, j, nullptr)) + "]\"";
}
break;
}
if (numElems > 1)
jsonStr += "]";
}
}
jsonStr += "}";
return jsonStr;
}