Files
crosslang/src/runtime_methods/json.cpp
Mike Nolan 2430b62232
Some checks failed
Build and Deploy on Tag / 🔨 Build for PowerPC (push) Successful in 1m11s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-riscv64:latest, riscv64-linux-gnu, riscv64) (push) Successful in 3m22s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-x64:latest, x86_64-linux-gnu, amd64) (push) Successful in 3m34s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-arm:latest, arm-linux-gnueabihf, arm7) (push) Successful in 3m37s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-arm64:latest, aarch64-linux-gnu, arm64) (push) Successful in 3m39s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-x86:latest, i386-linux-gnu, 386) (push) Successful in 55s
Build and Deploy on Tag / update-tap (push) Failing after 4m8s
Replace time-based GC with allocation-count trigger, migrate all Create factories to GCList::Create(), fix VFSPath root path, reorder TObject variant
2026-09-01 05:15:43 -05:00

194 lines
5.8 KiB
C++

#include "CrossLang.hpp"
using namespace Tesses::Framework::Serialization::Json;
namespace Tesses::CrossLang {
static bool IsValidForJson(TObject v) {
if (std::holds_alternative<std::nullptr_t>(v))
return true;
if (std::holds_alternative<int64_t>(v))
return true;
if (std::holds_alternative<double>(v))
return true;
if (std::holds_alternative<bool>(v))
return true;
if (std::holds_alternative<std::string>(v))
return true;
if (std::holds_alternative<THeapObjectHolder>(v)) {
auto res = std::get<THeapObjectHolder>(v);
auto ls = dynamic_cast<TList *>(res.obj);
auto dict = dynamic_cast<TDictionary *>(res.obj);
if (ls != nullptr)
return true;
if (dict != nullptr)
return true;
}
return false;
}
static JToken JsonSerialize(TObject v) {
if (std::holds_alternative<std::nullptr_t>(v))
return nullptr;
if (std::holds_alternative<int64_t>(v))
return std::get<int64_t>(v);
if (std::holds_alternative<double>(v))
return std::get<double>(v);
if (std::holds_alternative<bool>(v))
return std::get<bool>(v);
if (std::holds_alternative<std::string>(v))
return std::get<std::string>(v);
if (std::holds_alternative<THeapObjectHolder>(v)) {
auto obj = std::get<THeapObjectHolder>(v).obj;
auto ls = dynamic_cast<TList *>(obj);
auto dict = dynamic_cast<TDictionary *>(obj);
if (ls != nullptr) {
JArray items;
for (int64_t i = 0; i < ls->Count(); i++) {
auto val = ls->Get(i);
if (IsValidForJson(val))
items.Add(JsonSerialize(val));
}
return items;
}
if (dict != nullptr) {
JObject obj;
for (auto item : dict->items) {
if (IsValidForJson(item.second))
obj.SetValue(item.first, JsonSerialize(item.second));
}
return obj;
}
}
return nullptr;
}
static TObject JsonEncode(GCList &ls2, std::vector<TObject> args) {
if (args.size() >= 1) {
bool indent =
(args.size() == 2 && std::holds_alternative<bool>(args[1]) &&
std::get<bool>(args[1]));
auto json = JsonSerialize(args[0]);
return Json::Encode(json, indent);
}
return "null";
}
static TObject JsonDocEncode(GCList &ls2, std::vector<TObject> args) {
if (args.size() >= 1) {
bool indent =
(args.size() == 2 && std::holds_alternative<bool>(args[1]) &&
std::get<bool>(args[1]));
auto json = JsonSerialize(args[0]);
JArray ar;
if (TryGetJToken(json, ar))
return Json::DocEncode(ar, indent);
}
return "";
}
static TObject JsonDeserialize(GCList &ls2, JToken json) {
if (std::holds_alternative<JUndefined>(json))
return nullptr;
if (std::holds_alternative<std::nullptr_t>(json))
return nullptr;
bool b;
int64_t _i64;
double _f64;
std::string str;
JArray arr;
JObject obj;
if (TryGetJToken(json, b))
return b;
if (TryGetJToken(json, _i64))
return _i64;
if (TryGetJToken(json, _f64))
return _f64;
if (TryGetJToken(json, str))
return str;
if (TryGetJToken(json, arr)) {
TList *ls = TList::Create(ls2);
for (auto &item : arr) {
auto itemRes = JsonDeserialize(ls2, item);
ls2.GetGC()->BarrierBegin();
ls->Add(itemRes);
ls2.GetGC()->BarrierEnd();
}
return ls;
}
if (TryGetJToken(json, obj)) {
TDictionary *dict = TDictionary::Create(ls2);
for (auto &item : obj) {
auto itemRes = JsonDeserialize(ls2, item.second);
ls2.GetGC()->BarrierBegin();
dict->SetValue(item.first, itemRes);
ls2.GetGC()->BarrierEnd();
}
return dict;
}
return Undefined();
}
static TObject JsonDecode(GCList &ls2, std::vector<TObject> args) {
if (args.size() > 0 && std::holds_alternative<std::string>(args[0])) {
return JsonDeserialize(ls2,
Json::Decode(std::get<std::string>(args[0])));
}
return Undefined();
}
static TObject JsonDocDecode(GCList &ls2, std::vector<TObject> args) {
if (args.size() > 0 && std::holds_alternative<std::string>(args[0])) {
return JsonDeserialize(ls2,
Json::DocDecode(std::get<std::string>(args[0])));
}
return Undefined();
}
std::string Json_Encode(TObject o, bool indent) {
return Json::Encode(JsonSerialize(o), indent);
}
TObject Json_Decode(GCList &ls, std::string str) {
return JsonDeserialize(ls, Json::Decode(str));
}
std::string Json_DocEncode(TObject o, bool indent) {
auto obj = JsonSerialize(o);
JArray ls;
if (TryGetJToken(obj, ls))
return Json::DocEncode(ls, indent);
return "";
}
TObject Json_DocDecode(GCList &ls, std::string str) {
return JsonDeserialize(ls, Json::DocDecode(str));
}
void TStd::RegisterJson(std::shared_ptr<GC> gc, TRootEnvironment *env) {
env->permissions.canRegisterJSON = true;
GCList ls(gc);
TDictionary *dict = TDictionary::Create(ls);
dict->DeclareFunction(gc, "Decode", "Deserialize Json", {"jsonString"},
JsonDecode);
dict->DeclareFunction(gc, "Encode", "Serialize Json", {"any", "$indent"},
JsonEncode);
dict->DeclareFunction(gc, "DocDecode", "Deserialize JsonDoc",
{"jsonDocString"}, JsonDocDecode);
dict->DeclareFunction(gc, "DocEncode", "Serialize JsonDoc",
{"ls", "$indent"}, JsonDocEncode);
gc->BarrierBegin();
env->DeclareVariable("Json", dict);
gc->BarrierEnd();
}
} // namespace Tesses::CrossLang