PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs

https://bitbucket.org/AlethiaGrid/opensimulator-0.7-.x
C# | 2147 lines | 1689 code | 347 blank | 111 comment | 256 complexity | 904ed97bae202553a030ac2a0b67ff07 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections;
  29. using System.Globalization;
  30. using System.Text.RegularExpressions;
  31. using OpenSim.Framework;
  32. using OpenMetaverse;
  33. using OMV_Vector3 = OpenMetaverse.Vector3;
  34. using OMV_Vector3d = OpenMetaverse.Vector3d;
  35. using OMV_Quaternion = OpenMetaverse.Quaternion;
  36. namespace OpenSim.Region.ScriptEngine.Shared
  37. {
  38. [Serializable]
  39. public partial class LSL_Types
  40. {
  41. // Types are kept is separate .dll to avoid having to add whatever .dll it is in it to script AppDomain
  42. [Serializable]
  43. public struct Vector3
  44. {
  45. public double x;
  46. public double y;
  47. public double z;
  48. #region Constructors
  49. public Vector3(Vector3 vector)
  50. {
  51. x = (float)vector.x;
  52. y = (float)vector.y;
  53. z = (float)vector.z;
  54. }
  55. public Vector3(OMV_Vector3 vector)
  56. {
  57. x = vector.X;
  58. y = vector.Y;
  59. z = vector.Z;
  60. }
  61. public Vector3(OMV_Vector3d vector)
  62. {
  63. x = vector.X;
  64. y = vector.Y;
  65. z = vector.Z;
  66. }
  67. public Vector3(double X, double Y, double Z)
  68. {
  69. x = X;
  70. y = Y;
  71. z = Z;
  72. }
  73. public Vector3(string str)
  74. {
  75. str = str.Replace('<', ' ');
  76. str = str.Replace('>', ' ');
  77. string[] tmps = str.Split(new Char[] { ',', '<', '>' });
  78. if (tmps.Length < 3)
  79. {
  80. x=y=z=0;
  81. return;
  82. }
  83. bool res;
  84. res = Double.TryParse(tmps[0], NumberStyles.Float, Culture.NumberFormatInfo, out x);
  85. res = res & Double.TryParse(tmps[1], NumberStyles.Float, Culture.NumberFormatInfo, out y);
  86. res = res & Double.TryParse(tmps[2], NumberStyles.Float, Culture.NumberFormatInfo, out z);
  87. }
  88. #endregion
  89. #region Overriders
  90. public override string ToString()
  91. {
  92. string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", x, y, z);
  93. return s;
  94. }
  95. public static explicit operator LSLString(Vector3 vec)
  96. {
  97. string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z);
  98. return new LSLString(s);
  99. }
  100. public static explicit operator string(Vector3 vec)
  101. {
  102. string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z);
  103. return s;
  104. }
  105. public static explicit operator Vector3(string s)
  106. {
  107. return new Vector3(s);
  108. }
  109. public static implicit operator list(Vector3 vec)
  110. {
  111. return new list(new object[] { vec });
  112. }
  113. public static implicit operator OMV_Vector3(Vector3 vec)
  114. {
  115. return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z);
  116. }
  117. public static implicit operator Vector3(OMV_Vector3 vec)
  118. {
  119. return new Vector3(vec);
  120. }
  121. public static implicit operator OMV_Vector3d(Vector3 vec)
  122. {
  123. return new OMV_Vector3d(vec.x, vec.y, vec.z);
  124. }
  125. public static implicit operator Vector3(OMV_Vector3d vec)
  126. {
  127. return new Vector3(vec);
  128. }
  129. public static bool operator ==(Vector3 lhs, Vector3 rhs)
  130. {
  131. return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
  132. }
  133. public static bool operator !=(Vector3 lhs, Vector3 rhs)
  134. {
  135. return !(lhs == rhs);
  136. }
  137. public override int GetHashCode()
  138. {
  139. return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode());
  140. }
  141. public override bool Equals(object o)
  142. {
  143. if (!(o is Vector3)) return false;
  144. Vector3 vector = (Vector3)o;
  145. return (x == vector.x && y == vector.y && z == vector.z);
  146. }
  147. public static Vector3 operator -(Vector3 vector)
  148. {
  149. return new Vector3(-vector.x, -vector.y, -vector.z);
  150. }
  151. #endregion
  152. #region Vector & Vector Math
  153. // Vector-Vector Math
  154. public static Vector3 operator +(Vector3 lhs, Vector3 rhs)
  155. {
  156. return new Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z);
  157. }
  158. public static Vector3 operator -(Vector3 lhs, Vector3 rhs)
  159. {
  160. return new Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z);
  161. }
  162. public static LSLFloat operator *(Vector3 lhs, Vector3 rhs)
  163. {
  164. return Dot(lhs, rhs);
  165. }
  166. public static Vector3 operator %(Vector3 v1, Vector3 v2)
  167. {
  168. //Cross product
  169. Vector3 tv;
  170. tv.x = (v1.y * v2.z) - (v1.z * v2.y);
  171. tv.y = (v1.z * v2.x) - (v1.x * v2.z);
  172. tv.z = (v1.x * v2.y) - (v1.y * v2.x);
  173. return tv;
  174. }
  175. #endregion
  176. #region Vector & Float Math
  177. // Vector-Float and Float-Vector Math
  178. public static Vector3 operator *(Vector3 vec, float val)
  179. {
  180. return new Vector3(vec.x * val, vec.y * val, vec.z * val);
  181. }
  182. public static Vector3 operator *(float val, Vector3 vec)
  183. {
  184. return new Vector3(vec.x * val, vec.y * val, vec.z * val);
  185. }
  186. public static Vector3 operator /(Vector3 v, float f)
  187. {
  188. v.x = v.x / f;
  189. v.y = v.y / f;
  190. v.z = v.z / f;
  191. return v;
  192. }
  193. #endregion
  194. #region Vector & Double Math
  195. public static Vector3 operator *(Vector3 vec, double val)
  196. {
  197. return new Vector3(vec.x * val, vec.y * val, vec.z * val);
  198. }
  199. public static Vector3 operator *(double val, Vector3 vec)
  200. {
  201. return new Vector3(vec.x * val, vec.y * val, vec.z * val);
  202. }
  203. public static Vector3 operator /(Vector3 v, double f)
  204. {
  205. v.x = v.x / f;
  206. v.y = v.y / f;
  207. v.z = v.z / f;
  208. return v;
  209. }
  210. #endregion
  211. #region Vector & Rotation Math
  212. // Vector-Rotation Math
  213. public static Vector3 operator *(Vector3 v, Quaternion r)
  214. {
  215. Quaternion vq = new Quaternion(v.x, v.y, v.z, 0);
  216. Quaternion nq = new Quaternion(-r.x, -r.y, -r.z, r.s);
  217. // adapted for operator * computing "b * a"
  218. Quaternion result = nq * (vq * r);
  219. return new Vector3(result.x, result.y, result.z);
  220. }
  221. public static Vector3 operator /(Vector3 v, Quaternion r)
  222. {
  223. r.s = -r.s;
  224. return v * r;
  225. }
  226. #endregion
  227. #region Static Helper Functions
  228. public static double Dot(Vector3 v1, Vector3 v2)
  229. {
  230. return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
  231. }
  232. public static Vector3 Cross(Vector3 v1, Vector3 v2)
  233. {
  234. return new Vector3
  235. (
  236. v1.y * v2.z - v1.z * v2.y,
  237. v1.z * v2.x - v1.x * v2.z,
  238. v1.x * v2.y - v1.y * v2.x
  239. );
  240. }
  241. public static double Mag(Vector3 v)
  242. {
  243. return Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
  244. }
  245. public static Vector3 Norm(Vector3 vector)
  246. {
  247. double mag = Mag(vector);
  248. if (mag > 0.0)
  249. {
  250. double invMag = 1.0 / mag;
  251. return vector * invMag;
  252. }
  253. return new Vector3(0, 0, 0);
  254. }
  255. #endregion
  256. }
  257. [Serializable]
  258. public struct Quaternion
  259. {
  260. public double x;
  261. public double y;
  262. public double z;
  263. public double s;
  264. #region Constructors
  265. public Quaternion(Quaternion Quat)
  266. {
  267. x = (float)Quat.x;
  268. y = (float)Quat.y;
  269. z = (float)Quat.z;
  270. s = (float)Quat.s;
  271. if (x == 0 && y == 0 && z == 0 && s == 0)
  272. s = 1;
  273. }
  274. public Quaternion(double X, double Y, double Z, double S)
  275. {
  276. x = X;
  277. y = Y;
  278. z = Z;
  279. s = S;
  280. if (x == 0 && y == 0 && z == 0 && s == 0)
  281. s = 1;
  282. }
  283. public Quaternion(string str)
  284. {
  285. str = str.Replace('<', ' ');
  286. str = str.Replace('>', ' ');
  287. string[] tmps = str.Split(new Char[] { ',', '<', '>' });
  288. if (tmps.Length < 4)
  289. {
  290. x=y=z=s=0;
  291. return;
  292. }
  293. bool res;
  294. res = Double.TryParse(tmps[0], NumberStyles.Float, Culture.NumberFormatInfo, out x);
  295. res = res & Double.TryParse(tmps[1], NumberStyles.Float, Culture.NumberFormatInfo, out y);
  296. res = res & Double.TryParse(tmps[2], NumberStyles.Float, Culture.NumberFormatInfo, out z);
  297. res = res & Double.TryParse(tmps[3], NumberStyles.Float, Culture.NumberFormatInfo, out s);
  298. if (x == 0 && y == 0 && z == 0 && s == 0)
  299. s = 1;
  300. }
  301. public Quaternion(OMV_Quaternion rot)
  302. {
  303. x = rot.X;
  304. y = rot.Y;
  305. z = rot.Z;
  306. s = rot.W;
  307. }
  308. #endregion
  309. #region Overriders
  310. public override int GetHashCode()
  311. {
  312. return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ s.GetHashCode());
  313. }
  314. public override bool Equals(object o)
  315. {
  316. if (!(o is Quaternion)) return false;
  317. Quaternion quaternion = (Quaternion)o;
  318. return x == quaternion.x && y == quaternion.y && z == quaternion.z && s == quaternion.s;
  319. }
  320. public override string ToString()
  321. {
  322. string st=String.Format(Culture.FormatProvider, "<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", x, y, z, s);
  323. return st;
  324. }
  325. public static explicit operator string(Quaternion r)
  326. {
  327. string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s);
  328. return s;
  329. }
  330. public static explicit operator LSLString(Quaternion r)
  331. {
  332. string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s);
  333. return new LSLString(s);
  334. }
  335. public static explicit operator Quaternion(string s)
  336. {
  337. return new Quaternion(s);
  338. }
  339. public static implicit operator list(Quaternion r)
  340. {
  341. return new list(new object[] { r });
  342. }
  343. public static implicit operator OMV_Quaternion(Quaternion rot)
  344. {
  345. // LSL quaternions can normalize to 0, normal Quaternions can't.
  346. if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
  347. rot.z = 1; // ZERO_ROTATION = 0,0,0,1
  348. OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
  349. omvrot.Normalize();
  350. return omvrot;
  351. }
  352. public static implicit operator Quaternion(OMV_Quaternion rot)
  353. {
  354. return new Quaternion(rot);
  355. }
  356. public static bool operator ==(Quaternion lhs, Quaternion rhs)
  357. {
  358. // Return true if the fields match:
  359. return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.s == rhs.s;
  360. }
  361. public static bool operator !=(Quaternion lhs, Quaternion rhs)
  362. {
  363. return !(lhs == rhs);
  364. }
  365. public static double Mag(Quaternion q)
  366. {
  367. return Math.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.s * q.s);
  368. }
  369. #endregion
  370. public static Quaternion operator +(Quaternion a, Quaternion b)
  371. {
  372. return new Quaternion(a.x + b.x, a.y + b.y, a.z + b.z, a.s + b.s);
  373. }
  374. public static Quaternion operator /(Quaternion a, Quaternion b)
  375. {
  376. b.s = -b.s;
  377. return a * b;
  378. }
  379. public static Quaternion operator -(Quaternion a, Quaternion b)
  380. {
  381. return new Quaternion(a.x - b.x, a.y - b.y, a.z - b.z, a.s - b.s);
  382. }
  383. // using the equations below, we need to do "b * a" to be compatible with LSL
  384. public static Quaternion operator *(Quaternion b, Quaternion a)
  385. {
  386. Quaternion c;
  387. c.x = a.s * b.x + a.x * b.s + a.y * b.z - a.z * b.y;
  388. c.y = a.s * b.y + a.y * b.s + a.z * b.x - a.x * b.z;
  389. c.z = a.s * b.z + a.z * b.s + a.x * b.y - a.y * b.x;
  390. c.s = a.s * b.s - a.x * b.x - a.y * b.y - a.z * b.z;
  391. return c;
  392. }
  393. }
  394. [Serializable]
  395. public class list
  396. {
  397. private object[] m_data;
  398. public list(params object[] args)
  399. {
  400. m_data = args;
  401. }
  402. public int Length
  403. {
  404. get
  405. {
  406. if (m_data == null)
  407. m_data=new Object[0];
  408. return m_data.Length;
  409. }
  410. }
  411. public int Size
  412. {
  413. get
  414. {
  415. if (m_data == null)
  416. m_data=new Object[0];
  417. int size = 0;
  418. foreach (Object o in m_data)
  419. {
  420. if (o is LSL_Types.LSLInteger)
  421. size += 4;
  422. else if (o is LSL_Types.LSLFloat)
  423. size += 8;
  424. else if (o is LSL_Types.LSLString)
  425. size += ((LSL_Types.LSLString)o).m_string.Length;
  426. else if (o is LSL_Types.key)
  427. size += ((LSL_Types.key)o).value.Length;
  428. else if (o is LSL_Types.Vector3)
  429. size += 32;
  430. else if (o is LSL_Types.Quaternion)
  431. size += 64;
  432. else if (o is int)
  433. size += 4;
  434. else if (o is string)
  435. size += ((string)o).Length;
  436. else if (o is float)
  437. size += 8;
  438. else if (o is double)
  439. size += 16;
  440. else
  441. throw new Exception("Unknown type in List.Size: " + o.GetType().ToString());
  442. }
  443. return size;
  444. }
  445. }
  446. public object[] Data
  447. {
  448. get {
  449. if (m_data == null)
  450. m_data=new Object[0];
  451. return m_data;
  452. }
  453. set {m_data = value; }
  454. }
  455. // Function to obtain LSL type from an index. This is needed
  456. // because LSL lists allow for multiple types, and safely
  457. // iterating in them requires a type check.
  458. public Type GetLSLListItemType(int itemIndex)
  459. {
  460. return m_data[itemIndex].GetType();
  461. }
  462. // Member functions to obtain item as specific types.
  463. // For cases where implicit conversions would apply if items
  464. // were not in a list (e.g. integer to float, but not float
  465. // to integer) functions check for alternate types so as to
  466. // down-cast from Object to the correct type.
  467. // Note: no checks for item index being valid are performed
  468. public LSL_Types.LSLFloat GetLSLFloatItem(int itemIndex)
  469. {
  470. if (m_data[itemIndex] is LSL_Types.LSLInteger)
  471. {
  472. return (LSL_Types.LSLInteger)m_data[itemIndex];
  473. }
  474. else if (m_data[itemIndex] is Int32)
  475. {
  476. return new LSL_Types.LSLFloat((int)m_data[itemIndex]);
  477. }
  478. else if (m_data[itemIndex] is float)
  479. {
  480. return new LSL_Types.LSLFloat((float)m_data[itemIndex]);
  481. }
  482. else if (m_data[itemIndex] is Double)
  483. {
  484. return new LSL_Types.LSLFloat((Double)m_data[itemIndex]);
  485. }
  486. else if (m_data[itemIndex] is LSL_Types.LSLString)
  487. {
  488. return new LSL_Types.LSLFloat(m_data[itemIndex].ToString());
  489. }
  490. else
  491. {
  492. return (LSL_Types.LSLFloat)m_data[itemIndex];
  493. }
  494. }
  495. public LSL_Types.LSLString GetLSLStringItem(int itemIndex)
  496. {
  497. if (m_data[itemIndex] is LSL_Types.key)
  498. {
  499. return (LSL_Types.key)m_data[itemIndex];
  500. }
  501. else if (m_data[itemIndex] is String)
  502. {
  503. return new LSL_Types.LSLString((string)m_data[itemIndex]);
  504. }
  505. else if (m_data[itemIndex] is LSL_Types.LSLFloat)
  506. {
  507. return new LSL_Types.LSLString((LSLFloat)m_data[itemIndex]);
  508. }
  509. else if (m_data[itemIndex] is LSL_Types.LSLInteger)
  510. {
  511. return new LSL_Types.LSLString((LSLInteger)m_data[itemIndex]);
  512. }
  513. else
  514. {
  515. return (LSL_Types.LSLString)m_data[itemIndex];
  516. }
  517. }
  518. public LSL_Types.LSLInteger GetLSLIntegerItem(int itemIndex)
  519. {
  520. if (m_data[itemIndex] is LSL_Types.LSLInteger)
  521. return (LSL_Types.LSLInteger)m_data[itemIndex];
  522. if (m_data[itemIndex] is LSL_Types.LSLFloat)
  523. return new LSLInteger((int)m_data[itemIndex]);
  524. else if (m_data[itemIndex] is Int32)
  525. return new LSLInteger((int)m_data[itemIndex]);
  526. else if (m_data[itemIndex] is LSL_Types.LSLString)
  527. return new LSLInteger(m_data[itemIndex].ToString());
  528. else
  529. throw new InvalidCastException(string.Format(
  530. "{0} expected but {1} given",
  531. typeof(LSL_Types.LSLInteger).Name,
  532. m_data[itemIndex] != null ?
  533. m_data[itemIndex].GetType().Name : "null"));
  534. }
  535. public LSL_Types.Vector3 GetVector3Item(int itemIndex)
  536. {
  537. if (m_data[itemIndex] is LSL_Types.Vector3)
  538. {
  539. return (LSL_Types.Vector3)m_data[itemIndex];
  540. }
  541. else if(m_data[itemIndex] is OpenMetaverse.Vector3)
  542. {
  543. return new LSL_Types.Vector3(
  544. (OpenMetaverse.Vector3)m_data[itemIndex]);
  545. }
  546. else
  547. {
  548. throw new InvalidCastException(string.Format(
  549. "{0} expected but {1} given",
  550. typeof(LSL_Types.Vector3).Name,
  551. m_data[itemIndex] != null ?
  552. m_data[itemIndex].GetType().Name : "null"));
  553. }
  554. }
  555. public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
  556. {
  557. if (m_data[itemIndex] is LSL_Types.Quaternion)
  558. {
  559. return (LSL_Types.Quaternion)m_data[itemIndex];
  560. }
  561. else if(m_data[itemIndex] is OpenMetaverse.Quaternion)
  562. {
  563. return new LSL_Types.Quaternion(
  564. (OpenMetaverse.Quaternion)m_data[itemIndex]);
  565. }
  566. else
  567. {
  568. throw new InvalidCastException(string.Format(
  569. "{0} expected but {1} given",
  570. typeof(LSL_Types.Quaternion).Name,
  571. m_data[itemIndex] != null ?
  572. m_data[itemIndex].GetType().Name : "null"));
  573. }
  574. }
  575. public LSL_Types.key GetKeyItem(int itemIndex)
  576. {
  577. return (LSL_Types.key)m_data[itemIndex];
  578. }
  579. public static list operator +(list a, list b)
  580. {
  581. object[] tmp;
  582. tmp = new object[a.Length + b.Length];
  583. a.Data.CopyTo(tmp, 0);
  584. b.Data.CopyTo(tmp, a.Length);
  585. return new list(tmp);
  586. }
  587. private void ExtendAndAdd(object o)
  588. {
  589. Array.Resize(ref m_data, Length + 1);
  590. m_data.SetValue(o, Length - 1);
  591. }
  592. public static list operator +(list a, LSLString s)
  593. {
  594. a.ExtendAndAdd(s);
  595. return a;
  596. }
  597. public static list operator +(list a, LSLInteger i)
  598. {
  599. a.ExtendAndAdd(i);
  600. return a;
  601. }
  602. public static list operator +(list a, LSLFloat d)
  603. {
  604. a.ExtendAndAdd(d);
  605. return a;
  606. }
  607. public static bool operator ==(list a, list b)
  608. {
  609. int la = -1;
  610. int lb = -1;
  611. try { la = a.Length; }
  612. catch (NullReferenceException) { }
  613. try { lb = b.Length; }
  614. catch (NullReferenceException) { }
  615. return la == lb;
  616. }
  617. public static bool operator !=(list a, list b)
  618. {
  619. int la = -1;
  620. int lb = -1;
  621. try { la = a.Length; }
  622. catch (NullReferenceException) { }
  623. try {lb = b.Length;}
  624. catch (NullReferenceException) { }
  625. return la != lb;
  626. }
  627. public void Add(object o)
  628. {
  629. object[] tmp;
  630. tmp = new object[m_data.Length + 1];
  631. m_data.CopyTo(tmp, 0);
  632. tmp[m_data.Length] = o;
  633. m_data = tmp;
  634. }
  635. public bool Contains(object o)
  636. {
  637. bool ret = false;
  638. foreach (object i in Data)
  639. {
  640. if (i == o)
  641. {
  642. ret = true;
  643. break;
  644. }
  645. }
  646. return ret;
  647. }
  648. public list DeleteSublist(int start, int end)
  649. {
  650. // Not an easy one
  651. // If start <= end, remove that part
  652. // if either is negative, count from the end of the array
  653. // if the resulting start > end, remove all BUT that part
  654. Object[] ret;
  655. if (start < 0)
  656. start=m_data.Length+start;
  657. if (start < 0)
  658. start=0;
  659. if (end < 0)
  660. end=m_data.Length+end;
  661. if (end < 0)
  662. end=0;
  663. if (start > end)
  664. {
  665. if (end >= m_data.Length)
  666. return new list(new Object[0]);
  667. if (start >= m_data.Length)
  668. start=m_data.Length-1;
  669. return GetSublist(end, start);
  670. }
  671. // start >= 0 && end >= 0 here
  672. if (start >= m_data.Length)
  673. {
  674. ret=new Object[m_data.Length];
  675. Array.Copy(m_data, 0, ret, 0, m_data.Length);
  676. return new list(ret);
  677. }
  678. if (end >= m_data.Length)
  679. end=m_data.Length-1;
  680. // now, this makes the math easier
  681. int remove=end+1-start;
  682. ret=new Object[m_data.Length-remove];
  683. if (ret.Length == 0)
  684. return new list(ret);
  685. int src;
  686. int dest=0;
  687. for (src = 0; src < m_data.Length; src++)
  688. {
  689. if (src < start || src > end)
  690. ret[dest++]=m_data[src];
  691. }
  692. return new list(ret);
  693. }
  694. public list GetSublist(int start, int end)
  695. {
  696. object[] ret;
  697. // Take care of neg start or end's
  698. // NOTE that either index may still be negative after
  699. // adding the length, so we must take additional
  700. // measures to protect against this. Note also that
  701. // after normalisation the negative indices are no
  702. // longer relative to the end of the list.
  703. if (start < 0)
  704. {
  705. start = m_data.Length + start;
  706. }
  707. if (end < 0)
  708. {
  709. end = m_data.Length + end;
  710. }
  711. // The conventional case is start <= end
  712. // NOTE that the case of an empty list is
  713. // dealt with by the initial test. Start
  714. // less than end is taken to be the most
  715. // common case.
  716. if (start <= end)
  717. {
  718. // Start sublist beyond length
  719. // Also deals with start AND end still negative
  720. if (start >= m_data.Length || end < 0)
  721. {
  722. return new list();
  723. }
  724. // Sublist extends beyond the end of the supplied list
  725. if (end >= m_data.Length)
  726. {
  727. end = m_data.Length - 1;
  728. }
  729. // Sublist still starts before the beginning of the list
  730. if (start < 0)
  731. {
  732. start = 0;
  733. }
  734. ret = new object[end - start + 1];
  735. Array.Copy(m_data, start, ret, 0, end - start + 1);
  736. return new list(ret);
  737. }
  738. // Deal with the segmented case: 0->end + start->EOL
  739. else
  740. {
  741. list result = null;
  742. // If end is negative, then prefix list is empty
  743. if (end < 0)
  744. {
  745. result = new list();
  746. // If start is still negative, then the whole of
  747. // the existing list is returned. This case is
  748. // only admitted if end is also still negative.
  749. if (start < 0)
  750. {
  751. return this;
  752. }
  753. }
  754. else
  755. {
  756. result = GetSublist(0,end);
  757. }
  758. // If start is outside of list, then just return
  759. // the prefix, whatever it is.
  760. if (start >= m_data.Length)
  761. {
  762. return result;
  763. }
  764. return result + GetSublist(start, Data.Length);
  765. }
  766. }
  767. private static int compare(object left, object right, int ascending)
  768. {
  769. if (!left.GetType().Equals(right.GetType()))
  770. {
  771. // unequal types are always "equal" for comparison purposes.
  772. // this way, the bubble sort will never swap them, and we'll
  773. // get that feathered effect we're looking for
  774. return 0;
  775. }
  776. int ret = 0;
  777. if (left is key)
  778. {
  779. key l = (key)left;
  780. key r = (key)right;
  781. ret = String.CompareOrdinal(l.value, r.value);
  782. }
  783. else if (left is LSLString)
  784. {
  785. LSLString l = (LSLString)left;
  786. LSLString r = (LSLString)right;
  787. ret = String.CompareOrdinal(l.m_string, r.m_string);
  788. }
  789. else if (left is LSLInteger)
  790. {
  791. LSLInteger l = (LSLInteger)left;
  792. LSLInteger r = (LSLInteger)right;
  793. ret = Math.Sign(l.value - r.value);
  794. }
  795. else if (left is LSLFloat)
  796. {
  797. LSLFloat l = (LSLFloat)left;
  798. LSLFloat r = (LSLFloat)right;
  799. ret = Math.Sign(l.value - r.value);
  800. }
  801. else if (left is Vector3)
  802. {
  803. Vector3 l = (Vector3)left;
  804. Vector3 r = (Vector3)right;
  805. ret = Math.Sign(Vector3.Mag(l) - Vector3.Mag(r));
  806. }
  807. else if (left is Quaternion)
  808. {
  809. Quaternion l = (Quaternion)left;
  810. Quaternion r = (Quaternion)right;
  811. ret = Math.Sign(Quaternion.Mag(l) - Quaternion.Mag(r));
  812. }
  813. if (ascending == 0)
  814. {
  815. ret = 0 - ret;
  816. }
  817. return ret;
  818. }
  819. class HomogeneousComparer : IComparer
  820. {
  821. public HomogeneousComparer()
  822. {
  823. }
  824. public int Compare(object lhs, object rhs)
  825. {
  826. return compare(lhs, rhs, 1);
  827. }
  828. }
  829. public list Sort(int stride, int ascending)
  830. {
  831. if (Data.Length == 0)
  832. return new list(); // Don't even bother
  833. object[] ret = new object[Data.Length];
  834. Array.Copy(Data, 0, ret, 0, Data.Length);
  835. if (stride <= 0)
  836. {
  837. stride = 1;
  838. }
  839. // we can optimize here in the case where stride == 1 and the list
  840. // consists of homogeneous types
  841. if (stride == 1)
  842. {
  843. bool homogeneous = true;
  844. int index;
  845. for (index = 1; index < Data.Length; index++)
  846. {
  847. if (!Data[0].GetType().Equals(Data[index].GetType()))
  848. {
  849. homogeneous = false;
  850. break;
  851. }
  852. }
  853. if (homogeneous)
  854. {
  855. Array.Sort(ret, new HomogeneousComparer());
  856. if (ascending == 0)
  857. {
  858. Array.Reverse(ret);
  859. }
  860. return new list(ret);
  861. }
  862. }
  863. // Because of the desired type specific feathered sorting behavior
  864. // requried by the spec, we MUST use a non-optimized bubble sort here.
  865. // Anything else will give you the incorrect behavior.
  866. // begin bubble sort...
  867. int i;
  868. int j;
  869. int k;
  870. int n = Data.Length;
  871. for (i = 0; i < (n-stride); i += stride)
  872. {
  873. for (j = i + stride; j < n; j += stride)
  874. {
  875. if (compare(ret[i], ret[j], ascending) > 0)
  876. {
  877. for (k = 0; k < stride; k++)
  878. {
  879. object tmp = ret[i + k];
  880. ret[i + k] = ret[j + k];
  881. ret[j + k] = tmp;
  882. }
  883. }
  884. }
  885. }
  886. // end bubble sort
  887. return new list(ret);
  888. }
  889. #region CSV Methods
  890. public static list FromCSV(string csv)
  891. {
  892. return new list(csv.Split(','));
  893. }
  894. public string ToCSV()
  895. {
  896. string ret = "";
  897. foreach (object o in this.Data)
  898. {
  899. if (ret == "")
  900. {
  901. ret = o.ToString();
  902. }
  903. else
  904. {
  905. ret = ret + ", " + o.ToString();
  906. }
  907. }
  908. return ret;
  909. }
  910. private string ToSoup()
  911. {
  912. string output;
  913. output = String.Empty;
  914. if (m_data.Length == 0)
  915. {
  916. return String.Empty;
  917. }
  918. foreach (object o in m_data)
  919. {
  920. output = output + o.ToString();
  921. }
  922. return output;
  923. }
  924. public static explicit operator String(list l)
  925. {
  926. return l.ToSoup();
  927. }
  928. public static explicit operator LSLString(list l)
  929. {
  930. return new LSLString(l.ToSoup());
  931. }
  932. public override string ToString()
  933. {
  934. return ToSoup();
  935. }
  936. #endregion
  937. #region Statistic Methods
  938. public double Min()
  939. {
  940. double minimum = double.PositiveInfinity;
  941. double entry;
  942. for (int i = 0; i < Data.Length; i++)
  943. {
  944. if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
  945. {
  946. if (entry < minimum) minimum = entry;
  947. }
  948. }
  949. return minimum;
  950. }
  951. public double Max()
  952. {
  953. double maximum = double.NegativeInfinity;
  954. double entry;
  955. for (int i = 0; i < Data.Length; i++)
  956. {
  957. if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
  958. {
  959. if (entry > maximum) maximum = entry;
  960. }
  961. }
  962. return maximum;
  963. }
  964. public double Range()
  965. {
  966. return (this.Max() / this.Min());
  967. }
  968. public int NumericLength()
  969. {
  970. int count = 0;
  971. double entry;
  972. for (int i = 0; i < Data.Length; i++)
  973. {
  974. if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
  975. {
  976. count++;
  977. }
  978. }
  979. return count;
  980. }
  981. public static list ToDoubleList(list src)
  982. {
  983. list ret = new list();
  984. double entry;
  985. for (int i = 0; i < src.Data.Length; i++)
  986. {
  987. if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
  988. {
  989. ret.Add(entry);
  990. }
  991. }
  992. return ret;
  993. }
  994. public double Sum()
  995. {
  996. double sum = 0;
  997. double entry;
  998. for (int i = 0; i < Data.Length; i++)
  999. {
  1000. if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
  1001. {
  1002. sum = sum + entry;
  1003. }
  1004. }
  1005. return sum;
  1006. }
  1007. public double SumSqrs()
  1008. {
  1009. double sum = 0;
  1010. double entry;
  1011. for (int i = 0; i < Data.Length; i++)
  1012. {
  1013. if (double.TryParse(Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
  1014. {
  1015. sum = sum + Math.Pow(entry, 2);
  1016. }
  1017. }
  1018. return sum;
  1019. }
  1020. public double Mean()
  1021. {
  1022. return (this.Sum() / this.NumericLength());
  1023. }
  1024. public void NumericSort()
  1025. {
  1026. IComparer Numeric = new NumericComparer();
  1027. Array.Sort(Data, Numeric);
  1028. }
  1029. public void AlphaSort()
  1030. {
  1031. IComparer Alpha = new AlphaCompare();
  1032. Array.Sort(Data, Alpha);
  1033. }
  1034. public double Median()
  1035. {
  1036. return Qi(0.5);
  1037. }
  1038. public double GeometricMean()
  1039. {
  1040. double ret = 1.0;
  1041. list nums = ToDoubleList(this);
  1042. for (int i = 0; i < nums.Data.Length; i++)
  1043. {
  1044. ret *= (double)nums.Data[i];
  1045. }
  1046. return Math.Exp(Math.Log(ret) / (double)nums.Data.Length);
  1047. }
  1048. public double HarmonicMean()
  1049. {
  1050. double ret = 0.0;
  1051. list nums = ToDoubleList(this);
  1052. for (int i = 0; i < nums.Data.Length; i++)
  1053. {
  1054. ret += 1.0 / (double)nums.Data[i];
  1055. }
  1056. return ((double)nums.Data.Length / ret);
  1057. }
  1058. public double Variance()
  1059. {
  1060. double s = 0;
  1061. list num = ToDoubleList(this);
  1062. for (int i = 0; i < num.Data.Length; i++)
  1063. {
  1064. s += Math.Pow((double)num.Data[i], 2);
  1065. }
  1066. return (s - num.Data.Length * Math.Pow(num.Mean(), 2)) / (num.Data.Length - 1);
  1067. }
  1068. public double StdDev()
  1069. {
  1070. return Math.Sqrt(this.Variance());
  1071. }
  1072. public double Qi(double i)
  1073. {
  1074. list j = this;
  1075. j.NumericSort();
  1076. if (Math.Ceiling(this.Length * i) == this.Length * i)
  1077. {
  1078. return (double)((double)j.Data[(int)(this.Length * i - 1)] + (double)j.Data[(int)(this.Length * i)]) / 2;
  1079. }
  1080. else
  1081. {
  1082. return (double)j.Data[((int)(Math.Ceiling(this.Length * i))) - 1];
  1083. }
  1084. }
  1085. #endregion
  1086. public string ToPrettyString()
  1087. {
  1088. string output;
  1089. if (m_data.Length == 0)
  1090. {
  1091. return "[]";
  1092. }
  1093. output = "[";
  1094. foreach (object o in m_data)
  1095. {
  1096. if (o is String)
  1097. {
  1098. output = output + "\"" + o + "\", ";
  1099. }
  1100. else
  1101. {
  1102. output = output + o.ToString() + ", ";
  1103. }
  1104. }
  1105. output = output.Substring(0, output.Length - 2);
  1106. output = output + "]";
  1107. return output;
  1108. }
  1109. public class AlphaCompare : IComparer
  1110. {
  1111. int IComparer.Compare(object x, object y)
  1112. {
  1113. return string.Compare(x.ToString(), y.ToString());
  1114. }
  1115. }
  1116. public class NumericComparer : IComparer
  1117. {
  1118. int IComparer.Compare(object x, object y)
  1119. {
  1120. double a;
  1121. double b;
  1122. if (!double.TryParse(x.ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out a))
  1123. {
  1124. a = 0.0;
  1125. }
  1126. if (!double.TryParse(y.ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out b))
  1127. {
  1128. b = 0.0;
  1129. }
  1130. if (a < b)
  1131. {
  1132. return -1;
  1133. }
  1134. else if (a == b)
  1135. {
  1136. return 0;
  1137. }
  1138. else
  1139. {
  1140. return 1;
  1141. }
  1142. }
  1143. }
  1144. public override bool Equals(object o)
  1145. {
  1146. if (!(o is list))
  1147. return false;
  1148. return Data.Length == ((list)o).Data.Length;
  1149. }
  1150. public override int GetHashCode()
  1151. {
  1152. return Data.GetHashCode();
  1153. }
  1154. }
  1155. //
  1156. // BELOW IS WORK IN PROGRESS... IT WILL CHANGE, SO DON'T USE YET! :)
  1157. //
  1158. public struct StringTest
  1159. {
  1160. // Our own little string
  1161. internal string actualString;
  1162. public static implicit operator bool(StringTest mString)
  1163. {
  1164. if (mString.actualString.Length == 0)
  1165. return true;
  1166. return false;
  1167. }
  1168. public override string ToString()
  1169. {
  1170. return actualString;
  1171. }
  1172. }
  1173. [Serializable]
  1174. public struct key
  1175. {
  1176. public string value;
  1177. #region Constructors
  1178. public key(string s)
  1179. {
  1180. value = s;
  1181. }
  1182. #endregion
  1183. #region Methods
  1184. static public bool Parse2Key(string s)
  1185. {
  1186. Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled);
  1187. if (isuuid.IsMatch(s))
  1188. {
  1189. return true;
  1190. }
  1191. else
  1192. {
  1193. return false;
  1194. }
  1195. }
  1196. #endregion
  1197. #region Operators
  1198. static public implicit operator Boolean(key k)
  1199. {
  1200. if (k.value.Length == 0)
  1201. {
  1202. return false;
  1203. }
  1204. if (k.value == "00000000-0000-0000-0000-000000000000")
  1205. {
  1206. return false;
  1207. }
  1208. Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled);
  1209. if (isuuid.IsMatch(k.value))
  1210. {
  1211. return true;
  1212. }
  1213. else
  1214. {
  1215. return false;
  1216. }
  1217. }
  1218. static public implicit operator key(string s)
  1219. {
  1220. return new key(s);
  1221. }
  1222. static public implicit operator String(key k)
  1223. {
  1224. return k.value;
  1225. }
  1226. static public implicit operator LSLString(key k)
  1227. {
  1228. return k.value;
  1229. }
  1230. public static bool operator ==(key k1, key k2)
  1231. {
  1232. return k1.value == k2.value;
  1233. }
  1234. public static bool operator !=(key k1, key k2)
  1235. {
  1236. return k1.value != k2.value;
  1237. }
  1238. #endregion
  1239. #region Overriders
  1240. public override bool Equals(object o)
  1241. {
  1242. return o.ToString() == value;
  1243. }
  1244. public override int GetHashCode()
  1245. {
  1246. return value.GetHashCode();
  1247. }
  1248. public override string ToString()
  1249. {
  1250. return value;
  1251. }
  1252. #endregion
  1253. }
  1254. [Serializable]
  1255. public struct LSLString
  1256. {
  1257. public string m_string;
  1258. #region Constructors
  1259. public LSLString(string s)
  1260. {
  1261. m_string = s;
  1262. }
  1263. public LSLString(double d)
  1264. {
  1265. string s = String.Format(Culture.FormatProvider, "{0:0.000000}", d);
  1266. m_string = s;
  1267. }
  1268. public LSLString(LSLFloat f)
  1269. {
  1270. string s = String.Format(Culture.FormatProvider, "{0:0.000000}", f.value);
  1271. m_string = s;
  1272. }
  1273. public LSLString(int i)
  1274. {
  1275. string s = String.Format("{0}", i);
  1276. m_string = s;
  1277. }
  1278. public LSLString(LSLInteger i) : this(i.value) {}
  1279. #endregion
  1280. #region Operators
  1281. static public implicit operator Boolean(LSLString s)
  1282. {
  1283. if (s.m_string.Length == 0)
  1284. {
  1285. return false;
  1286. }
  1287. else
  1288. {
  1289. return true;
  1290. }
  1291. }
  1292. static public implicit operator String(LSLString s)
  1293. {
  1294. return s.m_string;
  1295. }
  1296. static public implicit operator LSLString(string s)
  1297. {
  1298. return new LSLString(s);
  1299. }
  1300. public static string ToString(LSLString s)
  1301. {
  1302. return s.m_string;
  1303. }
  1304. public override string ToString()
  1305. {
  1306. return m_string;
  1307. }
  1308. public static bool operator ==(LSLString s1, string s2)
  1309. {
  1310. return s1.m_string == s2;
  1311. }
  1312. public static bool operator !=(LSLString s1, string s2)
  1313. {
  1314. return s1.m_string != s2;
  1315. }
  1316. public static LSLString operator +(LSLString s1, LSLString s2)
  1317. {
  1318. return new LSLString(s1.m_string + s2.m_string);
  1319. }
  1320. public static explicit operator double(LSLString s)
  1321. {
  1322. return new LSLFloat(s).value;
  1323. }
  1324. public static explicit operator LSLInteger(LSLString s)
  1325. {
  1326. return new LSLInteger(s.m_string);
  1327. }
  1328. public static explicit operator LSLString(double d)

Large files files are truncated, but you can click here to view the full file