PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/corlib/System/String.cs

https://bitbucket.org/cosi2/dotnetanywhere-wb
C# | 676 lines | 519 code | 135 blank | 22 comment | 128 complexity | c311cffec731f522cd6dccaf3770c677 MD5 | raw file
  1. #if !LOCALTEST
  2. using System.Runtime.CompilerServices;
  3. using System.Text;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Globalization;
  7. namespace System {
  8. public class String : ICloneable, IEnumerable, IEnumerable<char>,
  9. IComparable, IComparable<string>, IEquatable<string> {
  10. public static readonly string Empty = "";
  11. public static bool IsNullOrEmpty(string value) {
  12. return (value == null) || (value.length == 0);
  13. }
  14. // This field must be the only field, to tie up with C code
  15. private int length;
  16. //public int Length{get{return length;}}
  17. [MethodImpl(MethodImplOptions.InternalCall)]
  18. extern public String(char c, int count);
  19. [MethodImpl(MethodImplOptions.InternalCall)]
  20. extern public String(char[] chars);
  21. [MethodImpl(MethodImplOptions.InternalCall)]
  22. extern public String(char[] chars, int startIndex, int length);
  23. #region Private Internal Calls
  24. [MethodImpl(MethodImplOptions.InternalCall)]
  25. extern private String(string str, int startIndex, int length);
  26. [MethodImpl(MethodImplOptions.InternalCall)]
  27. extern private static string InternalConcat(string str0, string str1);
  28. [MethodImpl(MethodImplOptions.InternalCall)]
  29. extern private string InternalReplace(string oldValue, string newValue);
  30. // trimType: bit 0 = start; bit 1 = end
  31. [MethodImpl(MethodImplOptions.InternalCall)]
  32. extern private string InternalTrim(char[] trimChars, int trimType);
  33. [MethodImpl(MethodImplOptions.InternalCall)]
  34. extern private int InternalIndexOf(char value, int startIndex, int count, bool forwards);
  35. [MethodImpl(MethodImplOptions.InternalCall)]
  36. extern private int InternalIndexOfAny(char[] anyOf, int startIndex, int count, bool forward);
  37. #endregion
  38. public int Length {
  39. get {
  40. return this.length;
  41. }
  42. }
  43. [IndexerName("Chars")]
  44. extern public char this[int index] {
  45. [MethodImpl(MethodImplOptions.InternalCall)]
  46. get;
  47. }
  48. #region Misc Methods
  49. public static string Join(string separator, string[] value) {
  50. return Join(separator, value, 0, value.Length);
  51. }
  52. //public override int GetHashCode(){
  53. // if(Length==0) return 0;
  54. // return (int)Chars[0] + 13*(int)Chars[Length-1];
  55. //}
  56. public static string Join(string separator, string[] value, int startIndex, int count) {
  57. StringBuilder sb = new StringBuilder();
  58. for (int i = startIndex; i < count; i++) {
  59. sb.Append(value[i]);
  60. sb.Append(separator);
  61. }
  62. return sb.ToString(0, sb.Length - separator.Length);
  63. }
  64. public string[] Split(params char[] separator) {
  65. return this.Split(separator, int.MaxValue);
  66. }
  67. public string[] Split(char[] separator, int count) {
  68. if (count < 0) {
  69. throw new ArgumentException("count");
  70. }
  71. if (count == 0) {
  72. return new string[0];
  73. }
  74. if (separator == null || separator.Length == 0) {
  75. separator = char.WhiteChars;
  76. }
  77. List<string> ret = new List<string>();
  78. int pos = 0;
  79. for (; count > 0; count--) {
  80. int sepPos = this.IndexOfAny(separator, pos);
  81. if (sepPos < 0) {
  82. ret.Add(new string(this, pos, this.length - pos));
  83. break;
  84. }
  85. ret.Add(new string(this, pos, sepPos - pos));
  86. pos = sepPos + 1;
  87. }
  88. return ret.ToArray();
  89. }
  90. public bool StartsWith(string str) {
  91. if(str.length > this.length) return false;
  92. return this.Substring(0, str.length) == str;
  93. }
  94. public bool EndsWith(string str) {
  95. if(str.length > this.length) return false;
  96. return this.Substring(this.length - str.length, str.length) == str;
  97. }
  98. #endregion
  99. #region Concat Methods
  100. public static string Concat(string str0, string str1) {
  101. if (str0 == null) {
  102. return str1 ?? string.Empty;
  103. }
  104. if (str1 == null) {
  105. return str0;
  106. }
  107. return InternalConcat(str0, str1);
  108. }
  109. public static string Concat(string str0, string str1, string str2) {
  110. return Concat(Concat(str0, str1), str2);
  111. }
  112. public static string Concat(string str0, string str1, string str2, string str3) {
  113. return Concat(Concat(str0, str1), Concat(str2, str3));
  114. }
  115. public static string Concat(params string[] values) {
  116. if (values == null) {
  117. throw new ArgumentNullException("args");
  118. }
  119. StringBuilder sb = new StringBuilder();
  120. for (int i = 0; i < values.Length; i++) {
  121. sb.Append(values[i]);
  122. }
  123. return sb.ToString();
  124. }
  125. public static string Concat(object obj0) {
  126. return obj0.ToString();
  127. }
  128. public static string Concat(object obj0, object obj1) {
  129. string str0 = (obj0 == null) ? null : obj0.ToString();
  130. string str1 = (obj1 == null) ? null : obj1.ToString();
  131. if (str0 == null) {
  132. return str1 ?? string.Empty;
  133. }
  134. if (str1 == null) {
  135. return str0;
  136. }
  137. return InternalConcat(str0, str1);
  138. }
  139. public static string Concat(object obj0, object obj1, object obj2) {
  140. return Concat(new object[] { obj0, obj1, obj2 });
  141. }
  142. public static string Concat(object obj0, object obj1, object obj2, object obj3) {
  143. return Concat(new object[] { obj0, obj1, obj2, obj3 });
  144. }
  145. public static string Concat(params object[] objs) {
  146. if (objs == null) {
  147. throw new ArgumentNullException("args");
  148. }
  149. StringBuilder sb = new StringBuilder();
  150. for (int i = 0; i < objs.Length; i++) {
  151. sb.Append(objs[i]);
  152. }
  153. return sb.ToString();
  154. }
  155. #endregion
  156. #region Trim Methods
  157. public string Trim(params char[] trimChars) {
  158. if (trimChars == null || trimChars.Length == 0) {
  159. trimChars = char.WhiteChars;
  160. }
  161. return InternalTrim(trimChars, 3);
  162. }
  163. public string Trim() {
  164. return InternalTrim(char.WhiteChars, 3);
  165. }
  166. public string TrimStart(params char[] trimChars) {
  167. if (trimChars == null || trimChars.Length == 0) {
  168. trimChars = char.WhiteChars;
  169. }
  170. return InternalTrim(trimChars, 1);
  171. }
  172. public string TrimEnd(params char[] trimChars) {
  173. if (trimChars == null || trimChars.Length == 0) {
  174. trimChars = char.WhiteChars;
  175. }
  176. return InternalTrim(trimChars, 2);
  177. }
  178. #endregion
  179. #region Substring Methods
  180. public string Substring(int startIndex) {
  181. if (startIndex < 0 || startIndex > this.length) {
  182. throw new ArgumentOutOfRangeException();
  183. }
  184. return new string(this, startIndex, this.length - startIndex);
  185. }
  186. public string Substring(int startIndex, int length) {
  187. if (startIndex < 0 || length < 0 || startIndex + length > this.length) {
  188. throw new ArgumentOutOfRangeException();
  189. }
  190. return new string(this, startIndex, length);
  191. }
  192. #endregion
  193. #region Format Methods
  194. public static string Format(string format, object obj0) {
  195. return Format(null, format, new object[] { obj0 });
  196. }
  197. public static string Format(string format, object obj0, object obj1) {
  198. return Format(null, format, new object[] { obj0, obj1 });
  199. }
  200. public static string Format(string format, object obj0, object obj1, object obj2) {
  201. return Format(null, format, new object[] { obj0, obj1, obj2 });
  202. }
  203. public static string Format(string format, params object[] args) {
  204. return Format(null, format, args);
  205. }
  206. public static string Format(IFormatProvider provider, string format, params object[] args) {
  207. StringBuilder sb = new StringBuilder();
  208. StringHelper.FormatHelper(sb, provider, format, args);
  209. return sb.ToString();
  210. }
  211. #endregion
  212. #region Replace & Remove Methods
  213. public string Replace(char oldChar, char newChar) {
  214. StringBuilder sb = new StringBuilder(this);
  215. return sb.Replace(oldChar, newChar).ToString();
  216. }
  217. public string Replace(string oldValue, string newValue) {
  218. if (oldValue == null) {
  219. throw new ArgumentNullException("oldValue");
  220. }
  221. if (oldValue.Length == 0) {
  222. throw new ArgumentException("oldValue is an empty string.");
  223. }
  224. if (this.length == 0) {
  225. return this;
  226. }
  227. if (newValue == null) {
  228. newValue = string.Empty;
  229. }
  230. return InternalReplace(oldValue, newValue);
  231. }
  232. public string Remove(int startIndex) {
  233. if (startIndex < 0 || startIndex >= this.length) {
  234. throw new ArgumentOutOfRangeException("startIndex");
  235. }
  236. return new string(this, 0, startIndex);
  237. }
  238. public string Remove(int startIndex, int count) {
  239. if (startIndex < 0 || count < 0 || startIndex + count >= this.length) {
  240. throw new ArgumentOutOfRangeException();
  241. }
  242. int pos2 = startIndex+count;
  243. return (new string(this, 0, startIndex)) + (new string(this, pos2, this.length - pos2));
  244. }
  245. #endregion
  246. #region Compare and CompareOrdinal Methods
  247. public static int Compare(string strA, string strB) {
  248. return CompareOrdinal(strA, strB);
  249. }
  250. public static int Compare(string strA, string strB, bool IgnoreCase) {
  251. if(IgnoreCase)
  252. {//HACK: Horribly inefficient.
  253. strA = strA.ToLower();
  254. strB = strB.ToLower();
  255. }
  256. return CompareOrdinal(strA, strB);
  257. }
  258. public static int Compare(string strA, string strB, StringComparison type) {
  259. return Compare(strA, 0, strB, 0, Math.Max(strA.Length,strB.Length), type);
  260. }
  261. public static int Compare(string strA, int indexA, string strB, int indexB, int length) {
  262. return CompareOrdinal(strA.Substring(indexA, length), strB.Substring(indexB, length));
  263. }
  264. public static int CompareOrdinal(string strA, string strB) {
  265. if (strA == null) {
  266. if (strB == null) {
  267. return 0;
  268. }
  269. return -1;
  270. }
  271. if (strB == null) {
  272. return 1;
  273. }
  274. int top = Math.Min(strA.Length, strB.Length);
  275. for (int i = 0; i < top; i++) {
  276. if (strA[i] != strB[i]) {
  277. return (strA[i] - strB[i]);
  278. }
  279. }
  280. return strA.Length - strB.Length;
  281. }
  282. public static int CompareOrdinal (String strA, int indexA, String strB, int indexB, int length)
  283. {
  284. if ((indexA > strA.Length) || (indexB > strB.Length) || (indexA < 0) || (indexB < 0) || (length < 0))
  285. throw new ArgumentOutOfRangeException ();
  286. return CompareOrdinalUnchecked (strA, indexA, length, strB, indexB, length);
  287. }
  288. public static int CompareOrdinalCaseInsensitive (String strA, int indexA, String strB, int indexB, int length)
  289. {
  290. //HACK:Horribly inefficient
  291. strA = strA.ToLower();
  292. strB = strB.ToLower();
  293. return CompareOrdinal (strA, indexA, strB, indexB, length);
  294. }
  295. public static int Compare (string strA, int indexA, string strB, int indexB, int length, StringComparison comparisonType)
  296. {
  297. switch (comparisonType) {
  298. case StringComparison.CurrentCulture:
  299. case StringComparison.InvariantCulture:
  300. case StringComparison.Ordinal:
  301. return CompareOrdinal (strA, indexA, strB, indexB, length);
  302. case StringComparison.CurrentCultureIgnoreCase:
  303. case StringComparison.InvariantCultureIgnoreCase:
  304. case StringComparison.OrdinalIgnoreCase:
  305. return CompareOrdinalCaseInsensitive (strA, indexA, strB, indexB, length);
  306. default:
  307. string msg = String.Format ("Invalid value '{0}' for StringComparison", comparisonType);
  308. throw new ArgumentException (msg, "comparisonType");
  309. }
  310. }
  311. internal static /*unsafe*/ int CompareOrdinalUnchecked (String strA, int indexA, int lenA, String strB, int indexB, int lenB)
  312. {
  313. if (strA == null) {
  314. if (strB == null)
  315. return 0;
  316. else
  317. return -1;
  318. } else if (strB == null) {
  319. return 1;
  320. }
  321. int lengthA = Math.Min (lenA, strA.Length - indexA);
  322. int lengthB = Math.Min (lenB, strB.Length - indexB);
  323. if (lengthA == lengthB && Object.ReferenceEquals (strA, strB))
  324. return 0;
  325. //fixed (char* aptr = strA, bptr = strB) {
  326. int ap = 0/*aptr*/ + indexA;
  327. int end = ap + Math.Min (lengthA, lengthB);
  328. int bp = 0/*bptr*/ + indexB;
  329. while (ap < end) {
  330. if (strA[ap] != strB[bp])
  331. return strA[ap] - strB[bp];
  332. ap++;
  333. bp++;
  334. }
  335. return lengthA - lengthB;
  336. //}
  337. }
  338. #endregion
  339. #region IndexOf... Methods
  340. public int IndexOf(string value) {
  341. return IndexOf(value, 0, this.length);
  342. }
  343. public int IndexOf(string value, int startIndex) {
  344. return IndexOf(value, startIndex, this.length - startIndex);
  345. }
  346. public int IndexOf(string value, int startIndex, int count) {
  347. if (value == null) {
  348. throw new ArgumentNullException("value");
  349. }
  350. if (startIndex < 0 || count < 0 || startIndex + count > this.length) {
  351. throw new ArgumentOutOfRangeException();
  352. }
  353. if (value.length == 0) {
  354. return startIndex;
  355. }
  356. int valueLen = value.length;
  357. int finalIndex = startIndex + count - valueLen + 1;
  358. char char0 = value[0];
  359. for (int i = startIndex; i < finalIndex; i++) {
  360. if (this[i] == char0) {
  361. bool ok = true;
  362. for (int j = 1; j < valueLen; j++) {
  363. if (this[i + j] != value[j]) {
  364. ok = false;
  365. break;
  366. }
  367. }
  368. if (ok) {
  369. return i;
  370. }
  371. }
  372. }
  373. return -1;
  374. }
  375. public int IndexOf(char value) {
  376. return this.IndexOf(value, 0, this.length, true);
  377. }
  378. public int IndexOf(char value, int startIndex) {
  379. return this.IndexOf(value, startIndex, this.length - startIndex, true);
  380. }
  381. public int IndexOf(char value, int startIndex, int count) {
  382. return this.IndexOf(value, startIndex, count, true);
  383. }
  384. public int LastIndexOf(char value) {
  385. return this.IndexOf(value, 0, this.length, false);
  386. }
  387. public int LastIndexOf(char value, int startIndex) {
  388. return this.IndexOf(value, startIndex, this.length - startIndex, false);
  389. }
  390. public int LastIndexOf(char value, int startIndex, int count) {
  391. return this.IndexOf(value, startIndex, count, false);
  392. }
  393. private int IndexOf(char value, int startIndex, int count, bool forwards) {
  394. if (startIndex < 0 || count < 0 || startIndex + count > this.length) {
  395. throw new ArgumentOutOfRangeException();
  396. }
  397. return this.InternalIndexOf(value, startIndex, count, forwards);
  398. }
  399. public int IndexOfAny(char[] anyOf) {
  400. return this.IndexOfAny(anyOf, 0, this.length, true);
  401. }
  402. public int IndexOfAny(char[] anyOf, int startIndex) {
  403. return this.IndexOfAny(anyOf, startIndex, this.length - startIndex, true);
  404. }
  405. public int IndexOfAny(char[] anyOf, int startIndex, int count) {
  406. return this.IndexOfAny(anyOf, startIndex, count, true);
  407. }
  408. public int LastIndexOfAny(char[] anyOf) {
  409. return this.IndexOfAny(anyOf, 0, this.length, false);
  410. }
  411. public int LastIndexOfAny(char[] anyOf, int startIndex) {
  412. return this.IndexOfAny(anyOf, startIndex, this.length - startIndex, false);
  413. }
  414. public int LastIndexOfAny(char[] anyOf, int startIndex, int count) {
  415. return this.IndexOfAny(anyOf, startIndex, count, false);
  416. }
  417. private int IndexOfAny(char[] anyOf, int startIndex, int count, bool forward) {
  418. if (startIndex < 0 || count < 0 || startIndex + count > this.length) {
  419. throw new ArgumentOutOfRangeException();
  420. }
  421. /*int anyOfLen = anyOf.Length;
  422. int finIndex = (forward) ? (startIndex + count) : (startIndex - 1);
  423. int inc = (forward) ? 1 : -1;
  424. for (int i = (forward) ? startIndex : (startIndex + count - 1); i != finIndex; i += inc) {
  425. char c = this[i];
  426. for (int j = 0; j < anyOfLen; j++) {
  427. if (c == anyOf[j]) {
  428. return i;
  429. }
  430. }
  431. }
  432. return -1;*/
  433. return this.InternalIndexOfAny(anyOf, startIndex, count, forward);
  434. }
  435. #endregion
  436. #region Case methods
  437. public string ToLower() {
  438. return ToLower(CultureInfo.CurrentCulture);
  439. }
  440. public string ToLower(CultureInfo culture) {
  441. if (culture == null) {
  442. throw new ArgumentNullException("culture");
  443. }
  444. if (culture.LCID == 0x007f) {
  445. return ToLowerInvariant();
  446. }
  447. return culture.TextInfo.ToLower(this);
  448. }
  449. public string ToLowerInvariant() {
  450. int len = this.length;
  451. StringBuilder sb = new StringBuilder(len);
  452. for (int i = 0; i < len; i++) {
  453. sb.Append(char.ToLowerInvariant(this[i]));
  454. }
  455. return sb.ToString();
  456. }
  457. public string ToUpper() {
  458. return ToLower(CultureInfo.CurrentCulture);
  459. }
  460. public string ToUpper(CultureInfo culture) {
  461. if (culture == null) {
  462. throw new ArgumentNullException("culture");
  463. }
  464. if (culture.LCID == 0x007f) {
  465. return ToUpperInvariant();
  466. }
  467. return culture.TextInfo.ToUpper(this);
  468. }
  469. public string ToUpperInvariant() {
  470. int len = this.length;
  471. StringBuilder sb = new StringBuilder(len);
  472. for (int i = 0; i < len; i++) {
  473. sb.Append(char.ToUpperInvariant(this[i]));
  474. }
  475. return sb.ToString();
  476. }
  477. #endregion
  478. #region Overrides and Operators
  479. public override string ToString() {
  480. return this;
  481. }
  482. public override bool Equals(object obj) {
  483. return Equals(this, obj as string);
  484. }
  485. public static bool operator ==(string a, string b) {
  486. return Equals(a, b);
  487. }
  488. public static bool operator !=(string a, string b) {
  489. return !Equals(a, b);
  490. }
  491. [MethodImpl(MethodImplOptions.InternalCall)]
  492. extern public static bool Equals(string a, string b);
  493. [MethodImpl(MethodImplOptions.InternalCall)]
  494. extern public override int GetHashCode();
  495. #endregion
  496. #region IClonable Members
  497. public object Clone() {
  498. return this;
  499. }
  500. #endregion
  501. #region IComparable Members
  502. public int CompareTo(object value) {
  503. if (value == null) {
  504. return 1;
  505. }
  506. if (!(value is string)) {
  507. throw new ArgumentException();
  508. }
  509. return string.Compare(this, (string)value);
  510. }
  511. public int CompareTo(string value) {
  512. if (value == null)
  513. return 1;
  514. return string.Compare(this, value);
  515. }
  516. #endregion
  517. #region IEquatable<string> Members
  518. public bool Equals(string other) {
  519. return Equals(this, other);
  520. }
  521. #endregion
  522. #region IEnumerable Members
  523. public IEnumerator GetEnumerator() {
  524. return new CharEnumerator(this);
  525. }
  526. IEnumerator<char> IEnumerable<char>.GetEnumerator() {
  527. return new CharEnumerator(this);
  528. }
  529. #endregion
  530. public char [] ToCharArray()
  531. {
  532. char[] chars = new char[Length];
  533. for(int i=0;i<Length;i++)
  534. {
  535. chars[i] = this[i];
  536. }
  537. return chars;
  538. }
  539. }
  540. }
  541. #endif