diff options
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 769 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | 20 |
2 files changed, 650 insertions, 139 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 2000c44..d5f2e78 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -28,6 +28,7 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Collections.Specialized; | ||
31 | using System.Diagnostics; | 32 | using System.Diagnostics; |
32 | using System.Drawing; | 33 | using System.Drawing; |
33 | using System.Drawing.Imaging; | 34 | using System.Drawing.Imaging; |
@@ -40,7 +41,7 @@ using Nini.Config; | |||
40 | using log4net; | 41 | using log4net; |
41 | using OpenMetaverse; | 42 | using OpenMetaverse; |
42 | using OpenMetaverse.Assets; | 43 | using OpenMetaverse.Assets; |
43 | using OpenMetaverse.StructuredData; | 44 | using OpenMetaverse.StructuredData; // LitJson is hidden on this |
44 | using OpenMetaverse.Packets; | 45 | using OpenMetaverse.Packets; |
45 | using OpenMetaverse.Rendering; | 46 | using OpenMetaverse.Rendering; |
46 | using OpenSim; | 47 | using OpenSim; |
@@ -16700,92 +16701,158 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
16700 | return String.Empty; | 16701 | return String.Empty; |
16701 | } | 16702 | } |
16702 | 16703 | ||
16703 | public LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers) | 16704 | public LSL_List llJson2List(LSL_String json) |
16704 | { | 16705 | { |
16705 | OSD o = OSDParser.DeserializeJson(json); | 16706 | if(String.IsNullOrEmpty(json)) |
16706 | OSD specVal = JsonGetSpecific(o, specifiers, 0); | 16707 | return new LSL_List(); |
16708 | if(json == "[]") | ||
16709 | return new LSL_List(); | ||
16710 | if(json == "{}") | ||
16711 | return new LSL_List(); | ||
16712 | char first = ((string)json)[0]; | ||
16707 | 16713 | ||
16708 | return specVal.AsString(); | 16714 | if(first != '[' && first !='{') |
16709 | } | 16715 | { |
16716 | // we already have a single element | ||
16717 | LSL_List l = new LSL_List(); | ||
16718 | l.Add(json); | ||
16719 | return l; | ||
16720 | } | ||
16710 | 16721 | ||
16711 | public LSL_List llJson2List(LSL_String json) | 16722 | LitJson.JsonData jsdata; |
16712 | { | ||
16713 | try | 16723 | try |
16714 | { | 16724 | { |
16715 | OSD o = OSDParser.DeserializeJson(json); | 16725 | jsdata = LitJson.JsonMapper.ToObject(json); |
16716 | return (LSL_List)ParseJsonNode(o); | ||
16717 | } | 16726 | } |
16718 | catch (Exception) | 16727 | catch (Exception e) |
16728 | { | ||
16729 | string m = e.Message; // debug point | ||
16730 | return json; | ||
16731 | } | ||
16732 | try | ||
16733 | { | ||
16734 | return JsonParseTop(jsdata); | ||
16735 | } | ||
16736 | catch (Exception e) | ||
16719 | { | 16737 | { |
16720 | return new LSL_List(ScriptBaseClass.JSON_INVALID); | 16738 | string m = e.Message; // debug point |
16739 | return (LSL_String)ScriptBaseClass.JSON_INVALID; | ||
16721 | } | 16740 | } |
16722 | } | 16741 | } |
16723 | 16742 | ||
16724 | private object ParseJsonNode(OSD node) | 16743 | private LSL_List JsonParseTop(LitJson.JsonData elem) |
16725 | { | 16744 | { |
16726 | if (node.Type == OSDType.Integer) | 16745 | LSL_List retl = new LSL_List(); |
16727 | return new LSL_Integer(node.AsInteger()); | 16746 | if(elem == null) |
16728 | if (node.Type == OSDType.Boolean) | 16747 | retl.Add((LSL_String)ScriptBaseClass.JSON_NULL); |
16729 | return new LSL_Integer(node.AsBoolean() ? 1 : 0); | 16748 | |
16730 | if (node.Type == OSDType.Real) | 16749 | LitJson.JsonType elemType = elem.GetJsonType(); |
16731 | return new LSL_Float(node.AsReal()); | 16750 | switch (elemType) |
16732 | if (node.Type == OSDType.UUID || node.Type == OSDType.String) | 16751 | { |
16733 | return new LSL_String(node.AsString()); | 16752 | case LitJson.JsonType.Int: |
16734 | if (node.Type == OSDType.Array) | 16753 | retl.Add(new LSL_Integer((int)elem)); |
16735 | { | 16754 | return retl; |
16736 | LSL_List resp = new LSL_List(); | 16755 | case LitJson.JsonType.Boolean: |
16737 | OSDArray ar = node as OSDArray; | 16756 | retl.Add((LSL_String)((bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE)); |
16738 | foreach (OSD o in ar) | 16757 | return retl; |
16739 | resp.Add(ParseJsonNode(o)); | 16758 | case LitJson.JsonType.Double: |
16740 | return resp; | 16759 | retl.Add(new LSL_Float((float)elem)); |
16760 | return retl; | ||
16761 | case LitJson.JsonType.None: | ||
16762 | retl.Add((LSL_String)ScriptBaseClass.JSON_NULL); | ||
16763 | return retl; | ||
16764 | case LitJson.JsonType.String: | ||
16765 | retl.Add(new LSL_String((string)elem)); | ||
16766 | return retl; | ||
16767 | case LitJson.JsonType.Array: | ||
16768 | foreach (LitJson.JsonData subelem in elem) | ||
16769 | retl.Add(JsonParseTopNodes(subelem)); | ||
16770 | return retl; | ||
16771 | case LitJson.JsonType.Object: | ||
16772 | IDictionaryEnumerator e = ((IOrderedDictionary)elem).GetEnumerator(); | ||
16773 | while (e.MoveNext()) | ||
16774 | { | ||
16775 | retl.Add(new LSL_String((string)e.Key)); | ||
16776 | retl.Add(JsonParseTopNodes((LitJson.JsonData)e.Value)); | ||
16777 | } | ||
16778 | return retl; | ||
16779 | default: | ||
16780 | throw new Exception(ScriptBaseClass.JSON_INVALID); | ||
16741 | } | 16781 | } |
16742 | if (node.Type == OSDType.Map) | 16782 | } |
16783 | |||
16784 | private object JsonParseTopNodes(LitJson.JsonData elem) | ||
16785 | { | ||
16786 | if(elem == null) | ||
16787 | return ((LSL_String)ScriptBaseClass.JSON_NULL); | ||
16788 | |||
16789 | LitJson.JsonType elemType = elem.GetJsonType(); | ||
16790 | switch (elemType) | ||
16743 | { | 16791 | { |
16744 | LSL_List resp = new LSL_List(); | 16792 | case LitJson.JsonType.Int: |
16745 | OSDMap ar = node as OSDMap; | 16793 | return (new LSL_Integer((int)elem)); |
16746 | foreach (KeyValuePair<string, OSD> o in ar) | 16794 | case LitJson.JsonType.Boolean: |
16747 | { | 16795 | return ((bool)elem ? (LSL_String)ScriptBaseClass.JSON_TRUE : (LSL_String)ScriptBaseClass.JSON_FALSE); |
16748 | resp.Add(new LSL_String(o.Key)); | 16796 | case LitJson.JsonType.Double: |
16749 | resp.Add(ParseJsonNode(o.Value)); | 16797 | return (new LSL_Float((float)elem)); |
16750 | } | 16798 | case LitJson.JsonType.None: |
16751 | return resp; | 16799 | return ((LSL_String)ScriptBaseClass.JSON_NULL); |
16800 | case LitJson.JsonType.String: | ||
16801 | return (new LSL_String((string)elem)); | ||
16802 | case LitJson.JsonType.Array: | ||
16803 | case LitJson.JsonType.Object: | ||
16804 | string s = LitJson.JsonMapper.ToJson(elem); | ||
16805 | return (LSL_String)s; | ||
16806 | default: | ||
16807 | throw new Exception(ScriptBaseClass.JSON_INVALID); | ||
16752 | } | 16808 | } |
16753 | throw new Exception(ScriptBaseClass.JSON_INVALID); | ||
16754 | } | 16809 | } |
16755 | 16810 | ||
16756 | public LSL_String llList2Json(LSL_String type, LSL_List values) | 16811 | public LSL_String llList2Json(LSL_String type, LSL_List values) |
16757 | { | 16812 | { |
16758 | try | 16813 | try |
16759 | { | 16814 | { |
16815 | StringBuilder sb = new StringBuilder(); | ||
16760 | if (type == ScriptBaseClass.JSON_ARRAY) | 16816 | if (type == ScriptBaseClass.JSON_ARRAY) |
16761 | { | 16817 | { |
16762 | OSDArray array = new OSDArray(); | 16818 | sb.Append("["); |
16819 | int i= 0; | ||
16763 | foreach (object o in values.Data) | 16820 | foreach (object o in values.Data) |
16764 | { | 16821 | { |
16765 | array.Add(ListToJson(o)); | 16822 | sb.Append(ListToJson(o)); |
16823 | if((i++) < values.Data.Length - 1) | ||
16824 | sb.Append(","); | ||
16766 | } | 16825 | } |
16767 | return OSDParser.SerializeJsonString(array); | 16826 | sb.Append("]"); |
16827 | return (LSL_String)sb.ToString();; | ||
16768 | } | 16828 | } |
16769 | else if (type == ScriptBaseClass.JSON_OBJECT) | 16829 | else if (type == ScriptBaseClass.JSON_OBJECT) |
16770 | { | 16830 | { |
16771 | OSDMap map = new OSDMap(); | 16831 | sb.Append("{"); |
16772 | for (int i = 0; i < values.Data.Length; i += 2) | 16832 | for (int i = 0; i < values.Data.Length; i += 2) |
16773 | { | 16833 | { |
16774 | if (!(values.Data[i] is LSL_String)) | 16834 | if (!(values.Data[i] is LSL_String)) |
16775 | return ScriptBaseClass.JSON_INVALID; | 16835 | return ScriptBaseClass.JSON_INVALID; |
16776 | map.Add(((LSL_String)values.Data[i]).m_string, ListToJson(values.Data[i + 1])); | 16836 | string key = ((LSL_String)values.Data[i]).m_string; |
16837 | key = EscapeForJSON(key, true); | ||
16838 | sb.Append(key); | ||
16839 | sb.Append(":"); | ||
16840 | sb.Append(ListToJson(values.Data[i+1])); | ||
16841 | if(i < values.Data.Length - 2) | ||
16842 | sb.Append(","); | ||
16777 | } | 16843 | } |
16778 | return OSDParser.SerializeJsonString(map); | 16844 | sb.Append("}"); |
16845 | return (LSL_String)sb.ToString(); | ||
16779 | } | 16846 | } |
16780 | return ScriptBaseClass.JSON_INVALID; | 16847 | return ScriptBaseClass.JSON_INVALID; |
16781 | } | 16848 | } |
16782 | catch (Exception ex) | 16849 | catch |
16783 | { | 16850 | { |
16784 | return ex.Message; | 16851 | return ScriptBaseClass.JSON_INVALID; |
16785 | } | 16852 | } |
16786 | } | 16853 | } |
16787 | 16854 | ||
16788 | private OSD ListToJson(object o) | 16855 | private string ListToJson(object o) |
16789 | { | 16856 | { |
16790 | if (o is LSL_Float || o is double) | 16857 | if (o is LSL_Float || o is double) |
16791 | { | 16858 | { |
@@ -16795,7 +16862,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
16795 | else | 16862 | else |
16796 | float_val = ((LSL_Float)o).value; | 16863 | float_val = ((LSL_Float)o).value; |
16797 | 16864 | ||
16798 | return OSD.FromReal(float_val); | 16865 | if(double.IsInfinity(float_val)) |
16866 | return "\"Inf\""; | ||
16867 | if(double.IsNaN(float_val)) | ||
16868 | return "\"NaN\""; | ||
16869 | |||
16870 | return ((LSL_Float)float_val).ToString(); | ||
16799 | } | 16871 | } |
16800 | if (o is LSL_Integer || o is int) | 16872 | if (o is LSL_Integer || o is int) |
16801 | { | 16873 | { |
@@ -16804,17 +16876,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
16804 | i = ((int)o); | 16876 | i = ((int)o); |
16805 | else | 16877 | else |
16806 | i = ((LSL_Integer)o).value; | 16878 | i = ((LSL_Integer)o).value; |
16807 | 16879 | return i.ToString(); | |
16808 | if (i == 0) | ||
16809 | return OSD.FromBoolean(false); | ||
16810 | else if (i == 1) | ||
16811 | return OSD.FromBoolean(true); | ||
16812 | return OSD.FromInteger(i); | ||
16813 | } | 16880 | } |
16814 | if (o is LSL_Rotation) | 16881 | if (o is LSL_Rotation) |
16815 | return OSD.FromString(((LSL_Rotation)o).ToString()); | 16882 | return ((LSL_Rotation)o).ToString(); |
16816 | if (o is LSL_Vector) | 16883 | if (o is LSL_Vector) |
16817 | return OSD.FromString(((LSL_Vector)o).ToString()); | 16884 | return ((LSL_Vector)o).ToString(); |
16818 | if (o is LSL_String || o is string) | 16885 | if (o is LSL_String || o is string) |
16819 | { | 16886 | { |
16820 | string str; | 16887 | string str; |
@@ -16823,137 +16890,579 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
16823 | else | 16890 | else |
16824 | str = ((LSL_String)o).m_string; | 16891 | str = ((LSL_String)o).m_string; |
16825 | 16892 | ||
16826 | if (str == ScriptBaseClass.JSON_NULL) | 16893 | if(str == ScriptBaseClass.JSON_TRUE || str == "true") |
16827 | return new OSD(); | 16894 | return "true"; |
16828 | return OSD.FromString(str); | 16895 | if(str == ScriptBaseClass.JSON_FALSE ||str == "false") |
16896 | return "false"; | ||
16897 | if(str == ScriptBaseClass.JSON_NULL || str == "null") | ||
16898 | return "null"; | ||
16899 | str.Trim(); | ||
16900 | if (str[0] == '{') | ||
16901 | return str; | ||
16902 | if (str[0] == '[') | ||
16903 | return str; | ||
16904 | return EscapeForJSON(str, true); | ||
16829 | } | 16905 | } |
16830 | throw new Exception(ScriptBaseClass.JSON_INVALID); | 16906 | throw new IndexOutOfRangeException(); |
16831 | } | 16907 | } |
16832 | 16908 | ||
16833 | private OSD JsonGetSpecific(OSD o, LSL_List specifiers, int i) | 16909 | private string EscapeForJSON(string s, bool AddOuter) |
16834 | { | 16910 | { |
16835 | object spec = specifiers.Data[i]; | 16911 | int i; |
16836 | OSD nextVal = null; | 16912 | char c; |
16837 | if (o is OSDArray) | 16913 | String t; |
16914 | int len = s.Length; | ||
16915 | |||
16916 | StringBuilder sb = new StringBuilder(len + 64); | ||
16917 | if(AddOuter) | ||
16918 | sb.Append("\""); | ||
16919 | |||
16920 | for (i = 0; i < len; i++) | ||
16838 | { | 16921 | { |
16839 | if (spec is LSL_Integer) | 16922 | c = s[i]; |
16840 | nextVal = ((OSDArray)o)[((LSL_Integer)spec).value]; | 16923 | switch (c) |
16924 | { | ||
16925 | case '\\': | ||
16926 | case '"': | ||
16927 | case '/': | ||
16928 | sb.Append('\\'); | ||
16929 | sb.Append(c); | ||
16930 | break; | ||
16931 | case '\b': | ||
16932 | sb.Append("\\b"); | ||
16933 | break; | ||
16934 | case '\t': | ||
16935 | sb.Append("\\t"); | ||
16936 | break; | ||
16937 | case '\n': | ||
16938 | sb.Append("\\n"); | ||
16939 | break; | ||
16940 | case '\f': | ||
16941 | sb.Append("\\f"); | ||
16942 | break; | ||
16943 | case '\r': | ||
16944 | sb.Append("\\r"); | ||
16945 | break; | ||
16946 | default: | ||
16947 | if (c < ' ') | ||
16948 | { | ||
16949 | t = "000" + String.Format("X", c); | ||
16950 | sb.Append("\\u" + t.Substring(t.Length - 4)); | ||
16951 | } | ||
16952 | else | ||
16953 | { | ||
16954 | sb.Append(c); | ||
16955 | } | ||
16956 | break; | ||
16957 | } | ||
16958 | } | ||
16959 | if(AddOuter) | ||
16960 | sb.Append("\""); | ||
16961 | return sb.ToString(); | ||
16962 | } | ||
16963 | |||
16964 | public LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value) | ||
16965 | { | ||
16966 | bool noSpecifiers = specifiers.Length == 0; | ||
16967 | LitJson.JsonData workData; | ||
16968 | try | ||
16969 | { | ||
16970 | if(noSpecifiers) | ||
16971 | specifiers.Add(new LSL_Integer(0)); | ||
16972 | |||
16973 | if(!String.IsNullOrEmpty(json)) | ||
16974 | workData = LitJson.JsonMapper.ToObject(json); | ||
16975 | else | ||
16976 | { | ||
16977 | workData = new LitJson.JsonData(); | ||
16978 | workData.SetJsonType(LitJson.JsonType.Array); | ||
16979 | } | ||
16841 | } | 16980 | } |
16842 | if (o is OSDMap) | 16981 | catch (Exception e) |
16843 | { | 16982 | { |
16844 | if (spec is LSL_String) | 16983 | string m = e.Message; // debug point |
16845 | nextVal = ((OSDMap)o)[((LSL_String)spec).m_string]; | 16984 | return ScriptBaseClass.JSON_INVALID; |
16846 | } | 16985 | } |
16847 | if (nextVal != null) | 16986 | try |
16848 | { | 16987 | { |
16849 | if (specifiers.Data.Length - 1 > i) | 16988 | LitJson.JsonData replace = JsonSetSpecific(workData, specifiers, 0, value); |
16850 | return JsonGetSpecific(nextVal, specifiers, i + 1); | 16989 | if(replace != null) |
16990 | workData = replace; | ||
16991 | } | ||
16992 | catch (Exception e) | ||
16993 | { | ||
16994 | string m = e.Message; // debug point | ||
16995 | return ScriptBaseClass.JSON_INVALID; | ||
16851 | } | 16996 | } |
16852 | return nextVal; | ||
16853 | } | ||
16854 | 16997 | ||
16855 | public LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value) | ||
16856 | { | ||
16857 | try | 16998 | try |
16858 | { | 16999 | { |
16859 | OSD o = OSDParser.DeserializeJson(json); | 17000 | string r = LitJson.JsonMapper.ToJson(workData); |
16860 | JsonSetSpecific(o, specifiers, 0, value); | 17001 | if(noSpecifiers) |
16861 | return OSDParser.SerializeJsonString(o); | 17002 | r = r.Substring(1,r.Length -2); // strip leading and trailing brakets |
17003 | return r; | ||
16862 | } | 17004 | } |
16863 | catch (Exception) | 17005 | catch (Exception e) |
16864 | { | 17006 | { |
17007 | string m = e.Message; // debug point | ||
16865 | } | 17008 | } |
16866 | return ScriptBaseClass.JSON_INVALID; | 17009 | return ScriptBaseClass.JSON_INVALID; |
16867 | } | 17010 | } |
16868 | 17011 | ||
16869 | private void JsonSetSpecific(OSD o, LSL_List specifiers, int i, LSL_String val) | 17012 | private LitJson.JsonData JsonSetSpecific(LitJson.JsonData elem, LSL_List specifiers, int level, LSL_String val) |
16870 | { | 17013 | { |
16871 | object spec = specifiers.Data[i]; | 17014 | object spec = specifiers.Data[level]; |
16872 | // 20131224 not used object specNext = i+1 == specifiers.Data.Length ? null : specifiers.Data[i+1]; | 17015 | if(spec is LSL_String) |
16873 | OSD nextVal = null; | 17016 | spec = ((LSL_String)spec).m_string; |
16874 | if (o is OSDArray) | 17017 | else if (spec is LSL_Integer) |
17018 | spec = ((LSL_Integer)spec).value; | ||
17019 | |||
17020 | if(!(spec is string || spec is int)) | ||
17021 | throw new IndexOutOfRangeException(); | ||
17022 | |||
17023 | int speclen = specifiers.Data.Length - 1; | ||
17024 | |||
17025 | bool hasvalue = false; | ||
17026 | LitJson.JsonData value = null; | ||
17027 | |||
17028 | LitJson.JsonType elemType = elem.GetJsonType(); | ||
17029 | if (elemType == LitJson.JsonType.Array) | ||
16875 | { | 17030 | { |
16876 | OSDArray array = ((OSDArray)o); | 17031 | if (spec is int) |
16877 | if (spec is LSL_Integer) | ||
16878 | { | 17032 | { |
16879 | int v = ((LSL_Integer)spec).value; | 17033 | int v = (int)spec; |
16880 | if (v >= array.Count) | 17034 | int c = elem.Count; |
16881 | array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val)); | 17035 | if(v < 0 || (v != 0 && v > c)) |
17036 | throw new IndexOutOfRangeException(); | ||
17037 | if(v == c) | ||
17038 | elem.Add(JsonBuildRestOfSpec(specifiers, level + 1, val)); | ||
16882 | else | 17039 | else |
16883 | nextVal = ((OSDArray)o)[v]; | 17040 | { |
17041 | hasvalue = true; | ||
17042 | value = elem[v]; | ||
17043 | } | ||
17044 | } | ||
17045 | else if (spec is string) | ||
17046 | { | ||
17047 | if((string)spec == ScriptBaseClass.JSON_APPEND) | ||
17048 | elem.Add(JsonBuildRestOfSpec(specifiers, level + 1, val)); | ||
17049 | else if(elem.Count < 2) | ||
17050 | { | ||
17051 | // our initial guess of array was wrong | ||
17052 | LitJson.JsonData newdata = new LitJson.JsonData(); | ||
17053 | newdata.SetJsonType(LitJson.JsonType.Object); | ||
17054 | IOrderedDictionary no = newdata as IOrderedDictionary; | ||
17055 | no.Add((string)spec,JsonBuildRestOfSpec(specifiers, level + 1, val)); | ||
17056 | return newdata; | ||
17057 | } | ||
16884 | } | 17058 | } |
16885 | else if (spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND) | ||
16886 | array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val)); | ||
16887 | } | 17059 | } |
16888 | if (o is OSDMap) | 17060 | else if (elemType == LitJson.JsonType.Object) |
16889 | { | 17061 | { |
16890 | if (spec is LSL_String) | 17062 | if (spec is string) |
16891 | { | 17063 | { |
16892 | OSDMap map = ((OSDMap)o); | 17064 | IOrderedDictionary e = elem as IOrderedDictionary; |
16893 | if (map.ContainsKey(((LSL_String)spec).m_string)) | 17065 | string key = (string)spec; |
16894 | nextVal = map[((LSL_String)spec).m_string]; | 17066 | if(e.Contains(key)) |
17067 | { | ||
17068 | hasvalue = true; | ||
17069 | value = (LitJson.JsonData)e[key]; | ||
17070 | } | ||
16895 | else | 17071 | else |
16896 | map.Add(((LSL_String)spec).m_string, JsonBuildRestOfSpec(specifiers, i + 1, val)); | 17072 | e.Add(key, JsonBuildRestOfSpec(specifiers, level + 1, val)); |
16897 | } | 17073 | } |
17074 | else if(spec is int && (int)spec == 0) | ||
17075 | { | ||
17076 | //we are replacing a object by a array | ||
17077 | LitJson.JsonData newData = new LitJson.JsonData(); | ||
17078 | newData.SetJsonType(LitJson.JsonType.Array); | ||
17079 | newData.Add(JsonBuildRestOfSpec(specifiers, level + 1, val)); | ||
17080 | return newData; | ||
17081 | } | ||
17082 | } | ||
17083 | else | ||
17084 | { | ||
17085 | LitJson.JsonData newData = JsonBuildRestOfSpec(specifiers, level, val); | ||
17086 | return newData; | ||
16898 | } | 17087 | } |
16899 | if (nextVal != null) | 17088 | |
17089 | if (hasvalue) | ||
16900 | { | 17090 | { |
16901 | if (specifiers.Data.Length - 1 > i) | 17091 | if (level < speclen) |
16902 | { | 17092 | { |
16903 | JsonSetSpecific(nextVal, specifiers, i + 1, val); | 17093 | LitJson.JsonData replace = JsonSetSpecific(value, specifiers, level + 1, val); |
16904 | return; | 17094 | if(replace != null) |
17095 | { | ||
17096 | if(elemType == LitJson.JsonType.Array) | ||
17097 | { | ||
17098 | if(spec is int) | ||
17099 | elem[(int)spec] = replace; | ||
17100 | else if( spec is string) | ||
17101 | { | ||
17102 | LitJson.JsonData newdata = new LitJson.JsonData(); | ||
17103 | newdata.SetJsonType(LitJson.JsonType.Object); | ||
17104 | IOrderedDictionary no = newdata as IOrderedDictionary; | ||
17105 | no.Add((string)spec, replace); | ||
17106 | return newdata; | ||
17107 | } | ||
17108 | } | ||
17109 | else if(elemType == LitJson.JsonType.Object) | ||
17110 | { | ||
17111 | if(spec is string) | ||
17112 | elem[(string)spec] = replace; | ||
17113 | else if(spec is int && (int)spec == 0) | ||
17114 | { | ||
17115 | LitJson.JsonData newdata = new LitJson.JsonData(); | ||
17116 | newdata.SetJsonType(LitJson.JsonType.Array); | ||
17117 | newdata.Add(replace); | ||
17118 | return newdata; | ||
17119 | } | ||
17120 | } | ||
17121 | } | ||
17122 | return null; | ||
17123 | } | ||
17124 | else if(speclen == level) | ||
17125 | { | ||
17126 | if(val == ScriptBaseClass.JSON_DELETE) | ||
17127 | { | ||
17128 | if(elemType == LitJson.JsonType.Array) | ||
17129 | { | ||
17130 | if(spec is int) | ||
17131 | { | ||
17132 | IList el = elem as IList; | ||
17133 | el.RemoveAt((int)spec); | ||
17134 | } | ||
17135 | } | ||
17136 | else if(elemType == LitJson.JsonType.Object) | ||
17137 | { | ||
17138 | if(spec is string) | ||
17139 | { | ||
17140 | IOrderedDictionary eo = elem as IOrderedDictionary; | ||
17141 | eo.Remove((string) spec); | ||
17142 | } | ||
17143 | } | ||
17144 | return null; | ||
17145 | } | ||
17146 | |||
17147 | LitJson.JsonData newval = null; | ||
17148 | float num; | ||
17149 | if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null") | ||
17150 | newval = null; | ||
17151 | else if(val == ScriptBaseClass.JSON_TRUE || val == "true") | ||
17152 | newval = new LitJson.JsonData(true); | ||
17153 | else if(val == ScriptBaseClass.JSON_FALSE || val == "false") | ||
17154 | newval = new LitJson.JsonData(false); | ||
17155 | else if(float.TryParse(val, out num)) | ||
17156 | { | ||
17157 | // assuming we are at en.us already | ||
17158 | if(num - (int)num == 0.0f && !val.Contains(".")) | ||
17159 | newval = new LitJson.JsonData((int)num); | ||
17160 | else | ||
17161 | { | ||
17162 | num = (float)Math.Round(num,6); | ||
17163 | newval = new LitJson.JsonData((double)num); | ||
17164 | } | ||
17165 | } | ||
17166 | else | ||
17167 | { | ||
17168 | string str = val.m_string; | ||
17169 | newval = new LitJson.JsonData(str); | ||
17170 | } | ||
17171 | |||
17172 | if(elemType == LitJson.JsonType.Array) | ||
17173 | { | ||
17174 | if(spec is int) | ||
17175 | elem[(int)spec] = newval; | ||
17176 | else if( spec is string) | ||
17177 | { | ||
17178 | LitJson.JsonData newdata = new LitJson.JsonData(); | ||
17179 | newdata.SetJsonType(LitJson.JsonType.Object); | ||
17180 | IOrderedDictionary no = newdata as IOrderedDictionary; | ||
17181 | no.Add((string)spec,newval); | ||
17182 | return newdata; | ||
17183 | } | ||
17184 | } | ||
17185 | else if(elemType == LitJson.JsonType.Object) | ||
17186 | { | ||
17187 | if(spec is string) | ||
17188 | elem[(string)spec] = newval; | ||
17189 | else if(spec is int && (int)spec == 0) | ||
17190 | { | ||
17191 | LitJson.JsonData newdata = new LitJson.JsonData(); | ||
17192 | newdata.SetJsonType(LitJson.JsonType.Array); | ||
17193 | newdata.Add(newval); | ||
17194 | return newdata; | ||
17195 | } | ||
17196 | } | ||
16905 | } | 17197 | } |
16906 | } | 17198 | } |
17199 | if(val == ScriptBaseClass.JSON_DELETE) | ||
17200 | throw new IndexOutOfRangeException(); | ||
17201 | return null; | ||
16907 | } | 17202 | } |
16908 | 17203 | ||
16909 | private OSD JsonBuildRestOfSpec(LSL_List specifiers, int i, LSL_String val) | 17204 | private LitJson.JsonData JsonBuildRestOfSpec(LSL_List specifiers, int level, LSL_String val) |
16910 | { | 17205 | { |
16911 | object spec = i >= specifiers.Data.Length ? null : specifiers.Data[i]; | 17206 | object spec = level >= specifiers.Data.Length ? null : specifiers.Data[level]; |
16912 | // 20131224 not used object specNext = i+1 >= specifiers.Data.Length ? null : specifiers.Data[i+1]; | 17207 | // 20131224 not used object specNext = i+1 >= specifiers.Data.Length ? null : specifiers.Data[i+1]; |
16913 | 17208 | ||
17209 | float num; | ||
16914 | if (spec == null) | 17210 | if (spec == null) |
16915 | return OSD.FromString(val); | 17211 | { |
17212 | if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null") | ||
17213 | return null; | ||
17214 | if(val == ScriptBaseClass.JSON_DELETE) | ||
17215 | throw new IndexOutOfRangeException(); | ||
17216 | if(val == ScriptBaseClass.JSON_TRUE || val == "true") | ||
17217 | return new LitJson.JsonData(true); | ||
17218 | if(val == ScriptBaseClass.JSON_FALSE || val == "false") | ||
17219 | return new LitJson.JsonData(false); | ||
17220 | if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null") | ||
17221 | return null; | ||
17222 | if(float.TryParse(val, out num)) | ||
17223 | { | ||
17224 | // assuming we are at en.us already | ||
17225 | if(num - (int)num == 0.0f && !val.Contains(".")) | ||
17226 | return new LitJson.JsonData((int)num); | ||
17227 | else | ||
17228 | { | ||
17229 | num = (float)Math.Round(num,6); | ||
17230 | return new LitJson.JsonData(num); | ||
17231 | } | ||
17232 | } | ||
17233 | else | ||
17234 | { | ||
17235 | string str = val.m_string; | ||
17236 | return new LitJson.JsonData(str); | ||
17237 | } | ||
17238 | throw new IndexOutOfRangeException(); | ||
17239 | } | ||
16916 | 17240 | ||
16917 | if (spec is LSL_Integer || | 17241 | if(spec is LSL_String) |
16918 | (spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND)) | 17242 | spec = ((LSL_String)spec).m_string; |
17243 | else if (spec is LSL_Integer) | ||
17244 | spec = ((LSL_Integer)spec).value; | ||
17245 | |||
17246 | if (spec is int || | ||
17247 | (spec is string && ((string)spec) == ScriptBaseClass.JSON_APPEND) ) | ||
16919 | { | 17248 | { |
16920 | OSDArray array = new OSDArray(); | 17249 | if(spec is int && (int)spec != 0) |
16921 | array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val)); | 17250 | throw new IndexOutOfRangeException(); |
16922 | return array; | 17251 | LitJson.JsonData newdata = new LitJson.JsonData(); |
17252 | newdata.SetJsonType(LitJson.JsonType.Array); | ||
17253 | newdata.Add(JsonBuildRestOfSpec(specifiers, level + 1, val)); | ||
17254 | return newdata; | ||
16923 | } | 17255 | } |
16924 | else if (spec is LSL_String) | 17256 | else if (spec is string) |
16925 | { | 17257 | { |
16926 | OSDMap map = new OSDMap(); | 17258 | LitJson.JsonData newdata = new LitJson.JsonData(); |
16927 | map.Add((LSL_String)spec, JsonBuildRestOfSpec(specifiers, i + 1, val)); | 17259 | newdata.SetJsonType(LitJson.JsonType.Object); |
16928 | return map; | 17260 | IOrderedDictionary no = newdata as IOrderedDictionary; |
17261 | no.Add((string)spec,JsonBuildRestOfSpec(specifiers, level + 1, val)); | ||
17262 | return newdata; | ||
17263 | } | ||
17264 | throw new IndexOutOfRangeException(); | ||
17265 | } | ||
17266 | |||
17267 | private bool JsonFind(LitJson.JsonData elem, LSL_List specifiers, int level, out LitJson.JsonData value) | ||
17268 | { | ||
17269 | value = null; | ||
17270 | if(elem == null) | ||
17271 | return false; | ||
17272 | |||
17273 | object spec; | ||
17274 | spec = specifiers.Data[level]; | ||
17275 | |||
17276 | bool haveVal = false; | ||
17277 | LitJson.JsonData next = null; | ||
17278 | |||
17279 | if (elem.GetJsonType() == LitJson.JsonType.Array) | ||
17280 | { | ||
17281 | if (spec is LSL_Integer) | ||
17282 | { | ||
17283 | int indx = (LSL_Integer)spec; | ||
17284 | if(indx >= 0 && indx < elem.Count) | ||
17285 | { | ||
17286 | haveVal = true; | ||
17287 | next = (LitJson.JsonData)elem[indx]; | ||
17288 | } | ||
17289 | } | ||
17290 | } | ||
17291 | else if (elem.GetJsonType() == LitJson.JsonType.Object) | ||
17292 | { | ||
17293 | if (spec is LSL_String) | ||
17294 | { | ||
17295 | IOrderedDictionary e = elem as IOrderedDictionary; | ||
17296 | string key = (LSL_String)spec; | ||
17297 | if(e.Contains(key)) | ||
17298 | { | ||
17299 | haveVal = true; | ||
17300 | next = (LitJson.JsonData)e[key]; | ||
17301 | } | ||
17302 | } | ||
17303 | } | ||
17304 | |||
17305 | if (haveVal) | ||
17306 | { | ||
17307 | if(level == specifiers.Data.Length - 1) | ||
17308 | { | ||
17309 | value = next; | ||
17310 | return true; | ||
17311 | } | ||
17312 | |||
17313 | level++; | ||
17314 | if(next == null) | ||
17315 | return false; | ||
17316 | |||
17317 | LitJson.JsonType nextType = next.GetJsonType(); | ||
17318 | if(nextType != LitJson.JsonType.Object && nextType != LitJson.JsonType.Array) | ||
17319 | return false; | ||
17320 | |||
17321 | return JsonFind(next, specifiers, level, out value); | ||
17322 | } | ||
17323 | return false; | ||
17324 | } | ||
17325 | |||
17326 | public LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers) | ||
17327 | { | ||
17328 | if(String.IsNullOrWhiteSpace(json)) | ||
17329 | return ScriptBaseClass.JSON_INVALID; | ||
17330 | |||
17331 | if(specifiers.Length > 0 && (json == "{}" || json == "[]")) | ||
17332 | return ScriptBaseClass.JSON_INVALID; | ||
17333 | |||
17334 | char first = ((string)json)[0]; | ||
17335 | if((first != '[' && first !='{')) | ||
17336 | { | ||
17337 | if(specifiers.Length > 0) | ||
17338 | return ScriptBaseClass.JSON_INVALID; | ||
17339 | json = "[" + json + "]"; // could handle single element case.. but easier like this | ||
17340 | specifiers.Add((LSL_Integer)0); | ||
17341 | } | ||
17342 | |||
17343 | LitJson.JsonData jsonData; | ||
17344 | try | ||
17345 | { | ||
17346 | jsonData = LitJson.JsonMapper.ToObject(json); | ||
17347 | } | ||
17348 | catch (Exception e) | ||
17349 | { | ||
17350 | string m = e.Message; // debug point | ||
17351 | return ScriptBaseClass.JSON_INVALID; | ||
17352 | } | ||
17353 | |||
17354 | LitJson.JsonData elem = null; | ||
17355 | if(specifiers.Length == 0) | ||
17356 | elem = jsonData; | ||
17357 | else | ||
17358 | { | ||
17359 | if(!JsonFind(jsonData, specifiers, 0, out elem)) | ||
17360 | return ScriptBaseClass.JSON_INVALID; | ||
17361 | } | ||
17362 | return JsonElementToString(elem); | ||
17363 | } | ||
17364 | |||
17365 | private LSL_String JsonElementToString(LitJson.JsonData elem) | ||
17366 | { | ||
17367 | if(elem == null) | ||
17368 | return ScriptBaseClass.JSON_NULL; | ||
17369 | |||
17370 | LitJson.JsonType elemType = elem.GetJsonType(); | ||
17371 | switch(elemType) | ||
17372 | { | ||
17373 | case LitJson.JsonType.Array: | ||
17374 | return new LSL_String(LitJson.JsonMapper.ToJson(elem)); | ||
17375 | case LitJson.JsonType.Boolean: | ||
17376 | return new LSL_String((bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE); | ||
17377 | case LitJson.JsonType.Double: | ||
17378 | double d= (double)elem; | ||
17379 | string sd = String.Format(Culture.FormatProvider, "{0:0.0#####}",d); | ||
17380 | return new LSL_String(sd); | ||
17381 | case LitJson.JsonType.Int: | ||
17382 | int i = (int)elem; | ||
17383 | return new LSL_String(i.ToString()); | ||
17384 | case LitJson.JsonType.Long: | ||
17385 | long l = (long)elem; | ||
17386 | return new LSL_String(l.ToString()); | ||
17387 | case LitJson.JsonType.Object: | ||
17388 | return new LSL_String(LitJson.JsonMapper.ToJson(elem)); | ||
17389 | case LitJson.JsonType.String: | ||
17390 | string s = (string)elem; | ||
17391 | return new LSL_String(s); | ||
17392 | case LitJson.JsonType.None: | ||
17393 | return ScriptBaseClass.JSON_NULL; | ||
17394 | default: | ||
17395 | return ScriptBaseClass.JSON_INVALID; | ||
16929 | } | 17396 | } |
16930 | return new OSD(); | ||
16931 | } | 17397 | } |
16932 | 17398 | ||
16933 | public LSL_String llJsonValueType(LSL_String json, LSL_List specifiers) | 17399 | public LSL_String llJsonValueType(LSL_String json, LSL_List specifiers) |
16934 | { | 17400 | { |
16935 | OSD o = OSDParser.DeserializeJson(json); | 17401 | if(String.IsNullOrWhiteSpace(json)) |
16936 | OSD specVal = JsonGetSpecific(o, specifiers, 0); | ||
16937 | if (specVal == null) | ||
16938 | return ScriptBaseClass.JSON_INVALID; | 17402 | return ScriptBaseClass.JSON_INVALID; |
16939 | switch (specVal.Type) | 17403 | |
17404 | if(specifiers.Length > 0 && (json == "{}" || json == "[]")) | ||
17405 | return ScriptBaseClass.JSON_INVALID; | ||
17406 | |||
17407 | char first = ((string)json)[0]; | ||
17408 | if((first != '[' && first !='{')) | ||
17409 | { | ||
17410 | if(specifiers.Length > 0) | ||
17411 | return ScriptBaseClass.JSON_INVALID; | ||
17412 | json = "[" + json + "]"; // could handle single element case.. but easier like this | ||
17413 | specifiers.Add((LSL_Integer)0); | ||
17414 | } | ||
17415 | |||
17416 | LitJson.JsonData jsonData; | ||
17417 | try | ||
16940 | { | 17418 | { |
16941 | case OSDType.Array: | 17419 | jsonData = LitJson.JsonMapper.ToObject(json); |
17420 | } | ||
17421 | catch (Exception e) | ||
17422 | { | ||
17423 | string m = e.Message; // debug point | ||
17424 | return ScriptBaseClass.JSON_INVALID; | ||
17425 | } | ||
17426 | |||
17427 | LitJson.JsonData elem = null; | ||
17428 | if(specifiers.Length == 0) | ||
17429 | elem = jsonData; | ||
17430 | else | ||
17431 | { | ||
17432 | if(!JsonFind(jsonData, specifiers, 0, out elem)) | ||
17433 | return ScriptBaseClass.JSON_INVALID; | ||
17434 | } | ||
17435 | |||
17436 | if(elem == null) | ||
17437 | return ScriptBaseClass.JSON_NULL; | ||
17438 | |||
17439 | LitJson.JsonType elemType = elem.GetJsonType(); | ||
17440 | switch(elemType) | ||
17441 | { | ||
17442 | case LitJson.JsonType.Array: | ||
16942 | return ScriptBaseClass.JSON_ARRAY; | 17443 | return ScriptBaseClass.JSON_ARRAY; |
16943 | case OSDType.Boolean: | 17444 | case LitJson.JsonType.Boolean: |
16944 | return specVal.AsBoolean() ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE; | 17445 | return (bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE; |
16945 | case OSDType.Integer: | 17446 | case LitJson.JsonType.Double: |
16946 | case OSDType.Real: | 17447 | case LitJson.JsonType.Int: |
17448 | case LitJson.JsonType.Long: | ||
16947 | return ScriptBaseClass.JSON_NUMBER; | 17449 | return ScriptBaseClass.JSON_NUMBER; |
16948 | case OSDType.Map: | 17450 | case LitJson.JsonType.Object: |
16949 | return ScriptBaseClass.JSON_OBJECT; | 17451 | return ScriptBaseClass.JSON_OBJECT; |
16950 | case OSDType.String: | 17452 | case LitJson.JsonType.String: |
16951 | case OSDType.UUID: | 17453 | string s = (string)elem; |
17454 | if(s == ScriptBaseClass.JSON_NULL) | ||
17455 | return ScriptBaseClass.JSON_NULL; | ||
17456 | if(s == ScriptBaseClass.JSON_TRUE) | ||
17457 | return ScriptBaseClass.JSON_TRUE; | ||
17458 | if(s == ScriptBaseClass.JSON_FALSE) | ||
17459 | return ScriptBaseClass.JSON_FALSE; | ||
16952 | return ScriptBaseClass.JSON_STRING; | 17460 | return ScriptBaseClass.JSON_STRING; |
16953 | case OSDType.Unknown: | 17461 | case LitJson.JsonType.None: |
16954 | return ScriptBaseClass.JSON_NULL; | 17462 | return ScriptBaseClass.JSON_NULL; |
17463 | default: | ||
17464 | return ScriptBaseClass.JSON_INVALID; | ||
16955 | } | 17465 | } |
16956 | return ScriptBaseClass.JSON_INVALID; | ||
16957 | } | 17466 | } |
16958 | } | 17467 | } |
16959 | 17468 | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index ce0fa48..a277f6c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | |||
@@ -29,6 +29,7 @@ using System; | |||
29 | using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | 29 | using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; |
30 | using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; | 30 | using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; |
31 | using LSLInteger = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | 31 | using LSLInteger = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; |
32 | using LSLString = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
32 | 33 | ||
33 | namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | 34 | namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase |
34 | { | 35 | { |
@@ -834,15 +835,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
834 | public const int KFM_CMD_STOP = 1; | 835 | public const int KFM_CMD_STOP = 1; |
835 | public const int KFM_CMD_PAUSE = 2; | 836 | public const int KFM_CMD_PAUSE = 2; |
836 | 837 | ||
837 | public const string JSON_ARRAY = "JSON_ARRAY"; | 838 | public const string JSON_INVALID = "\uFDD0"; |
838 | public const string JSON_OBJECT = "JSON_OBJECT"; | 839 | public const string JSON_OBJECT = "\uFDD1"; |
839 | public const string JSON_INVALID = "JSON_INVALID"; | 840 | public const string JSON_ARRAY = "\uFDD2"; |
840 | public const string JSON_NUMBER = "JSON_NUMBER"; | 841 | public const string JSON_NUMBER = "\uFDD3"; |
841 | public const string JSON_STRING = "JSON_STRING"; | 842 | public const string JSON_STRING = "\uFDD4"; |
842 | public const string JSON_TRUE = "JSON_TRUE"; | 843 | public const string JSON_NULL = "\uFDD5"; |
843 | public const string JSON_FALSE = "JSON_FALSE"; | 844 | public const string JSON_TRUE = "\uFDD6"; |
844 | public const string JSON_NULL = "JSON_NULL"; | 845 | public const string JSON_FALSE = "\uFDD7"; |
845 | public const string JSON_APPEND = "JSON_APPEND"; | 846 | public const string JSON_DELETE = "\uFDD8"; |
847 | public const string JSON_APPEND = "-1"; | ||
846 | 848 | ||
847 | /// <summary> | 849 | /// <summary> |
848 | /// process name parameter as regex | 850 | /// process name parameter as regex |