static bool sIsSame(const Value& a, const Value& b) { if(a.Is<ValueMap>() && b.Is<ValueMap>()) { ValueMap m = a; ValueMap n = b; for(int i = 0; i < m.GetCount(); i++) if(!sIsSame(n[m.GetKey(i)], m.GetValue(i))) return false; for(int i = 0; i < n.GetCount(); i++) if(!sIsSame(m[n.GetKey(i)], n.GetValue(i))) return false; return true; } else if(a.Is<ValueArray>() && b.Is<ValueArray>()) { if(a.GetCount() != b.GetCount()) return false; for(int i = 0; i < a.GetCount(); i++) if(!sIsSame(a[i], b[i])) return false; return true; } else return a == b; }
void S_info::Set(const void *s, const ValueMap& m) const { for(int i = 0; i < m.GetCount(); i++) { Value v = m.GetKey(i); if(IsString(v)) Set(s, (String)v, m.GetValue(i)); } }
String AsJSON(const Value& v, const String& sep, bool pretty) { String r; if(v.GetType() == VALUEMAP_V) { r << "{"; String sep1; if(pretty) { r << "\r\n"; sep1 = sep + '\t'; } ValueMap m = v; ValueArray va = m.GetValues(); for(int i = 0; i < m.GetCount(); i++) { if(i) { r << ","; if(pretty) r << "\r\n"; } if(pretty) r << sep1; r << AsJSON((String)m.GetKey(i)) << (pretty ? ": " : ":") << AsJSON(va[i], sep1, pretty); } if(pretty) r << "\r\n" << sep; r << "}"; return r; } if(v.GetType() == VALUEARRAY_V) { r << "["; String sep1; if(pretty) { r << "\r\n"; sep1 = sep + '\t'; } ValueArray va = v; for(int i = 0; i < va.GetCount(); i++) { if(i) { r << ","; if(pretty) r << "\r\n"; } if(pretty) r << sep1; r << AsJSON(va[i], sep1, pretty); } if(pretty) r << "\r\n" << sep; r << "]"; return r; } if(IsNumber(v) && IsNull(v)) return "null"; if(v.GetType() == INT_V) return Format("%d", (int)v); if(v.GetType() == BOOL_V) return (bool)v ? "true" : "false"; if(IsNumber(v)) return Format("%.16g", (double)v); if(IsString(v)) return AsCString((String)v, INT_MAX, NULL, ASCSTRING_JSON); if(IsDateTime(v)) return AsJSON((Time)v); if(IsNull(v)) return "null"; NEVER_("Non-JSON value in AsJSON: " + v.GetTypeName()); return "null"; }