StringTools.hx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /*
  2. * Copyright (C)2005-2012 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. /**
  23. This class provides advanced methods on Strings. It is ideally used with
  24. 'using StringTools' and then acts as an extension to the String class.
  25. If the first argument to any of the methods is null, the result is
  26. unspecified.
  27. **/
  28. #if cs
  29. @:keep
  30. #end
  31. class StringTools {
  32. /**
  33. Encode an URL by using the standard format.
  34. **/
  35. public static function urlEncode( s : String ) : String untyped {
  36. #if flash9
  37. return __global__["encodeURIComponent"](s);
  38. #elseif flash
  39. return _global["escape"](s);
  40. #elseif neko
  41. return new String(_urlEncode(s.__s));
  42. #elseif js
  43. return encodeURIComponent(s);
  44. #elseif cpp
  45. return s.__URLEncode();
  46. #elseif java
  47. try
  48. return untyped __java__("java.net.URLEncoder.encode(s, \"UTF-8\")")
  49. catch (e:Dynamic) throw e;
  50. #elseif cs
  51. return untyped __cs__("System.Uri.EscapeUriString(s)");
  52. #else
  53. return null;
  54. #end
  55. }
  56. /**
  57. Decode an URL using the standard format.
  58. **/
  59. public static function urlDecode( s : String ) : String untyped {
  60. #if flash9
  61. return __global__["decodeURIComponent"](s.split("+").join(" "));
  62. #elseif flash
  63. return _global["unescape"](s);
  64. #elseif neko
  65. return new String(_urlDecode(s.__s));
  66. #elseif js
  67. return decodeURIComponent(s.split("+").join(" "));
  68. #elseif cpp
  69. return s.__URLDecode();
  70. #elseif java
  71. try
  72. return untyped __java__("java.net.URLDecoder.decode(s, \"UTF-8\")")
  73. catch (e:Dynamic) throw e;
  74. #elseif cs
  75. return untyped __cs__("System.Uri.UnescapeDataString(s)");
  76. #else
  77. return null;
  78. #end
  79. }
  80. /**
  81. Escapes HTML special characters of the string [s].
  82. The following replacements are made:
  83. - & becomes &
  84. - < becomes &lt;
  85. - > becomes &gt;
  86. If [quotes] is true, the following characters are also replaced:
  87. - " becomes &quot;
  88. - ' becomes &#039;
  89. **/
  90. public static function htmlEscape( s : String, ?quotes : Bool ) : String {
  91. s = s.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;");
  92. return quotes ? s.split('"').join("&quot;").split("'").join("&#039;") : s;
  93. }
  94. /**
  95. Unescapes HTML special characters of the string [s].
  96. This is the inverse operation to htmlEscape, i.e. the following always
  97. holds: htmlUnescape(htmlEscape(s)) == s
  98. The replacements follow:
  99. - &amp; becomes &
  100. - &lt; becomes <
  101. - &gt; becomes >
  102. - &quot; becomes "
  103. - &#039; becomes '
  104. **/
  105. public static function htmlUnescape( s : String ) : String {
  106. return s.split("&gt;").join(">").split("&lt;").join("<").split("&quot;").join('"').split("&#039;").join("'").split("&amp;").join("&");
  107. }
  108. /**
  109. Tells if the string [s] starts with the string [start].
  110. If [start] is null, the result is unspecified.
  111. If [start] is the empty String "", the result is true.
  112. **/
  113. public static #if (cs || java) inline #end function startsWith( s : String, start : String ) : Bool {
  114. #if java
  115. return untyped s.startsWith(start);
  116. #elseif cs
  117. return untyped s.StartsWith(start);
  118. #else
  119. return( s.length >= start.length && s.substr(0, start.length) == start );
  120. #end
  121. }
  122. /**
  123. Tells if the string [s] ends with the string [end].
  124. If [end] is null, the result is unspecified.
  125. If [end] is the empty String "", the result is true.
  126. **/
  127. public static #if (cs || java) inline #end function endsWith( s : String, end : String ) : Bool {
  128. #if java
  129. return untyped s.endsWith(end);
  130. #elseif cs
  131. return untyped s.EndsWith(end);
  132. #else
  133. var elen = end.length;
  134. var slen = s.length;
  135. return( slen >= elen && s.substr(slen - elen, elen) == end );
  136. #end
  137. }
  138. /**
  139. Tells if the character in the string [s] at position [pos] is a space.
  140. A character is considered to be a space character if its character code
  141. is 9,10,11,12,13 or 32.
  142. If [s] is the empty String "", or if pos is not a valid position within
  143. [s], the result is false.
  144. **/
  145. public static function isSpace( s : String, pos : Int ) : Bool {
  146. var c = s.charCodeAt( pos );
  147. return (c > 8 && c < 14) || c == 32;
  148. }
  149. /**
  150. Removes leading space characters of [s].
  151. This function internally calls isSpace() to decide which characters to
  152. remove.
  153. If [s] is the empty String "" or consists only of space characters, the
  154. result is the empty String "".
  155. **/
  156. public #if cs inline #end static function ltrim( s : String ) : String {
  157. #if cs
  158. return untyped s.TrimStart();
  159. #else
  160. var l = s.length;
  161. var r = 0;
  162. while( r < l && isSpace(s,r) ){
  163. r++;
  164. }
  165. if( r > 0 )
  166. return s.substr(r, l-r);
  167. else
  168. return s;
  169. #end
  170. }
  171. /**
  172. Removes trailing space characters of [s].
  173. This function internally calls isSpace() to decide which characters to
  174. remove.
  175. If [s] is the empty String "" or consists only of space characters, the
  176. result is the empty String "".
  177. **/
  178. public #if cs inline #end static function rtrim( s : String ) : String {
  179. #if cs
  180. return untyped s.TrimEnd();
  181. #else
  182. var l = s.length;
  183. var r = 0;
  184. while( r < l && isSpace(s,l-r-1) ){
  185. r++;
  186. }
  187. if( r > 0 ){
  188. return s.substr(0, l-r);
  189. }else{
  190. return s;
  191. }
  192. #end
  193. }
  194. /**
  195. Removes leading and trailing space characters of [s].
  196. This is a convenience function for ltrim(rtrim(s)).
  197. **/
  198. public #if (cs || java) inline #end static function trim( s : String ) : String {
  199. #if cs
  200. return untyped s.Trim();
  201. #elseif java
  202. return untyped s.trim();
  203. #else
  204. return ltrim(rtrim(s));
  205. #end
  206. }
  207. /**
  208. Concatenates [c] to [s] until [s].length is at least [l].
  209. If [c] is the empty String "" or if [l] does not exceed [s].length,
  210. [s] is returned unchanged.
  211. If [c].length is 1, the resulting String length is exactly [l].
  212. Otherwise the length may exceed [l].
  213. If [c] is null, the result is unspecified.
  214. **/
  215. public static function lpad( s : String, c : String, l : Int ) : String {
  216. if (c.length <= 0)
  217. return s;
  218. while (s.length < l) {
  219. s = c + s;
  220. }
  221. return s;
  222. }
  223. /**
  224. Appends [c] to [s] until [s].length is at least [l].
  225. If [c] is the empty String "" or if [l] does not exceed [s].length,
  226. [s] is returned unchanged.
  227. If [c].length is 1, the resulting String length is exactly [l].
  228. Otherwise the length may exceed [l].
  229. If [c] is null, the result is unspecified.
  230. **/
  231. public static function rpad( s : String, c : String, l : Int ) : String {
  232. if (c.length <= 0)
  233. return s;
  234. while (s.length < l) {
  235. s = s + c;
  236. }
  237. return s;
  238. }
  239. /**
  240. Replace all occurences of the String [sub] in the String [s] by the
  241. String [by].
  242. If [sub] is the empty String "", [by] is inserted after each character
  243. of [s]. If [by] is also the empty String "", [s] remains unchanged.
  244. This is a convenience function for [s].split([sub]).join([by]).
  245. If [sub] or [by] are null, the result is unspecified.
  246. **/
  247. public static function replace( s : String, sub : String, by : String ) : String {
  248. #if java
  249. if (sub.length == 0)
  250. return s.split(sub).join(by);
  251. else
  252. return untyped s.replace(sub, by);
  253. #elseif cs
  254. if (sub.length == 0)
  255. return s.split(sub).join(by);
  256. else
  257. return untyped s.Replace(sub, by);
  258. #else
  259. return s.split(sub).join(by);
  260. #end
  261. }
  262. /**
  263. Encodes [n] into a hexadecimal representation.
  264. If [digits] is specified, the resulting String is padded with "0" until
  265. its length equals [digits].
  266. **/
  267. public static function hex( n : Int, ?digits : Int ) {
  268. #if flash9
  269. var n : UInt = n;
  270. var s : String = untyped n.toString(16);
  271. s = s.toUpperCase();
  272. #else
  273. var s = "";
  274. var hexChars = "0123456789ABCDEF";
  275. do {
  276. s = hexChars.charAt(n&15) + s;
  277. n >>>= 4;
  278. } while( n > 0 );
  279. #end
  280. if( digits != null )
  281. while( s.length < digits )
  282. s = "0"+s;
  283. return s;
  284. }
  285. /**
  286. Returns the character code at position [index] of String [s].
  287. This method is faster than String.charCodeAt() on most platforms.
  288. However, unlike String.charCodeAt(), the result is unspecified if
  289. [index] is negative or exceeds [s].length.
  290. This operation is not guaranteed to work if [s] contains the \0
  291. character. The method isEof() can be used to check for that.
  292. **/
  293. public static inline function fastCodeAt( s : String, index : Int ) : Int untyped {
  294. #if neko
  295. return untyped __dollar__sget(s.__s, index);
  296. #elseif cpp
  297. return s.cca(index);
  298. #elseif flash9
  299. return s.cca(index);
  300. #elseif flash
  301. return s["cca"](index);
  302. #elseif java
  303. return ( index < s.length ) ? cast(_charAt(s, index), Int) : -1;
  304. #elseif cs
  305. return ( cast(index, UInt) < s.length ) ? cast(untyped s[index], Int) : -1;
  306. #elseif js
  307. #if mt
  308. return (untyped s).cca(index);
  309. #else
  310. return (untyped s).charCodeAt(index);
  311. #end
  312. #else
  313. return s.cca(index);
  314. #end
  315. }
  316. /*
  317. Tells if [c] represents the end-of-file (EOF) character.
  318. */
  319. @:noUsing public static inline function isEof( c : Int ) : Bool {
  320. #if (flash9 || cpp)
  321. return c == 0;
  322. #elseif flash8
  323. return c <= 0; // fast NaN
  324. #elseif js
  325. return c != c; // fast NaN
  326. #elseif neko
  327. return c == null;
  328. #elseif cs
  329. return c == -1;
  330. #elseif java
  331. return c == -1;
  332. #else
  333. return false;
  334. #end
  335. }
  336. #if java
  337. private static inline function _charAt(str:String, idx:Int):java.StdTypes.Char16 return untyped str._charAt(idx);
  338. #end
  339. #if neko
  340. private static var _urlEncode = neko.Lib.load("std","url_encode",1);
  341. private static var _urlDecode = neko.Lib.load("std","url_decode",1);
  342. #end
  343. }