PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/src/ServiceStack.Text/StringExtensions.cs

https://github.com/ioninteractive/ServiceStack.Text
C# | 959 lines | 773 code | 162 blank | 24 comment | 168 complexity | ea7836b2db682adc8907d6fc7abacae2 MD5 | raw file
  1. //
  2. // https://github.com/ServiceStack/ServiceStack.Text
  3. // ServiceStack.Text: .NET C# POCO JSON, JSV and CSV Text Serializers.
  4. //
  5. // Authors:
  6. // Demis Bellot (demis.bellot@gmail.com)
  7. //
  8. // Copyright 2012 Service Stack LLC. All Rights Reserved.
  9. //
  10. // Licensed under the same terms of ServiceStack.
  11. //
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Globalization;
  15. using System.IO;
  16. using System.Linq;
  17. using System.Text;
  18. using System.Text.RegularExpressions;
  19. using ServiceStack.Text;
  20. using ServiceStack.Text.Common;
  21. using ServiceStack.Text.Support;
  22. namespace ServiceStack
  23. {
  24. public static class StringExtensions
  25. {
  26. public static T To<T>(this string value)
  27. {
  28. return TypeSerializer.DeserializeFromString<T>(value);
  29. }
  30. public static T To<T>(this string value, T defaultValue)
  31. {
  32. return String.IsNullOrEmpty(value) ? defaultValue : TypeSerializer.DeserializeFromString<T>(value);
  33. }
  34. public static T ToOrDefaultValue<T>(this string value)
  35. {
  36. return String.IsNullOrEmpty(value) ? default(T) : TypeSerializer.DeserializeFromString<T>(value);
  37. }
  38. public static object To(this string value, Type type)
  39. {
  40. return TypeSerializer.DeserializeFromString(value, type);
  41. }
  42. /// <summary>
  43. /// Converts from base: 0 - 62
  44. /// </summary>
  45. /// <param name="source">The source.</param>
  46. /// <param name="from">From.</param>
  47. /// <param name="to">To.</param>
  48. /// <returns></returns>
  49. public static string BaseConvert(this string source, int from, int to)
  50. {
  51. const string chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  52. var result = "";
  53. var length = source.Length;
  54. var number = new int[length];
  55. for (var i = 0; i < length; i++)
  56. {
  57. number[i] = chars.IndexOf(source[i]);
  58. }
  59. int newlen;
  60. do
  61. {
  62. var divide = 0;
  63. newlen = 0;
  64. for (var i = 0; i < length; i++)
  65. {
  66. divide = divide * @from + number[i];
  67. if (divide >= to)
  68. {
  69. number[newlen++] = divide / to;
  70. divide = divide % to;
  71. }
  72. else if (newlen > 0)
  73. {
  74. number[newlen++] = 0;
  75. }
  76. }
  77. length = newlen;
  78. result = chars[divide] + result;
  79. }
  80. while (newlen != 0);
  81. return result;
  82. }
  83. public static string EncodeXml(this string value)
  84. {
  85. return value.Replace("<", "&lt;").Replace(">", "&gt;").Replace("&", "&amp;");
  86. }
  87. public static string EncodeJson(this string value)
  88. {
  89. return String.Concat
  90. ("\"",
  91. value.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\r", "").Replace("\n", "\\n"),
  92. "\""
  93. );
  94. }
  95. public static string EncodeJsv(this string value)
  96. {
  97. if (JsState.QueryStringMode)
  98. {
  99. return UrlEncode(value);
  100. }
  101. return String.IsNullOrEmpty(value) || !JsWriter.HasAnyEscapeChars(value)
  102. ? value
  103. : String.Concat
  104. (
  105. JsWriter.QuoteString,
  106. value.Replace(JsWriter.QuoteString, TypeSerializer.DoubleQuoteString),
  107. JsWriter.QuoteString
  108. );
  109. }
  110. public static string DecodeJsv(this string value)
  111. {
  112. const int startingQuotePos = 1;
  113. const int endingQuotePos = 2;
  114. return String.IsNullOrEmpty(value) || value[0] != JsWriter.QuoteChar
  115. ? value
  116. : value.Substring(startingQuotePos, value.Length - endingQuotePos)
  117. .Replace(TypeSerializer.DoubleQuoteString, JsWriter.QuoteString);
  118. }
  119. public static string UrlEncode(this string text)
  120. {
  121. if (String.IsNullOrEmpty(text)) return text;
  122. var sb = new StringBuilder();
  123. foreach (var charCode in Encoding.UTF8.GetBytes(text))
  124. {
  125. if (
  126. charCode >= 65 && charCode <= 90 // A-Z
  127. || charCode >= 97 && charCode <= 122 // a-z
  128. || charCode >= 48 && charCode <= 57 // 0-9
  129. || charCode >= 44 && charCode <= 46 // ,-.
  130. )
  131. {
  132. sb.Append((char)charCode);
  133. }
  134. else if(charCode == 32)
  135. {
  136. sb.Append('+');
  137. }
  138. else
  139. {
  140. sb.Append('%' + charCode.ToString("x2"));
  141. }
  142. }
  143. return sb.ToString();
  144. }
  145. public static string UrlDecode(this string text)
  146. {
  147. if (String.IsNullOrEmpty(text)) return null;
  148. var bytes = new List<byte>();
  149. var textLength = text.Length;
  150. for (var i = 0; i < textLength; i++)
  151. {
  152. var c = text[i];
  153. if (c == '+')
  154. {
  155. bytes.Add(32);
  156. }
  157. else if (c == '%')
  158. {
  159. var hexNo = Convert.ToByte(text.Substring(i + 1, 2), 16);
  160. bytes.Add(hexNo);
  161. i += 2;
  162. }
  163. else
  164. {
  165. bytes.Add((byte)c);
  166. }
  167. }
  168. byte[] byteArray = bytes.ToArray();
  169. return Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
  170. }
  171. public static string HexUnescape(this string text, params char[] anyCharOf)
  172. {
  173. if (String.IsNullOrEmpty(text)) return null;
  174. if (anyCharOf == null || anyCharOf.Length == 0) return text;
  175. var sb = new StringBuilder();
  176. var textLength = text.Length;
  177. for (var i = 0; i < textLength; i++)
  178. {
  179. var c = text.Substring(i, 1);
  180. if (c == "%")
  181. {
  182. var hexNo = Convert.ToInt32(text.Substring(i + 1, 2), 16);
  183. sb.Append((char)hexNo);
  184. i += 2;
  185. }
  186. else
  187. {
  188. sb.Append(c);
  189. }
  190. }
  191. return sb.ToString();
  192. }
  193. public static string UrlFormat(this string url, params string[] urlComponents)
  194. {
  195. var encodedUrlComponents = new string[urlComponents.Length];
  196. for (var i = 0; i < urlComponents.Length; i++)
  197. {
  198. var x = urlComponents[i];
  199. encodedUrlComponents[i] = x.UrlEncode();
  200. }
  201. return String.Format(url, encodedUrlComponents);
  202. }
  203. public static string ToRot13(this string value)
  204. {
  205. var array = value.ToCharArray();
  206. for (var i = 0; i < array.Length; i++)
  207. {
  208. var number = (int)array[i];
  209. if (number >= 'a' && number <= 'z')
  210. number += (number > 'm') ? -13 : 13;
  211. else if (number >= 'A' && number <= 'Z')
  212. number += (number > 'M') ? -13 : 13;
  213. array[i] = (char)number;
  214. }
  215. return new string(array);
  216. }
  217. public static string WithTrailingSlash(this string path)
  218. {
  219. if (String.IsNullOrEmpty(path))
  220. throw new ArgumentNullException("path");
  221. if (path[path.Length - 1] != '/')
  222. {
  223. return path + "/";
  224. }
  225. return path;
  226. }
  227. public static string AppendPath(this string uri, params string[] uriComponents)
  228. {
  229. return AppendUrlPaths(uri, uriComponents);
  230. }
  231. public static string AppendUrlPaths(this string uri, params string[] uriComponents)
  232. {
  233. var sb = new StringBuilder(uri.WithTrailingSlash());
  234. var i = 0;
  235. foreach (var uriComponent in uriComponents)
  236. {
  237. if (i++ > 0) sb.Append('/');
  238. sb.Append(uriComponent.UrlEncode());
  239. }
  240. return sb.ToString();
  241. }
  242. public static string AppendUrlPathsRaw(this string uri, params string[] uriComponents)
  243. {
  244. var sb = new StringBuilder(uri.WithTrailingSlash());
  245. var i = 0;
  246. foreach (var uriComponent in uriComponents)
  247. {
  248. if (i++ > 0) sb.Append('/');
  249. sb.Append(uriComponent);
  250. }
  251. return sb.ToString();
  252. }
  253. public static string FromUtf8Bytes(this byte[] bytes)
  254. {
  255. return bytes == null ? null
  256. : Encoding.UTF8.GetString(bytes, 0, bytes.Length);
  257. }
  258. public static byte[] ToUtf8Bytes(this string value)
  259. {
  260. return Encoding.UTF8.GetBytes(value);
  261. }
  262. public static byte[] ToUtf8Bytes(this int intVal)
  263. {
  264. return FastToUtf8Bytes(intVal.ToString());
  265. }
  266. public static byte[] ToUtf8Bytes(this long longVal)
  267. {
  268. return FastToUtf8Bytes(longVal.ToString());
  269. }
  270. public static byte[] ToUtf8Bytes(this ulong ulongVal)
  271. {
  272. return FastToUtf8Bytes(ulongVal.ToString());
  273. }
  274. public static byte[] ToUtf8Bytes(this double doubleVal)
  275. {
  276. var doubleStr = doubleVal.ToString(CultureInfo.InvariantCulture.NumberFormat);
  277. if (doubleStr.IndexOf('E') != -1 || doubleStr.IndexOf('e') != -1)
  278. doubleStr = DoubleConverter.ToExactString(doubleVal);
  279. return FastToUtf8Bytes(doubleStr);
  280. }
  281. /// <summary>
  282. /// Skip the encoding process for 'safe strings'
  283. /// </summary>
  284. /// <param name="strVal"></param>
  285. /// <returns></returns>
  286. private static byte[] FastToUtf8Bytes(string strVal)
  287. {
  288. var bytes = new byte[strVal.Length];
  289. for (var i = 0; i < strVal.Length; i++)
  290. bytes[i] = (byte)strVal[i];
  291. return bytes;
  292. }
  293. public static string[] SplitOnFirst(this string strVal, char needle)
  294. {
  295. if (strVal == null) return new string[0];
  296. var pos = strVal.IndexOf(needle);
  297. return pos == -1
  298. ? new[] { strVal }
  299. : new[] { strVal.Substring(0, pos), strVal.Substring(pos + 1) };
  300. }
  301. public static string[] SplitOnFirst(this string strVal, string needle)
  302. {
  303. if (strVal == null) return new string[0];
  304. var pos = strVal.IndexOf(needle);
  305. return pos == -1
  306. ? new[] { strVal }
  307. : new[] { strVal.Substring(0, pos), strVal.Substring(pos + 1) };
  308. }
  309. public static string[] SplitOnLast(this string strVal, char needle)
  310. {
  311. if (strVal == null) return new string[0];
  312. var pos = strVal.LastIndexOf(needle);
  313. return pos == -1
  314. ? new[] { strVal }
  315. : new[] { strVal.Substring(0, pos), strVal.Substring(pos + 1) };
  316. }
  317. public static string[] SplitOnLast(this string strVal, string needle)
  318. {
  319. if (strVal == null) return new string[0];
  320. var pos = strVal.LastIndexOf(needle);
  321. return pos == -1
  322. ? new[] { strVal }
  323. : new[] { strVal.Substring(0, pos), strVal.Substring(pos + 1) };
  324. }
  325. public static string WithoutExtension(this string filePath)
  326. {
  327. if (String.IsNullOrEmpty(filePath)) return null;
  328. var extPos = filePath.LastIndexOf('.');
  329. if (extPos == -1) return filePath;
  330. var dirPos = filePath.LastIndexOfAny(DirSeps);
  331. return extPos > dirPos ? filePath.Substring(0, extPos) : filePath;
  332. }
  333. static readonly char[] DirSeps = new[] { '\\', '/' };
  334. public static string ParentDirectory(this string filePath)
  335. {
  336. if (String.IsNullOrEmpty(filePath)) return null;
  337. var dirSep = filePath.IndexOf(PclExport.Instance.DirSep) != -1
  338. ? PclExport.Instance.DirSep
  339. : filePath.IndexOf(PclExport.Instance.AltDirSep) != -1
  340. ? PclExport.Instance.AltDirSep
  341. : (char)0;
  342. return dirSep == 0 ? null : filePath.TrimEnd(dirSep).SplitOnLast(dirSep)[0];
  343. }
  344. public static string ToJsv<T>(this T obj)
  345. {
  346. return TypeSerializer.SerializeToString(obj);
  347. }
  348. public static T FromJsv<T>(this string jsv)
  349. {
  350. return TypeSerializer.DeserializeFromString<T>(jsv);
  351. }
  352. public static string ToJson<T>(this T obj)
  353. {
  354. return JsConfig.PreferInterfaces
  355. ? JsonSerializer.SerializeToString(obj, AssemblyUtils.MainInterface<T>())
  356. : JsonSerializer.SerializeToString(obj);
  357. }
  358. public static T FromJson<T>(this string json)
  359. {
  360. return JsonSerializer.DeserializeFromString<T>(json);
  361. }
  362. public static string ToCsv<T>(this T obj)
  363. {
  364. return CsvSerializer.SerializeToString(obj);
  365. }
  366. public static string FormatWith(this string text, params object[] args)
  367. {
  368. return String.Format(text, args);
  369. }
  370. public static string Fmt(this string text, params object[] args)
  371. {
  372. return String.Format(text, args);
  373. }
  374. public static bool StartsWithIgnoreCase(this string text, string startsWith)
  375. {
  376. return text != null
  377. && text.StartsWith(startsWith, PclExport.Instance.InvariantComparisonIgnoreCase);
  378. }
  379. public static bool EndsWithIgnoreCase(this string text, string endsWith)
  380. {
  381. return text != null
  382. && text.EndsWith(endsWith, PclExport.Instance.InvariantComparisonIgnoreCase);
  383. }
  384. public static string ReadAllText(this string filePath)
  385. {
  386. return PclExport.Instance.ReadAllText(filePath);
  387. }
  388. public static bool FileExists(this string filePath)
  389. {
  390. return PclExport.Instance.FileExists(filePath);
  391. }
  392. public static bool DirectoryExists(this string dirPath)
  393. {
  394. return PclExport.Instance.DirectoryExists(dirPath);
  395. }
  396. public static void CreateDirectory(this string dirPath)
  397. {
  398. PclExport.Instance.CreateDirectory(dirPath);
  399. }
  400. public static int IndexOfAny(this string text, params string[] needles)
  401. {
  402. return IndexOfAny(text, 0, needles);
  403. }
  404. public static int IndexOfAny(this string text, int startIndex, params string[] needles)
  405. {
  406. var firstPos = -1;
  407. if (text != null)
  408. {
  409. foreach (var needle in needles)
  410. {
  411. var pos = text.IndexOf(needle, startIndex);
  412. if ((pos >= 0) && (firstPos == -1 || pos < firstPos))
  413. firstPos = pos;
  414. }
  415. }
  416. return firstPos;
  417. }
  418. public static string ExtractContents(this string fromText, string startAfter, string endAt)
  419. {
  420. return ExtractContents(fromText, startAfter, startAfter, endAt);
  421. }
  422. public static string ExtractContents(this string fromText, string uniqueMarker, string startAfter, string endAt)
  423. {
  424. if (String.IsNullOrEmpty(uniqueMarker))
  425. throw new ArgumentNullException("uniqueMarker");
  426. if (String.IsNullOrEmpty(startAfter))
  427. throw new ArgumentNullException("startAfter");
  428. if (String.IsNullOrEmpty(endAt))
  429. throw new ArgumentNullException("endAt");
  430. if (String.IsNullOrEmpty(fromText)) return null;
  431. var markerPos = fromText.IndexOf(uniqueMarker);
  432. if (markerPos == -1) return null;
  433. var startPos = fromText.IndexOf(startAfter, markerPos);
  434. if (startPos == -1) return null;
  435. startPos += startAfter.Length;
  436. var endPos = fromText.IndexOf(endAt, startPos);
  437. if (endPos == -1) endPos = fromText.Length;
  438. return fromText.Substring(startPos, endPos - startPos);
  439. }
  440. static readonly Regex StripHtmlRegEx = new Regex(@"<(.|\n)*?>", PclExport.Instance.RegexOptions);
  441. public static string StripHtml(this string html)
  442. {
  443. return String.IsNullOrEmpty(html) ? null : StripHtmlRegEx.Replace(html, "");
  444. }
  445. static readonly Regex StripBracketsRegEx = new Regex(@"\[(.|\n)*?\]", PclExport.Instance.RegexOptions);
  446. static readonly Regex StripBracesRegEx = new Regex(@"\((.|\n)*?\)", PclExport.Instance.RegexOptions);
  447. public static string StripMarkdownMarkup(this string markdown)
  448. {
  449. if (String.IsNullOrEmpty(markdown)) return null;
  450. markdown = StripBracketsRegEx.Replace(markdown, "");
  451. markdown = StripBracesRegEx.Replace(markdown, "");
  452. markdown = markdown
  453. .Replace("*", "")
  454. .Replace("!", "")
  455. .Replace("\r", "")
  456. .Replace("\n", "")
  457. .Replace("#", "");
  458. return markdown;
  459. }
  460. private const int LowerCaseOffset = 'a' - 'A';
  461. public static string ToCamelCase(this string value)
  462. {
  463. if (String.IsNullOrEmpty(value)) return value;
  464. var len = value.Length;
  465. var newValue = new char[len];
  466. var firstPart = true;
  467. for (var i = 0; i < len; ++i)
  468. {
  469. var c0 = value[i];
  470. var c1 = i < len - 1 ? value[i + 1] : 'A';
  471. var c0isUpper = c0 >= 'A' && c0 <= 'Z';
  472. var c1isUpper = c1 >= 'A' && c1 <= 'Z';
  473. if (firstPart && c0isUpper && (c1isUpper || i == 0))
  474. c0 = (char)(c0 + LowerCaseOffset);
  475. else
  476. firstPart = false;
  477. newValue[i] = c0;
  478. }
  479. return new string(newValue);
  480. }
  481. public static string ToTitleCase(this string value)
  482. {
  483. return PclExport.Instance.ToTitleCase(value);
  484. }
  485. public static string ToLowercaseUnderscore(this string value)
  486. {
  487. if (String.IsNullOrEmpty(value)) return value;
  488. value = value.ToCamelCase();
  489. var sb = new StringBuilder(value.Length);
  490. foreach (char t in value)
  491. {
  492. if (Char.IsDigit(t) || (Char.IsLetter(t) && Char.IsLower(t)) || t == '_')
  493. {
  494. sb.Append(t);
  495. }
  496. else
  497. {
  498. sb.Append("_");
  499. sb.Append(Char.ToLowerInvariant(t));
  500. }
  501. }
  502. return sb.ToString();
  503. }
  504. public static string SafeSubstring(this string value, int startIndex)
  505. {
  506. return SafeSubstring(value, startIndex, value.Length);
  507. }
  508. public static string SafeSubstring(this string value, int startIndex, int length)
  509. {
  510. if (String.IsNullOrEmpty(value)) return String.Empty;
  511. if (value.Length >= (startIndex + length))
  512. return value.Substring(startIndex, length);
  513. return value.Length > startIndex ? value.Substring(startIndex) : String.Empty;
  514. }
  515. public static bool IsAnonymousType(this Type type)
  516. {
  517. if (type == null)
  518. throw new ArgumentNullException("type");
  519. return PclExport.Instance.IsAnonymousType(type);
  520. }
  521. public static int CompareIgnoreCase(this string strA, string strB)
  522. {
  523. return String.Compare(strA, strB, PclExport.Instance.InvariantComparisonIgnoreCase);
  524. }
  525. public static bool EndsWithInvariant(this string str, string endsWith)
  526. {
  527. return str.EndsWith(endsWith, PclExport.Instance.InvariantComparison);
  528. }
  529. private static readonly Regex InvalidVarCharsRegex = new Regex(@"[^A-Za-z0-9]", PclExport.Instance.RegexOptions);
  530. private static readonly Regex SplitCamelCaseRegex = new Regex("([A-Z]|[0-9]+)", PclExport.Instance.RegexOptions);
  531. private static readonly Regex HttpRegex = new Regex(@"^http://",
  532. PclExport.Instance.RegexOptions | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
  533. public static T ToEnum<T>(this string value)
  534. {
  535. return (T)Enum.Parse(typeof(T), value, true);
  536. }
  537. public static T ToEnumOrDefault<T>(this string value, T defaultValue)
  538. {
  539. if (String.IsNullOrEmpty(value)) return defaultValue;
  540. return (T)Enum.Parse(typeof(T), value, true);
  541. }
  542. public static string SplitCamelCase(this string value)
  543. {
  544. return SplitCamelCaseRegex.Replace(value, " $1").TrimStart();
  545. }
  546. public static string ToInvariantUpper(this char value)
  547. {
  548. return PclExport.Instance.ToInvariantUpper(value);
  549. }
  550. public static string ToEnglish(this string camelCase)
  551. {
  552. var ucWords = camelCase.SplitCamelCase().ToLower();
  553. return ucWords[0].ToInvariantUpper() + ucWords.Substring(1);
  554. }
  555. public static string ToHttps(this string url)
  556. {
  557. if (url == null)
  558. {
  559. throw new ArgumentNullException("url");
  560. }
  561. return HttpRegex.Replace(url.Trim(), "https://");
  562. }
  563. public static bool IsEmpty(this string value)
  564. {
  565. return String.IsNullOrEmpty(value);
  566. }
  567. public static bool IsNullOrEmpty(this string value)
  568. {
  569. return String.IsNullOrEmpty(value);
  570. }
  571. public static bool EqualsIgnoreCase(this string value, string other)
  572. {
  573. return String.Equals(value, other, StringComparison.CurrentCultureIgnoreCase);
  574. }
  575. public static string ReplaceFirst(this string haystack, string needle, string replacement)
  576. {
  577. var pos = haystack.IndexOf(needle);
  578. if (pos < 0) return haystack;
  579. return haystack.Substring(0, pos) + replacement + haystack.Substring(pos + needle.Length);
  580. }
  581. public static string ReplaceAll(this string haystack, string needle, string replacement)
  582. {
  583. int pos;
  584. // Avoid a possible infinite loop
  585. if (needle == replacement) return haystack;
  586. while ((pos = haystack.IndexOf(needle)) > 0)
  587. {
  588. haystack = haystack.Substring(0, pos)
  589. + replacement
  590. + haystack.Substring(pos + needle.Length);
  591. }
  592. return haystack;
  593. }
  594. public static bool ContainsAny(this string text, params string[] testMatches)
  595. {
  596. foreach (var testMatch in testMatches)
  597. {
  598. if (text.Contains(testMatch)) return true;
  599. }
  600. return false;
  601. }
  602. public static string SafeVarName(this string text)
  603. {
  604. if (String.IsNullOrEmpty(text)) return null;
  605. return InvalidVarCharsRegex.Replace(text, "_");
  606. }
  607. public static string Join(this List<string> items)
  608. {
  609. return String.Join(JsWriter.ItemSeperatorString, items.ToArray());
  610. }
  611. public static string Join(this List<string> items, string delimeter)
  612. {
  613. return String.Join(delimeter, items.ToArray());
  614. }
  615. public static string ToParentPath(this string path)
  616. {
  617. var pos = path.LastIndexOf('/');
  618. if (pos == -1) return "/";
  619. var parentPath = path.Substring(0, pos);
  620. return parentPath;
  621. }
  622. public static string RemoveCharFlags(this string text, bool[] charFlags)
  623. {
  624. if (text == null) return null;
  625. var copy = text.ToCharArray();
  626. var nonWsPos = 0;
  627. for (var i = 0; i < text.Length; i++)
  628. {
  629. var @char = text[i];
  630. if (@char < charFlags.Length && charFlags[@char]) continue;
  631. copy[nonWsPos++] = @char;
  632. }
  633. return new String(copy, 0, nonWsPos);
  634. }
  635. public static string ToNullIfEmpty(this string text)
  636. {
  637. return String.IsNullOrEmpty(text) ? null : text;
  638. }
  639. private static char[] SystemTypeChars = new[] { '<', '>', '+' };
  640. public static bool IsUserType(this Type type)
  641. {
  642. return type.IsClass()
  643. && type.Namespace != null
  644. && !type.Namespace.StartsWith("System")
  645. && type.Name.IndexOfAny(SystemTypeChars) == -1;
  646. }
  647. public static bool IsInt(this string text)
  648. {
  649. if (String.IsNullOrEmpty(text)) return false;
  650. int ret;
  651. return Int32.TryParse(text, out ret);
  652. }
  653. public static int ToInt(this string text)
  654. {
  655. return text == null ? default(int) : Int32.Parse(text);
  656. }
  657. public static int ToInt(this string text, int defaultValue)
  658. {
  659. int ret;
  660. return Int32.TryParse(text, out ret) ? ret : defaultValue;
  661. }
  662. public static long ToInt64(this string text)
  663. {
  664. return Int64.Parse(text);
  665. }
  666. public static long ToInt64(this string text, long defaultValue)
  667. {
  668. long ret;
  669. return Int64.TryParse(text, out ret) ? ret : defaultValue;
  670. }
  671. public static float ToFloat(this string text)
  672. {
  673. return text == null ? default(float) : float.Parse(text);
  674. }
  675. public static float ToFloat(this string text, float defaultValue)
  676. {
  677. float ret;
  678. return float.TryParse(text, out ret) ? ret : defaultValue;
  679. }
  680. public static double ToDouble(this string text)
  681. {
  682. return text == null ? default(double) : double.Parse(text);
  683. }
  684. public static double ToDouble(this string text, double defaultValue)
  685. {
  686. double ret;
  687. return double.TryParse(text, out ret) ? ret : defaultValue;
  688. }
  689. public static decimal ToDecimal(this string text)
  690. {
  691. return text == null ? default(decimal) : decimal.Parse(text);
  692. }
  693. public static decimal ToDecimal(this string text, decimal defaultValue)
  694. {
  695. decimal ret;
  696. return decimal.TryParse(text, out ret) ? ret : defaultValue;
  697. }
  698. public static bool Glob(this string value, string pattern)
  699. {
  700. int pos;
  701. for (pos = 0; pattern.Length != pos; pos++)
  702. {
  703. switch (pattern[pos])
  704. {
  705. case '?':
  706. break;
  707. case '*':
  708. for (int i = value.Length; i >= pos; i--)
  709. {
  710. if (Glob(value.Substring(i), pattern.Substring(pos + 1)))
  711. return true;
  712. }
  713. return false;
  714. default:
  715. if (value.Length == pos || Char.ToUpper(pattern[pos]) != Char.ToUpper(value[pos]))
  716. {
  717. return false;
  718. }
  719. break;
  720. }
  721. }
  722. return value.Length == pos;
  723. }
  724. public static string TrimPrefixes(this string fromString, params string[] prefixes)
  725. {
  726. if (string.IsNullOrEmpty(fromString))
  727. return fromString;
  728. foreach (var prefix in prefixes)
  729. {
  730. if (fromString.StartsWith(prefix))
  731. return fromString.Substring(prefix.Length);
  732. }
  733. return fromString;
  734. }
  735. public static string FromAsciiBytes(this byte[] bytes)
  736. {
  737. return bytes == null ? null
  738. : PclExport.Instance.GetAsciiString(bytes);
  739. }
  740. public static byte[] ToAsciiBytes(this string value)
  741. {
  742. return PclExport.Instance.GetAsciiBytes(value);
  743. }
  744. public static Dictionary<string,string> ParseKeyValueText(this string text, string delimiter=":")
  745. {
  746. var to = new Dictionary<string, string>();
  747. if (text == null) return to;
  748. foreach (var parts in text.ReadLines().Select(line => line.SplitOnFirst(delimiter)))
  749. {
  750. var key = parts[0].Trim();
  751. if (key.Length == 0) continue;
  752. to[key] = parts.Length == 2 ? parts[1].Trim() : null;
  753. }
  754. return to;
  755. }
  756. public static IEnumerable<string> ReadLines(this string text)
  757. {
  758. string line;
  759. var reader = new StringReader(text ?? "");
  760. while ((line = reader.ReadLine()) != null)
  761. {
  762. yield return line;
  763. }
  764. }
  765. #if !XBOX
  766. public static string HexEscape(this string text, params char[] anyCharOf)
  767. {
  768. if (String.IsNullOrEmpty(text)) return text;
  769. if (anyCharOf == null || anyCharOf.Length == 0) return text;
  770. var encodeCharMap = new HashSet<char>(anyCharOf);
  771. var sb = new StringBuilder();
  772. var textLength = text.Length;
  773. for (var i = 0; i < textLength; i++)
  774. {
  775. var c = text[i];
  776. if (encodeCharMap.Contains(c))
  777. {
  778. sb.Append('%' + ((int)c).ToString("x"));
  779. }
  780. else
  781. {
  782. sb.Append(c);
  783. }
  784. }
  785. return sb.ToString();
  786. }
  787. public static string ToXml<T>(this T obj)
  788. {
  789. return XmlSerializer.SerializeToString(obj);
  790. }
  791. public static T FromXml<T>(this string json)
  792. {
  793. return XmlSerializer.DeserializeFromString<T>(json);
  794. }
  795. #endif
  796. }
  797. }