reWrite lsl json functions, forward slash is not escaped as LitJson spec; code can use some cleanup. Scripts need to be recompiled
parent
c5d0c69a35
commit
ef35805176
|
@ -28,6 +28,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
|
@ -40,7 +41,7 @@ using Nini.Config;
|
||||||
using log4net;
|
using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenMetaverse.Assets;
|
using OpenMetaverse.Assets;
|
||||||
using OpenMetaverse.StructuredData;
|
using OpenMetaverse.StructuredData; // LitJson is hidden on this
|
||||||
using OpenMetaverse.Packets;
|
using OpenMetaverse.Packets;
|
||||||
using OpenMetaverse.Rendering;
|
using OpenMetaverse.Rendering;
|
||||||
using OpenSim;
|
using OpenSim;
|
||||||
|
@ -16700,92 +16701,158 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
return String.Empty;
|
return String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers)
|
|
||||||
{
|
|
||||||
OSD o = OSDParser.DeserializeJson(json);
|
|
||||||
OSD specVal = JsonGetSpecific(o, specifiers, 0);
|
|
||||||
|
|
||||||
return specVal.AsString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LSL_List llJson2List(LSL_String json)
|
public LSL_List llJson2List(LSL_String json)
|
||||||
{
|
{
|
||||||
|
if(String.IsNullOrEmpty(json))
|
||||||
|
return new LSL_List();
|
||||||
|
if(json == "[]")
|
||||||
|
return new LSL_List();
|
||||||
|
if(json == "{}")
|
||||||
|
return new LSL_List();
|
||||||
|
char first = ((string)json)[0];
|
||||||
|
|
||||||
|
if(first != '[' && first !='{')
|
||||||
|
{
|
||||||
|
// we already have a single element
|
||||||
|
LSL_List l = new LSL_List();
|
||||||
|
l.Add(json);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
LitJson.JsonData jsdata;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OSD o = OSDParser.DeserializeJson(json);
|
jsdata = LitJson.JsonMapper.ToObject(json);
|
||||||
return (LSL_List)ParseJsonNode(o);
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
return new LSL_List(ScriptBaseClass.JSON_INVALID);
|
string m = e.Message; // debug point
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JsonParseTop(jsdata);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
string m = e.Message; // debug point
|
||||||
|
return (LSL_String)ScriptBaseClass.JSON_INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object ParseJsonNode(OSD node)
|
private LSL_List JsonParseTop(LitJson.JsonData elem)
|
||||||
{
|
{
|
||||||
if (node.Type == OSDType.Integer)
|
LSL_List retl = new LSL_List();
|
||||||
return new LSL_Integer(node.AsInteger());
|
if(elem == null)
|
||||||
if (node.Type == OSDType.Boolean)
|
retl.Add((LSL_String)ScriptBaseClass.JSON_NULL);
|
||||||
return new LSL_Integer(node.AsBoolean() ? 1 : 0);
|
|
||||||
if (node.Type == OSDType.Real)
|
LitJson.JsonType elemType = elem.GetJsonType();
|
||||||
return new LSL_Float(node.AsReal());
|
switch (elemType)
|
||||||
if (node.Type == OSDType.UUID || node.Type == OSDType.String)
|
|
||||||
return new LSL_String(node.AsString());
|
|
||||||
if (node.Type == OSDType.Array)
|
|
||||||
{
|
{
|
||||||
LSL_List resp = new LSL_List();
|
case LitJson.JsonType.Int:
|
||||||
OSDArray ar = node as OSDArray;
|
retl.Add(new LSL_Integer((int)elem));
|
||||||
foreach (OSD o in ar)
|
return retl;
|
||||||
resp.Add(ParseJsonNode(o));
|
case LitJson.JsonType.Boolean:
|
||||||
return resp;
|
retl.Add((LSL_String)((bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE));
|
||||||
}
|
return retl;
|
||||||
if (node.Type == OSDType.Map)
|
case LitJson.JsonType.Double:
|
||||||
{
|
retl.Add(new LSL_Float((float)elem));
|
||||||
LSL_List resp = new LSL_List();
|
return retl;
|
||||||
OSDMap ar = node as OSDMap;
|
case LitJson.JsonType.None:
|
||||||
foreach (KeyValuePair<string, OSD> o in ar)
|
retl.Add((LSL_String)ScriptBaseClass.JSON_NULL);
|
||||||
{
|
return retl;
|
||||||
resp.Add(new LSL_String(o.Key));
|
case LitJson.JsonType.String:
|
||||||
resp.Add(ParseJsonNode(o.Value));
|
retl.Add(new LSL_String((string)elem));
|
||||||
}
|
return retl;
|
||||||
return resp;
|
case LitJson.JsonType.Array:
|
||||||
|
foreach (LitJson.JsonData subelem in elem)
|
||||||
|
retl.Add(JsonParseTopNodes(subelem));
|
||||||
|
return retl;
|
||||||
|
case LitJson.JsonType.Object:
|
||||||
|
IDictionaryEnumerator e = ((IOrderedDictionary)elem).GetEnumerator();
|
||||||
|
while (e.MoveNext())
|
||||||
|
{
|
||||||
|
retl.Add(new LSL_String((string)e.Key));
|
||||||
|
retl.Add(JsonParseTopNodes((LitJson.JsonData)e.Value));
|
||||||
}
|
}
|
||||||
|
return retl;
|
||||||
|
default:
|
||||||
throw new Exception(ScriptBaseClass.JSON_INVALID);
|
throw new Exception(ScriptBaseClass.JSON_INVALID);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object JsonParseTopNodes(LitJson.JsonData elem)
|
||||||
|
{
|
||||||
|
if(elem == null)
|
||||||
|
return ((LSL_String)ScriptBaseClass.JSON_NULL);
|
||||||
|
|
||||||
|
LitJson.JsonType elemType = elem.GetJsonType();
|
||||||
|
switch (elemType)
|
||||||
|
{
|
||||||
|
case LitJson.JsonType.Int:
|
||||||
|
return (new LSL_Integer((int)elem));
|
||||||
|
case LitJson.JsonType.Boolean:
|
||||||
|
return ((bool)elem ? (LSL_String)ScriptBaseClass.JSON_TRUE : (LSL_String)ScriptBaseClass.JSON_FALSE);
|
||||||
|
case LitJson.JsonType.Double:
|
||||||
|
return (new LSL_Float((float)elem));
|
||||||
|
case LitJson.JsonType.None:
|
||||||
|
return ((LSL_String)ScriptBaseClass.JSON_NULL);
|
||||||
|
case LitJson.JsonType.String:
|
||||||
|
return (new LSL_String((string)elem));
|
||||||
|
case LitJson.JsonType.Array:
|
||||||
|
case LitJson.JsonType.Object:
|
||||||
|
string s = LitJson.JsonMapper.ToJson(elem);
|
||||||
|
return (LSL_String)s;
|
||||||
|
default:
|
||||||
|
throw new Exception(ScriptBaseClass.JSON_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public LSL_String llList2Json(LSL_String type, LSL_List values)
|
public LSL_String llList2Json(LSL_String type, LSL_List values)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
if (type == ScriptBaseClass.JSON_ARRAY)
|
if (type == ScriptBaseClass.JSON_ARRAY)
|
||||||
{
|
{
|
||||||
OSDArray array = new OSDArray();
|
sb.Append("[");
|
||||||
|
int i= 0;
|
||||||
foreach (object o in values.Data)
|
foreach (object o in values.Data)
|
||||||
{
|
{
|
||||||
array.Add(ListToJson(o));
|
sb.Append(ListToJson(o));
|
||||||
|
if((i++) < values.Data.Length - 1)
|
||||||
|
sb.Append(",");
|
||||||
}
|
}
|
||||||
return OSDParser.SerializeJsonString(array);
|
sb.Append("]");
|
||||||
|
return (LSL_String)sb.ToString();;
|
||||||
}
|
}
|
||||||
else if (type == ScriptBaseClass.JSON_OBJECT)
|
else if (type == ScriptBaseClass.JSON_OBJECT)
|
||||||
{
|
{
|
||||||
OSDMap map = new OSDMap();
|
sb.Append("{");
|
||||||
for (int i = 0; i < values.Data.Length; i += 2)
|
for (int i = 0; i < values.Data.Length; i += 2)
|
||||||
{
|
{
|
||||||
if (!(values.Data[i] is LSL_String))
|
if (!(values.Data[i] is LSL_String))
|
||||||
return ScriptBaseClass.JSON_INVALID;
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
map.Add(((LSL_String)values.Data[i]).m_string, ListToJson(values.Data[i + 1]));
|
string key = ((LSL_String)values.Data[i]).m_string;
|
||||||
|
key = EscapeForJSON(key, true);
|
||||||
|
sb.Append(key);
|
||||||
|
sb.Append(":");
|
||||||
|
sb.Append(ListToJson(values.Data[i+1]));
|
||||||
|
if(i < values.Data.Length - 2)
|
||||||
|
sb.Append(",");
|
||||||
}
|
}
|
||||||
return OSDParser.SerializeJsonString(map);
|
sb.Append("}");
|
||||||
|
return (LSL_String)sb.ToString();
|
||||||
}
|
}
|
||||||
return ScriptBaseClass.JSON_INVALID;
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
return ex.Message;
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private OSD ListToJson(object o)
|
private string ListToJson(object o)
|
||||||
{
|
{
|
||||||
if (o is LSL_Float || o is double)
|
if (o is LSL_Float || o is double)
|
||||||
{
|
{
|
||||||
|
@ -16795,7 +16862,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
else
|
else
|
||||||
float_val = ((LSL_Float)o).value;
|
float_val = ((LSL_Float)o).value;
|
||||||
|
|
||||||
return OSD.FromReal(float_val);
|
if(double.IsInfinity(float_val))
|
||||||
|
return "\"Inf\"";
|
||||||
|
if(double.IsNaN(float_val))
|
||||||
|
return "\"NaN\"";
|
||||||
|
|
||||||
|
return ((LSL_Float)float_val).ToString();
|
||||||
}
|
}
|
||||||
if (o is LSL_Integer || o is int)
|
if (o is LSL_Integer || o is int)
|
||||||
{
|
{
|
||||||
|
@ -16804,17 +16876,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
i = ((int)o);
|
i = ((int)o);
|
||||||
else
|
else
|
||||||
i = ((LSL_Integer)o).value;
|
i = ((LSL_Integer)o).value;
|
||||||
|
return i.ToString();
|
||||||
if (i == 0)
|
|
||||||
return OSD.FromBoolean(false);
|
|
||||||
else if (i == 1)
|
|
||||||
return OSD.FromBoolean(true);
|
|
||||||
return OSD.FromInteger(i);
|
|
||||||
}
|
}
|
||||||
if (o is LSL_Rotation)
|
if (o is LSL_Rotation)
|
||||||
return OSD.FromString(((LSL_Rotation)o).ToString());
|
return ((LSL_Rotation)o).ToString();
|
||||||
if (o is LSL_Vector)
|
if (o is LSL_Vector)
|
||||||
return OSD.FromString(((LSL_Vector)o).ToString());
|
return ((LSL_Vector)o).ToString();
|
||||||
if (o is LSL_String || o is string)
|
if (o is LSL_String || o is string)
|
||||||
{
|
{
|
||||||
string str;
|
string str;
|
||||||
|
@ -16823,137 +16890,579 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
else
|
else
|
||||||
str = ((LSL_String)o).m_string;
|
str = ((LSL_String)o).m_string;
|
||||||
|
|
||||||
if (str == ScriptBaseClass.JSON_NULL)
|
if(str == ScriptBaseClass.JSON_TRUE || str == "true")
|
||||||
return new OSD();
|
return "true";
|
||||||
return OSD.FromString(str);
|
if(str == ScriptBaseClass.JSON_FALSE ||str == "false")
|
||||||
|
return "false";
|
||||||
|
if(str == ScriptBaseClass.JSON_NULL || str == "null")
|
||||||
|
return "null";
|
||||||
|
str.Trim();
|
||||||
|
if (str[0] == '{')
|
||||||
|
return str;
|
||||||
|
if (str[0] == '[')
|
||||||
|
return str;
|
||||||
|
return EscapeForJSON(str, true);
|
||||||
}
|
}
|
||||||
throw new Exception(ScriptBaseClass.JSON_INVALID);
|
throw new IndexOutOfRangeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private OSD JsonGetSpecific(OSD o, LSL_List specifiers, int i)
|
private string EscapeForJSON(string s, bool AddOuter)
|
||||||
{
|
{
|
||||||
object spec = specifiers.Data[i];
|
int i;
|
||||||
OSD nextVal = null;
|
char c;
|
||||||
if (o is OSDArray)
|
String t;
|
||||||
|
int len = s.Length;
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder(len + 64);
|
||||||
|
if(AddOuter)
|
||||||
|
sb.Append("\"");
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
if (spec is LSL_Integer)
|
c = s[i];
|
||||||
nextVal = ((OSDArray)o)[((LSL_Integer)spec).value];
|
switch (c)
|
||||||
|
{
|
||||||
|
case '\\':
|
||||||
|
case '"':
|
||||||
|
case '/':
|
||||||
|
sb.Append('\\');
|
||||||
|
sb.Append(c);
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
sb.Append("\\b");
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
sb.Append("\\t");
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
sb.Append("\\n");
|
||||||
|
break;
|
||||||
|
case '\f':
|
||||||
|
sb.Append("\\f");
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
sb.Append("\\r");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (c < ' ')
|
||||||
|
{
|
||||||
|
t = "000" + String.Format("X", c);
|
||||||
|
sb.Append("\\u" + t.Substring(t.Length - 4));
|
||||||
}
|
}
|
||||||
if (o is OSDMap)
|
else
|
||||||
{
|
{
|
||||||
if (spec is LSL_String)
|
sb.Append(c);
|
||||||
nextVal = ((OSDMap)o)[((LSL_String)spec).m_string];
|
|
||||||
}
|
}
|
||||||
if (nextVal != null)
|
break;
|
||||||
{
|
|
||||||
if (specifiers.Data.Length - 1 > i)
|
|
||||||
return JsonGetSpecific(nextVal, specifiers, i + 1);
|
|
||||||
}
|
}
|
||||||
return nextVal;
|
}
|
||||||
|
if(AddOuter)
|
||||||
|
sb.Append("\"");
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value)
|
public LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value)
|
||||||
{
|
{
|
||||||
|
bool noSpecifiers = specifiers.Length == 0;
|
||||||
|
LitJson.JsonData workData;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OSD o = OSDParser.DeserializeJson(json);
|
if(noSpecifiers)
|
||||||
JsonSetSpecific(o, specifiers, 0, value);
|
specifiers.Add(new LSL_Integer(0));
|
||||||
return OSDParser.SerializeJsonString(o);
|
|
||||||
}
|
if(!String.IsNullOrEmpty(json))
|
||||||
catch (Exception)
|
workData = LitJson.JsonMapper.ToObject(json);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
|
workData = new LitJson.JsonData();
|
||||||
|
workData.SetJsonType(LitJson.JsonType.Array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
string m = e.Message; // debug point
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LitJson.JsonData replace = JsonSetSpecific(workData, specifiers, 0, value);
|
||||||
|
if(replace != null)
|
||||||
|
workData = replace;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
string m = e.Message; // debug point
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string r = LitJson.JsonMapper.ToJson(workData);
|
||||||
|
if(noSpecifiers)
|
||||||
|
r = r.Substring(1,r.Length -2); // strip leading and trailing brakets
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
string m = e.Message; // debug point
|
||||||
}
|
}
|
||||||
return ScriptBaseClass.JSON_INVALID;
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void JsonSetSpecific(OSD o, LSL_List specifiers, int i, LSL_String val)
|
private LitJson.JsonData JsonSetSpecific(LitJson.JsonData elem, LSL_List specifiers, int level, LSL_String val)
|
||||||
{
|
{
|
||||||
object spec = specifiers.Data[i];
|
object spec = specifiers.Data[level];
|
||||||
// 20131224 not used object specNext = i+1 == specifiers.Data.Length ? null : specifiers.Data[i+1];
|
if(spec is LSL_String)
|
||||||
OSD nextVal = null;
|
spec = ((LSL_String)spec).m_string;
|
||||||
if (o is OSDArray)
|
else if (spec is LSL_Integer)
|
||||||
|
spec = ((LSL_Integer)spec).value;
|
||||||
|
|
||||||
|
if(!(spec is string || spec is int))
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
int speclen = specifiers.Data.Length - 1;
|
||||||
|
|
||||||
|
bool hasvalue = false;
|
||||||
|
LitJson.JsonData value = null;
|
||||||
|
|
||||||
|
LitJson.JsonType elemType = elem.GetJsonType();
|
||||||
|
if (elemType == LitJson.JsonType.Array)
|
||||||
|
{
|
||||||
|
if (spec is int)
|
||||||
|
{
|
||||||
|
int v = (int)spec;
|
||||||
|
int c = elem.Count;
|
||||||
|
if(v < 0 || (v != 0 && v > c))
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
if(v == c)
|
||||||
|
elem.Add(JsonBuildRestOfSpec(specifiers, level + 1, val));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hasvalue = true;
|
||||||
|
value = elem[v];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (spec is string)
|
||||||
|
{
|
||||||
|
if((string)spec == ScriptBaseClass.JSON_APPEND)
|
||||||
|
elem.Add(JsonBuildRestOfSpec(specifiers, level + 1, val));
|
||||||
|
else if(elem.Count < 2)
|
||||||
|
{
|
||||||
|
// our initial guess of array was wrong
|
||||||
|
LitJson.JsonData newdata = new LitJson.JsonData();
|
||||||
|
newdata.SetJsonType(LitJson.JsonType.Object);
|
||||||
|
IOrderedDictionary no = newdata as IOrderedDictionary;
|
||||||
|
no.Add((string)spec,JsonBuildRestOfSpec(specifiers, level + 1, val));
|
||||||
|
return newdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (elemType == LitJson.JsonType.Object)
|
||||||
|
{
|
||||||
|
if (spec is string)
|
||||||
|
{
|
||||||
|
IOrderedDictionary e = elem as IOrderedDictionary;
|
||||||
|
string key = (string)spec;
|
||||||
|
if(e.Contains(key))
|
||||||
|
{
|
||||||
|
hasvalue = true;
|
||||||
|
value = (LitJson.JsonData)e[key];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
e.Add(key, JsonBuildRestOfSpec(specifiers, level + 1, val));
|
||||||
|
}
|
||||||
|
else if(spec is int && (int)spec == 0)
|
||||||
|
{
|
||||||
|
//we are replacing a object by a array
|
||||||
|
LitJson.JsonData newData = new LitJson.JsonData();
|
||||||
|
newData.SetJsonType(LitJson.JsonType.Array);
|
||||||
|
newData.Add(JsonBuildRestOfSpec(specifiers, level + 1, val));
|
||||||
|
return newData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LitJson.JsonData newData = JsonBuildRestOfSpec(specifiers, level, val);
|
||||||
|
return newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasvalue)
|
||||||
|
{
|
||||||
|
if (level < speclen)
|
||||||
|
{
|
||||||
|
LitJson.JsonData replace = JsonSetSpecific(value, specifiers, level + 1, val);
|
||||||
|
if(replace != null)
|
||||||
|
{
|
||||||
|
if(elemType == LitJson.JsonType.Array)
|
||||||
|
{
|
||||||
|
if(spec is int)
|
||||||
|
elem[(int)spec] = replace;
|
||||||
|
else if( spec is string)
|
||||||
|
{
|
||||||
|
LitJson.JsonData newdata = new LitJson.JsonData();
|
||||||
|
newdata.SetJsonType(LitJson.JsonType.Object);
|
||||||
|
IOrderedDictionary no = newdata as IOrderedDictionary;
|
||||||
|
no.Add((string)spec, replace);
|
||||||
|
return newdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(elemType == LitJson.JsonType.Object)
|
||||||
|
{
|
||||||
|
if(spec is string)
|
||||||
|
elem[(string)spec] = replace;
|
||||||
|
else if(spec is int && (int)spec == 0)
|
||||||
|
{
|
||||||
|
LitJson.JsonData newdata = new LitJson.JsonData();
|
||||||
|
newdata.SetJsonType(LitJson.JsonType.Array);
|
||||||
|
newdata.Add(replace);
|
||||||
|
return newdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if(speclen == level)
|
||||||
|
{
|
||||||
|
if(val == ScriptBaseClass.JSON_DELETE)
|
||||||
|
{
|
||||||
|
if(elemType == LitJson.JsonType.Array)
|
||||||
|
{
|
||||||
|
if(spec is int)
|
||||||
|
{
|
||||||
|
IList el = elem as IList;
|
||||||
|
el.RemoveAt((int)spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(elemType == LitJson.JsonType.Object)
|
||||||
|
{
|
||||||
|
if(spec is string)
|
||||||
|
{
|
||||||
|
IOrderedDictionary eo = elem as IOrderedDictionary;
|
||||||
|
eo.Remove((string) spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LitJson.JsonData newval = null;
|
||||||
|
float num;
|
||||||
|
if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null")
|
||||||
|
newval = null;
|
||||||
|
else if(val == ScriptBaseClass.JSON_TRUE || val == "true")
|
||||||
|
newval = new LitJson.JsonData(true);
|
||||||
|
else if(val == ScriptBaseClass.JSON_FALSE || val == "false")
|
||||||
|
newval = new LitJson.JsonData(false);
|
||||||
|
else if(float.TryParse(val, out num))
|
||||||
|
{
|
||||||
|
// assuming we are at en.us already
|
||||||
|
if(num - (int)num == 0.0f && !val.Contains("."))
|
||||||
|
newval = new LitJson.JsonData((int)num);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num = (float)Math.Round(num,6);
|
||||||
|
newval = new LitJson.JsonData((double)num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string str = val.m_string;
|
||||||
|
newval = new LitJson.JsonData(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(elemType == LitJson.JsonType.Array)
|
||||||
|
{
|
||||||
|
if(spec is int)
|
||||||
|
elem[(int)spec] = newval;
|
||||||
|
else if( spec is string)
|
||||||
|
{
|
||||||
|
LitJson.JsonData newdata = new LitJson.JsonData();
|
||||||
|
newdata.SetJsonType(LitJson.JsonType.Object);
|
||||||
|
IOrderedDictionary no = newdata as IOrderedDictionary;
|
||||||
|
no.Add((string)spec,newval);
|
||||||
|
return newdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(elemType == LitJson.JsonType.Object)
|
||||||
|
{
|
||||||
|
if(spec is string)
|
||||||
|
elem[(string)spec] = newval;
|
||||||
|
else if(spec is int && (int)spec == 0)
|
||||||
|
{
|
||||||
|
LitJson.JsonData newdata = new LitJson.JsonData();
|
||||||
|
newdata.SetJsonType(LitJson.JsonType.Array);
|
||||||
|
newdata.Add(newval);
|
||||||
|
return newdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(val == ScriptBaseClass.JSON_DELETE)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LitJson.JsonData JsonBuildRestOfSpec(LSL_List specifiers, int level, LSL_String val)
|
||||||
|
{
|
||||||
|
object spec = level >= specifiers.Data.Length ? null : specifiers.Data[level];
|
||||||
|
// 20131224 not used object specNext = i+1 >= specifiers.Data.Length ? null : specifiers.Data[i+1];
|
||||||
|
|
||||||
|
float num;
|
||||||
|
if (spec == null)
|
||||||
|
{
|
||||||
|
if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null")
|
||||||
|
return null;
|
||||||
|
if(val == ScriptBaseClass.JSON_DELETE)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
if(val == ScriptBaseClass.JSON_TRUE || val == "true")
|
||||||
|
return new LitJson.JsonData(true);
|
||||||
|
if(val == ScriptBaseClass.JSON_FALSE || val == "false")
|
||||||
|
return new LitJson.JsonData(false);
|
||||||
|
if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null")
|
||||||
|
return null;
|
||||||
|
if(float.TryParse(val, out num))
|
||||||
|
{
|
||||||
|
// assuming we are at en.us already
|
||||||
|
if(num - (int)num == 0.0f && !val.Contains("."))
|
||||||
|
return new LitJson.JsonData((int)num);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num = (float)Math.Round(num,6);
|
||||||
|
return new LitJson.JsonData(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string str = val.m_string;
|
||||||
|
return new LitJson.JsonData(str);
|
||||||
|
}
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(spec is LSL_String)
|
||||||
|
spec = ((LSL_String)spec).m_string;
|
||||||
|
else if (spec is LSL_Integer)
|
||||||
|
spec = ((LSL_Integer)spec).value;
|
||||||
|
|
||||||
|
if (spec is int ||
|
||||||
|
(spec is string && ((string)spec) == ScriptBaseClass.JSON_APPEND) )
|
||||||
|
{
|
||||||
|
if(spec is int && (int)spec != 0)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
LitJson.JsonData newdata = new LitJson.JsonData();
|
||||||
|
newdata.SetJsonType(LitJson.JsonType.Array);
|
||||||
|
newdata.Add(JsonBuildRestOfSpec(specifiers, level + 1, val));
|
||||||
|
return newdata;
|
||||||
|
}
|
||||||
|
else if (spec is string)
|
||||||
|
{
|
||||||
|
LitJson.JsonData newdata = new LitJson.JsonData();
|
||||||
|
newdata.SetJsonType(LitJson.JsonType.Object);
|
||||||
|
IOrderedDictionary no = newdata as IOrderedDictionary;
|
||||||
|
no.Add((string)spec,JsonBuildRestOfSpec(specifiers, level + 1, val));
|
||||||
|
return newdata;
|
||||||
|
}
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool JsonFind(LitJson.JsonData elem, LSL_List specifiers, int level, out LitJson.JsonData value)
|
||||||
|
{
|
||||||
|
value = null;
|
||||||
|
if(elem == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
object spec;
|
||||||
|
spec = specifiers.Data[level];
|
||||||
|
|
||||||
|
bool haveVal = false;
|
||||||
|
LitJson.JsonData next = null;
|
||||||
|
|
||||||
|
if (elem.GetJsonType() == LitJson.JsonType.Array)
|
||||||
{
|
{
|
||||||
OSDArray array = ((OSDArray)o);
|
|
||||||
if (spec is LSL_Integer)
|
if (spec is LSL_Integer)
|
||||||
{
|
{
|
||||||
int v = ((LSL_Integer)spec).value;
|
int indx = (LSL_Integer)spec;
|
||||||
if (v >= array.Count)
|
if(indx >= 0 && indx < elem.Count)
|
||||||
array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val));
|
{
|
||||||
else
|
haveVal = true;
|
||||||
nextVal = ((OSDArray)o)[v];
|
next = (LitJson.JsonData)elem[indx];
|
||||||
}
|
}
|
||||||
else if (spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND)
|
|
||||||
array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val));
|
|
||||||
}
|
}
|
||||||
if (o is OSDMap)
|
}
|
||||||
|
else if (elem.GetJsonType() == LitJson.JsonType.Object)
|
||||||
{
|
{
|
||||||
if (spec is LSL_String)
|
if (spec is LSL_String)
|
||||||
{
|
{
|
||||||
OSDMap map = ((OSDMap)o);
|
IOrderedDictionary e = elem as IOrderedDictionary;
|
||||||
if (map.ContainsKey(((LSL_String)spec).m_string))
|
string key = (LSL_String)spec;
|
||||||
nextVal = map[((LSL_String)spec).m_string];
|
if(e.Contains(key))
|
||||||
|
{
|
||||||
|
haveVal = true;
|
||||||
|
next = (LitJson.JsonData)e[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (haveVal)
|
||||||
|
{
|
||||||
|
if(level == specifiers.Data.Length - 1)
|
||||||
|
{
|
||||||
|
value = next;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
level++;
|
||||||
|
if(next == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
LitJson.JsonType nextType = next.GetJsonType();
|
||||||
|
if(nextType != LitJson.JsonType.Object && nextType != LitJson.JsonType.Array)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return JsonFind(next, specifiers, level, out value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers)
|
||||||
|
{
|
||||||
|
if(String.IsNullOrWhiteSpace(json))
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
|
||||||
|
if(specifiers.Length > 0 && (json == "{}" || json == "[]"))
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
|
||||||
|
char first = ((string)json)[0];
|
||||||
|
if((first != '[' && first !='{'))
|
||||||
|
{
|
||||||
|
if(specifiers.Length > 0)
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
json = "[" + json + "]"; // could handle single element case.. but easier like this
|
||||||
|
specifiers.Add((LSL_Integer)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
LitJson.JsonData jsonData;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
jsonData = LitJson.JsonMapper.ToObject(json);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
string m = e.Message; // debug point
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
LitJson.JsonData elem = null;
|
||||||
|
if(specifiers.Length == 0)
|
||||||
|
elem = jsonData;
|
||||||
else
|
else
|
||||||
map.Add(((LSL_String)spec).m_string, JsonBuildRestOfSpec(specifiers, i + 1, val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nextVal != null)
|
|
||||||
{
|
{
|
||||||
if (specifiers.Data.Length - 1 > i)
|
if(!JsonFind(jsonData, specifiers, 0, out elem))
|
||||||
{
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
JsonSetSpecific(nextVal, specifiers, i + 1, val);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return JsonElementToString(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OSD JsonBuildRestOfSpec(LSL_List specifiers, int i, LSL_String val)
|
private LSL_String JsonElementToString(LitJson.JsonData elem)
|
||||||
{
|
{
|
||||||
object spec = i >= specifiers.Data.Length ? null : specifiers.Data[i];
|
if(elem == null)
|
||||||
// 20131224 not used object specNext = i+1 >= specifiers.Data.Length ? null : specifiers.Data[i+1];
|
return ScriptBaseClass.JSON_NULL;
|
||||||
|
|
||||||
if (spec == null)
|
LitJson.JsonType elemType = elem.GetJsonType();
|
||||||
return OSD.FromString(val);
|
switch(elemType)
|
||||||
|
|
||||||
if (spec is LSL_Integer ||
|
|
||||||
(spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND))
|
|
||||||
{
|
{
|
||||||
OSDArray array = new OSDArray();
|
case LitJson.JsonType.Array:
|
||||||
array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val));
|
return new LSL_String(LitJson.JsonMapper.ToJson(elem));
|
||||||
return array;
|
case LitJson.JsonType.Boolean:
|
||||||
|
return new LSL_String((bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE);
|
||||||
|
case LitJson.JsonType.Double:
|
||||||
|
double d= (double)elem;
|
||||||
|
string sd = String.Format(Culture.FormatProvider, "{0:0.0#####}",d);
|
||||||
|
return new LSL_String(sd);
|
||||||
|
case LitJson.JsonType.Int:
|
||||||
|
int i = (int)elem;
|
||||||
|
return new LSL_String(i.ToString());
|
||||||
|
case LitJson.JsonType.Long:
|
||||||
|
long l = (long)elem;
|
||||||
|
return new LSL_String(l.ToString());
|
||||||
|
case LitJson.JsonType.Object:
|
||||||
|
return new LSL_String(LitJson.JsonMapper.ToJson(elem));
|
||||||
|
case LitJson.JsonType.String:
|
||||||
|
string s = (string)elem;
|
||||||
|
return new LSL_String(s);
|
||||||
|
case LitJson.JsonType.None:
|
||||||
|
return ScriptBaseClass.JSON_NULL;
|
||||||
|
default:
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
}
|
}
|
||||||
else if (spec is LSL_String)
|
|
||||||
{
|
|
||||||
OSDMap map = new OSDMap();
|
|
||||||
map.Add((LSL_String)spec, JsonBuildRestOfSpec(specifiers, i + 1, val));
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
return new OSD();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LSL_String llJsonValueType(LSL_String json, LSL_List specifiers)
|
public LSL_String llJsonValueType(LSL_String json, LSL_List specifiers)
|
||||||
{
|
{
|
||||||
OSD o = OSDParser.DeserializeJson(json);
|
if(String.IsNullOrWhiteSpace(json))
|
||||||
OSD specVal = JsonGetSpecific(o, specifiers, 0);
|
|
||||||
if (specVal == null)
|
|
||||||
return ScriptBaseClass.JSON_INVALID;
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
switch (specVal.Type)
|
|
||||||
|
if(specifiers.Length > 0 && (json == "{}" || json == "[]"))
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
|
||||||
|
char first = ((string)json)[0];
|
||||||
|
if((first != '[' && first !='{'))
|
||||||
{
|
{
|
||||||
case OSDType.Array:
|
if(specifiers.Length > 0)
|
||||||
return ScriptBaseClass.JSON_ARRAY;
|
|
||||||
case OSDType.Boolean:
|
|
||||||
return specVal.AsBoolean() ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE;
|
|
||||||
case OSDType.Integer:
|
|
||||||
case OSDType.Real:
|
|
||||||
return ScriptBaseClass.JSON_NUMBER;
|
|
||||||
case OSDType.Map:
|
|
||||||
return ScriptBaseClass.JSON_OBJECT;
|
|
||||||
case OSDType.String:
|
|
||||||
case OSDType.UUID:
|
|
||||||
return ScriptBaseClass.JSON_STRING;
|
|
||||||
case OSDType.Unknown:
|
|
||||||
return ScriptBaseClass.JSON_NULL;
|
|
||||||
}
|
|
||||||
return ScriptBaseClass.JSON_INVALID;
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
json = "[" + json + "]"; // could handle single element case.. but easier like this
|
||||||
|
specifiers.Add((LSL_Integer)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
LitJson.JsonData jsonData;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
jsonData = LitJson.JsonMapper.ToObject(json);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
string m = e.Message; // debug point
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
LitJson.JsonData elem = null;
|
||||||
|
if(specifiers.Length == 0)
|
||||||
|
elem = jsonData;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!JsonFind(jsonData, specifiers, 0, out elem))
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(elem == null)
|
||||||
|
return ScriptBaseClass.JSON_NULL;
|
||||||
|
|
||||||
|
LitJson.JsonType elemType = elem.GetJsonType();
|
||||||
|
switch(elemType)
|
||||||
|
{
|
||||||
|
case LitJson.JsonType.Array:
|
||||||
|
return ScriptBaseClass.JSON_ARRAY;
|
||||||
|
case LitJson.JsonType.Boolean:
|
||||||
|
return (bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE;
|
||||||
|
case LitJson.JsonType.Double:
|
||||||
|
case LitJson.JsonType.Int:
|
||||||
|
case LitJson.JsonType.Long:
|
||||||
|
return ScriptBaseClass.JSON_NUMBER;
|
||||||
|
case LitJson.JsonType.Object:
|
||||||
|
return ScriptBaseClass.JSON_OBJECT;
|
||||||
|
case LitJson.JsonType.String:
|
||||||
|
string s = (string)elem;
|
||||||
|
if(s == ScriptBaseClass.JSON_NULL)
|
||||||
|
return ScriptBaseClass.JSON_NULL;
|
||||||
|
if(s == ScriptBaseClass.JSON_TRUE)
|
||||||
|
return ScriptBaseClass.JSON_TRUE;
|
||||||
|
if(s == ScriptBaseClass.JSON_FALSE)
|
||||||
|
return ScriptBaseClass.JSON_FALSE;
|
||||||
|
return ScriptBaseClass.JSON_STRING;
|
||||||
|
case LitJson.JsonType.None:
|
||||||
|
return ScriptBaseClass.JSON_NULL;
|
||||||
|
default:
|
||||||
|
return ScriptBaseClass.JSON_INVALID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ using System;
|
||||||
using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
|
using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
|
||||||
using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
|
using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
|
||||||
using LSLInteger = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
|
using LSLInteger = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
|
||||||
|
using LSLString = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
|
||||||
|
|
||||||
namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||||
{
|
{
|
||||||
|
@ -834,15 +835,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||||
public const int KFM_CMD_STOP = 1;
|
public const int KFM_CMD_STOP = 1;
|
||||||
public const int KFM_CMD_PAUSE = 2;
|
public const int KFM_CMD_PAUSE = 2;
|
||||||
|
|
||||||
public const string JSON_ARRAY = "JSON_ARRAY";
|
public const string JSON_INVALID = "\uFDD0";
|
||||||
public const string JSON_OBJECT = "JSON_OBJECT";
|
public const string JSON_OBJECT = "\uFDD1";
|
||||||
public const string JSON_INVALID = "JSON_INVALID";
|
public const string JSON_ARRAY = "\uFDD2";
|
||||||
public const string JSON_NUMBER = "JSON_NUMBER";
|
public const string JSON_NUMBER = "\uFDD3";
|
||||||
public const string JSON_STRING = "JSON_STRING";
|
public const string JSON_STRING = "\uFDD4";
|
||||||
public const string JSON_TRUE = "JSON_TRUE";
|
public const string JSON_NULL = "\uFDD5";
|
||||||
public const string JSON_FALSE = "JSON_FALSE";
|
public const string JSON_TRUE = "\uFDD6";
|
||||||
public const string JSON_NULL = "JSON_NULL";
|
public const string JSON_FALSE = "\uFDD7";
|
||||||
public const string JSON_APPEND = "JSON_APPEND";
|
public const string JSON_DELETE = "\uFDD8";
|
||||||
|
public const string JSON_APPEND = "-1";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// process name parameter as regex
|
/// process name parameter as regex
|
||||||
|
|
Loading…
Reference in New Issue