TypeConverter.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. using System;
  2. using Jint.Native;
  3. using Jint.Native.Errors;
  4. using Jint.Native.Object;
  5. namespace Jint.Runtime
  6. {
  7. public class TypeConverter
  8. {
  9. /// <summary>
  10. /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.1
  11. /// </summary>
  12. /// <param name="input"></param>
  13. /// <param name="preferredType"></param>
  14. /// <returns></returns>
  15. public static object ToPrimitive(object input, TypeCode preferredType = TypeCode.Empty)
  16. {
  17. if (input == Null.Instance || input == Undefined.Instance)
  18. {
  19. return input;
  20. }
  21. if (input is IPrimitiveType)
  22. {
  23. return input;
  24. }
  25. var o = input as ObjectInstance;
  26. if (o == null)
  27. {
  28. throw new ArgumentException();
  29. }
  30. return o.DefaultValue(preferredType);
  31. }
  32. /// <summary>
  33. /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.2
  34. /// </summary>
  35. /// <param name="o"></param>
  36. /// <returns></returns>
  37. public static bool ToBoolean(object o)
  38. {
  39. if (o == Undefined.Instance || o == Null.Instance)
  40. {
  41. return false;
  42. }
  43. var p = o as IPrimitiveType;
  44. if (p != null)
  45. {
  46. o = p.PrimitiveValue;
  47. }
  48. if (o is bool)
  49. {
  50. return (bool) o;
  51. }
  52. if (o is double)
  53. {
  54. var n = (double) o;
  55. if (n == 0 || double.IsNaN(n))
  56. {
  57. return false;
  58. }
  59. else
  60. {
  61. return true;
  62. }
  63. }
  64. var s = o as string;
  65. if (s != null)
  66. {
  67. if (String.IsNullOrEmpty(s))
  68. {
  69. return false;
  70. }
  71. else
  72. {
  73. return true;
  74. }
  75. }
  76. return true;
  77. }
  78. /// <summary>
  79. /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.3
  80. /// </summary>
  81. /// <param name="o"></param>
  82. /// <returns></returns>
  83. public static double ToNumber(object o)
  84. {
  85. if (o == Undefined.Instance)
  86. {
  87. return double.NaN;
  88. }
  89. if (o == Null.Instance)
  90. {
  91. return 0;
  92. }
  93. if (o is bool)
  94. {
  95. return (bool)o ? 1 : 0;
  96. }
  97. if (o is double)
  98. {
  99. return (double)o;
  100. }
  101. var s = o as string;
  102. if (s != null)
  103. {
  104. return double.Parse(s);
  105. }
  106. return ToNumber(ToPrimitive(o, TypeCode.Double));
  107. }
  108. /// <summary>
  109. /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.4
  110. /// </summary>
  111. /// <param name="o"></param>
  112. /// <returns></returns>
  113. public static int ToInteger(object o)
  114. {
  115. var number = ToNumber(o);
  116. if (double.IsNaN(number))
  117. {
  118. return 0;
  119. }
  120. return (int) number;
  121. }
  122. /// <summary>
  123. /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.5
  124. /// </summary>
  125. /// <param name="o"></param>
  126. /// <returns></returns>
  127. public static int ToInt32(object o)
  128. {
  129. var n = ToNumber(o);
  130. if (double.IsNaN(n) || double.IsInfinity(n) || n == 0)
  131. {
  132. return 0;
  133. }
  134. return Convert.ToInt32(n);
  135. }
  136. /// <summary>
  137. /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.6
  138. /// </summary>
  139. /// <param name="o"></param>
  140. /// <returns></returns>
  141. public static uint ToUint32(object o)
  142. {
  143. var n = ToNumber(o);
  144. if (double.IsNaN(n) || double.IsInfinity(n) || n == 0)
  145. {
  146. return 0;
  147. }
  148. return Convert.ToUInt32(n);
  149. }
  150. /// <summary>
  151. /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.7
  152. /// </summary>
  153. /// <param name="o"></param>
  154. /// <returns></returns>
  155. public static ushort ToUint16(object o)
  156. {
  157. var n = ToNumber(o);
  158. if (double.IsNaN(n) || double.IsInfinity(n) || n == 0)
  159. {
  160. return 0;
  161. }
  162. return Convert.ToUInt16(n);
  163. }
  164. /// <summary>
  165. /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.8
  166. /// </summary>
  167. /// <param name="o"></param>
  168. /// <returns></returns>
  169. public static string ToString(object o)
  170. {
  171. if (o == Undefined.Instance)
  172. {
  173. return "undefined";
  174. }
  175. if (o == Null.Instance)
  176. {
  177. return "null";
  178. }
  179. var p = o as IPrimitiveType;
  180. if (p != null)
  181. {
  182. o = p;
  183. }
  184. if (o is bool)
  185. {
  186. return (bool) o ? "true" : "false";
  187. }
  188. if (o is double)
  189. {
  190. var n = (double) o;
  191. if (double.IsNaN(n))
  192. {
  193. return "NaN";
  194. }
  195. if (double.IsInfinity(n))
  196. {
  197. return "infinity";
  198. }
  199. return n.ToString();
  200. }
  201. var s = o as string;
  202. if (s != null)
  203. {
  204. return s;
  205. }
  206. return ToString(ToPrimitive(o, TypeCode.String));
  207. }
  208. public static ObjectInstance ToObject(Engine engine, object value)
  209. {
  210. var o = value as ObjectInstance;
  211. if (o != null)
  212. {
  213. return o;
  214. }
  215. if (value == Undefined.Instance)
  216. {
  217. throw new TypeError();
  218. }
  219. if (value == Null.Instance)
  220. {
  221. throw new TypeError();
  222. }
  223. if (value is bool)
  224. {
  225. return engine.Boolean.Construct((bool) value);
  226. }
  227. if (value is int)
  228. {
  229. return engine.Number.Construct((int) value);
  230. }
  231. if (value is uint)
  232. {
  233. return engine.Number.Construct((uint) value);
  234. }
  235. if (value is double)
  236. {
  237. return engine.Number.Construct((double) value);
  238. }
  239. var s = value as string;
  240. if (s != null)
  241. {
  242. return engine.String.Construct(s);
  243. }
  244. throw new TypeError();
  245. }
  246. public static TypeCode GetType(object value)
  247. {
  248. if (value == null || value == Undefined.Instance || value == Null.Instance)
  249. {
  250. return TypeCode.Empty;
  251. }
  252. if (value is string)
  253. {
  254. return TypeCode.String;
  255. }
  256. if (value is double || value is int || value is uint || value is ushort)
  257. {
  258. return TypeCode.Double;
  259. }
  260. if (value is bool)
  261. {
  262. return TypeCode.Boolean;
  263. }
  264. return TypeCode.Object;
  265. }
  266. }
  267. }