#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "APIHelp.h" #include "NativeAPI.h" using namespace std; //////////////////// APIs //////////////////// template void PrintValue(T& out, Local v) { switch (v.getKind()) { case ValueKind::kString: out << v.asString().toString(); break; case ValueKind::kNumber: if (CheckIsFloat(v)) out << v.asNumber().toDouble(); else out << v.asNumber().toInt64(); break; case ValueKind::kBoolean: out << v.asBoolean().value(); break; case ValueKind::kNull: out << ""; break; case ValueKind::kArray: { Local arr = v.asArray(); if (arr.size() == 0) out << "[]"; else { static std::vector> arrStack = {}; if (std::find(arrStack.begin(), arrStack.end(), arr) == arrStack.end()) { arrStack.push_back(arr); out << '['; PrintValue(out, arr.get(0)); for (int i = 1; i < arr.size(); ++i) { out << ','; PrintValue(out, arr.get(i)); } out << ']'; arrStack.pop_back(); } else { out << ""; } } break; } case ValueKind::kObject: { // 自定义类型也会被识别为Object,优先处理 // IntPos IntPos* intpos = IntPos::extractPos(v); if (intpos != nullptr) { out << DimId2Name(intpos->dim) << "(" << intpos->x << "," << intpos->y << "," << intpos->z << ")"; break; } // FloatPos FloatPos* floatpos = FloatPos::extractPos(v); if (floatpos != nullptr) { out << fixed << setprecision(2) << DimId2Name(floatpos->dim) << "(" << floatpos->x << "," << floatpos->y << "," << floatpos->z << ")"; break; } // 其他自定义类型 if (IsInstanceOf(v)) { std::stringstream ss; ss << std::hex << (intptr_t)EngineScope::currentEngine()->getNativeInstance(v)->get(); out << ss.str(); break; } if (IsInstanceOf(v)) { std::stringstream ss; ScriptNativeFunction* func = EngineScope::currentEngine()->getNativeInstance(v); ss << std::hex << "Address: " << (intptr_t)func->mFunction << " " << "Symbol: " << func->mSymbol << " " << "ReturnType: " << magic_enum::enum_name(func->mReturnVal) << " " << "Params: " << func->mParams.size(); for (size_t i = 0; i < func->mParams.size(); ++i) { ss << " [" << i << "]" << magic_enum::enum_name(func->mParams[i]); } out << ss.str(); break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; break; } if (IsNbtClass(v)) { out << ""; break; } if (IsInstanceOf(v)) { out << ""; } if (IsInstanceOf(v)) { out << ""; } if (IsInstanceOf(v)) { out << ""; } if (IsInstanceOf(v)) { out << ""; } if (IsInstanceOf(v)) { out << ""; } Local obj = v.asObject(); std::vector keys = obj.getKeyNames(); if (keys.empty()) out << "{}"; else { static std::vector> objStack = {}; if (std::find(objStack.begin(), objStack.end(), obj) == objStack.end()) { objStack.push_back(obj); out << '{'; out << keys[0] + ":"; PrintValue(out, obj.get(keys[0])); for (int i = 1; i < keys.size(); ++i) { out << "," + keys[i] + ":"; PrintValue(out, obj.get(keys[i])); } out << '}'; objStack.pop_back(); } else { out << ""; } } break; } case ValueKind::kByteBuffer: { Local bytes = v.asByteBuffer(); out << ((const char*)bytes.getRawBytes(), bytes.byteLength()); break; } case ValueKind::kFunction: { out << ""; break; } default: { out << ""; break; } } } std::string ValueToString(Local v) { std::ostringstream sout; PrintValue(sout, v); return sout.str(); } bool CheckIsFloat(const Local& num) { try { return fabs(num.asNumber().toDouble() - num.asNumber().toInt64()) >= 1e-15; } catch (...) { return false; } } ///////////////////// Json To Value ///////////////////// Local BigInteger_Helper(fifo_json& i) { if (i.is_number_integer()) { if (i.is_number_unsigned()) { auto ui = i.get(); if (ui <= LLONG_MAX) return Number::newNumber((int64_t)ui); return Number::newNumber((double)ui); } return Number::newNumber(i.get()); } return Local(); } void JsonToValue_Helper(Local& res, fifo_json& j); void JsonToValue_Helper(Local& res, const string& key, fifo_json& j) { switch (j.type()) { case fifo_json::value_t::string: res.set(key, String::newString(j.get())); break; case fifo_json::value_t::number_integer: case fifo_json::value_t::number_unsigned: res.set(key, BigInteger_Helper(j)); break; case fifo_json::value_t::number_float: res.set(key, Number::newNumber(j.get())); break; case fifo_json::value_t::boolean: res.set(key, Boolean::newBoolean(j.get())); break; case fifo_json::value_t::null: res.set(key, Local()); break; case fifo_json::value_t::array: { Local arrToAdd = Array::newArray(); for (fifo_json::iterator it = j.begin(); it != j.end(); ++it) JsonToValue_Helper(arrToAdd, *it); res.set(key, arrToAdd); break; } case fifo_json::value_t::object: { Local objToAdd = Object::newObject(); for (fifo_json::iterator it = j.begin(); it != j.end(); ++it) JsonToValue_Helper(objToAdd, it.key(), it.value()); res.set(key, objToAdd); break; } default: res.set(key, Local()); break; } } void JsonToValue_Helper(Local& res, fifo_json& j) { switch (j.type()) { case fifo_json::value_t::string: res.add(String::newString(j.get())); break; case fifo_json::value_t::number_integer: case fifo_json::value_t::number_unsigned: res.add(BigInteger_Helper(j)); break; case fifo_json::value_t::number_float: res.add(Number::newNumber(j.get())); break; case fifo_json::value_t::boolean: res.add(Boolean::newBoolean(j.get())); break; case fifo_json::value_t::null: res.add(Local()); break; case fifo_json::value_t::array: { Local arrToAdd = Array::newArray(); for (fifo_json::iterator it = j.begin(); it != j.end(); ++it) JsonToValue_Helper(arrToAdd, *it); res.add(arrToAdd); break; } case fifo_json::value_t::object: { Local objToAdd = Object::newObject(); for (fifo_json::iterator it = j.begin(); it != j.end(); ++it) JsonToValue_Helper(objToAdd, it.key(), it.value()); res.add(objToAdd); break; } default: res.add(Local()); break; } } Local JsonToValue(fifo_json j) { Local res; switch (j.type()) { case fifo_json::value_t::string: res = String::newString(j.get()); break; case fifo_json::value_t::number_integer: case fifo_json::value_t::number_unsigned: res = BigInteger_Helper(j); break; case fifo_json::value_t::number_float: res = Number::newNumber(j.get()); break; case fifo_json::value_t::boolean: res = Boolean::newBoolean(j.get()); break; case fifo_json::value_t::null: res = Local(); break; case fifo_json::value_t::array: { Local resArr = Array::newArray(); for (fifo_json::iterator it = j.begin(); it != j.end(); ++it) JsonToValue_Helper(resArr, *it); res = resArr; break; } case fifo_json::value_t::object: { Local resObj = Object::newObject(); for (fifo_json::iterator it = j.begin(); it != j.end(); ++it) JsonToValue_Helper(resObj, it.key(), it.value()); res = resObj; break; } default: res = Local(); break; } return res; } Local JsonToValue(std::string jsonStr) { try { if (jsonStr.empty()) return String::newString(""); if (jsonStr.front() == '\"' && jsonStr.back() == '\"') return String::newString(jsonStr.substr(1, jsonStr.size() - 2)); auto j = fifo_json::parse(jsonStr, nullptr, true, true); return JsonToValue(j); } catch (const fifo_json::exception& e) { logger.warn(tr("llse.apiHelp.parseJson.fail") + TextEncoding::toUTF8(e.what())); return String::newString(jsonStr); } } ///////////////////// Value To Json ///////////////////// void ValueToJson_Obj_Helper(fifo_json& res, const Local& v); void ValueToJson_Arr_Helper(fifo_json& res, const Local& v) { for (int i = 0; i < v.size(); ++i) { switch (v.get(i).getKind()) { case ValueKind::kString: res.push_back(v.get(i).asString().toString()); break; case ValueKind::kNumber: if (CheckIsFloat(v.get(i))) res.push_back(v.get(i).asNumber().toDouble()); else res.push_back(v.get(i).asNumber().toInt64()); break; case ValueKind::kBoolean: res.push_back(v.get(i).asBoolean().value()); break; case ValueKind::kNull: res.push_back(nullptr); break; case ValueKind::kArray: { Local arrToAdd = v.get(i).asArray(); if (arrToAdd.size() == 0) res.push_back(fifo_json::array()); else { fifo_json arrJson = fifo_json::array(); ValueToJson_Arr_Helper(arrJson, arrToAdd); res.push_back(arrJson); } break; } case ValueKind::kObject: { Local objToAdd = v.get(i).asObject(); if (objToAdd.getKeyNames().empty()) res.push_back(fifo_json::object()); else { fifo_json objJson = fifo_json::object(); ValueToJson_Obj_Helper(objJson, objToAdd); res.push_back(objJson); } break; } default: res.push_back(nullptr); break; } } } void ValueToJson_Obj_Helper(fifo_json& res, const Local& v) { auto keys = v.getKeyNames(); for (auto& key : keys) { switch (v.get(key).getKind()) { case ValueKind::kString: res.push_back({key, v.get(key).asString().toString()}); break; case ValueKind::kNumber: if (CheckIsFloat(v.get(key))) res.push_back({key, v.get(key).asNumber().toDouble()}); else res.push_back({key, v.get(key).asNumber().toInt64()}); break; case ValueKind::kBoolean: res.push_back({key, v.get(key).asBoolean().value()}); break; case ValueKind::kNull: res.push_back({key, nullptr}); break; case ValueKind::kArray: { Local arrToAdd = v.get(key).asArray(); if (arrToAdd.size() == 0) res.push_back({key, fifo_json::array()}); else { fifo_json arrJson = fifo_json::array(); ValueToJson_Arr_Helper(arrJson, arrToAdd); res.push_back({key, arrJson}); } break; } case ValueKind::kObject: { Local objToAdd = v.get(key).asObject(); if (objToAdd.getKeyNames().empty()) res.push_back({key, fifo_json::object()}); else { fifo_json objJson = fifo_json::object(); ValueToJson_Obj_Helper(objJson, objToAdd); res.push_back({key, objJson}); } break; } default: res.push_back({key, nullptr}); break; } } } std::string ValueToJson(Local v, int formatIndent) { string result; switch (v.getKind()) { case ValueKind::kString: result = "\"" + v.asString().toString() + "\""; ReplaceStr(result, "\n", "\\n"); break; case ValueKind::kNumber: if (CheckIsFloat(v)) { result = std::to_string(v.asNumber().toDouble()); } else { result = std::to_string(v.asNumber().toInt64()); } break; case ValueKind::kBoolean: result = std::to_string(v.asBoolean().value()); break; case ValueKind::kNull: result = ""; break; case ValueKind::kArray: { fifo_json jsonRes = fifo_json::array(); ValueToJson_Arr_Helper(jsonRes, v.asArray()); result = jsonRes.dump(formatIndent); break; } case ValueKind::kObject: { fifo_json jsonRes = fifo_json::object(); ValueToJson_Obj_Helper(jsonRes, v.asObject()); result = jsonRes.dump(formatIndent); break; } default: result = ""; break; } return result; } std::string ValueKindToString(const ValueKind& kind) { switch (kind) { case ValueKind::kString: return "string"; case ValueKind::kNumber: return "number"; case ValueKind::kBoolean: return "boolean"; case ValueKind::kNull: return "null"; case ValueKind::kObject: return "object"; case ValueKind::kArray: return "array"; case ValueKind::kFunction: return "function"; case ValueKind::kByteBuffer: return "bytebuffer"; default: return "unknown"; } }