PageRenderTime 63ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/Utilities/Helpers/StringHelper.cs

#
C# | 2249 lines | 1460 code | 141 blank | 648 comment | 247 complexity | 1997209697b7ee7278fd993a99206ecd MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.IO;
  6. using System.Security.Cryptography;
  7. using System.Text;
  8. using System.Text.RegularExpressions;
  9. using System.Threading;
  10. using Delta.Utilities.Datatypes;
  11. using NUnit.Framework;
  12. namespace Delta.Utilities.Helpers
  13. {
  14. /// <summary>
  15. /// StringHelper: Provides additional or simplified string functions. This
  16. /// class does also offer a lot of powerful functions and allows complicated
  17. /// string operations. Easy functions at the beginning, harder ones later.
  18. /// </summary>
  19. public static class StringHelper
  20. {
  21. #region CutModes Enum
  22. /// <summary>
  23. /// Cut modes for MaxStringLength, cut at beginning of the string,
  24. /// at the end (default) or at both ends (for centered text maybe).
  25. /// </summary>
  26. public enum CutModes
  27. {
  28. /// <summary>
  29. /// Cut at beginning of text
  30. /// </summary>
  31. Begin,
  32. /// <summary>
  33. /// Cut at end of text
  34. /// </summary>
  35. End,
  36. /// <summary>
  37. /// Cut at both ends
  38. /// </summary>
  39. BothEnds,
  40. /// <summary>
  41. /// End string with ".." if we had to cut something off!
  42. /// Else the string is used normally.
  43. /// </summary>
  44. EndWithDots,
  45. }
  46. #endregion
  47. #region Constants
  48. /// <summary>
  49. /// New line, just "\r\n" (the default for Windows), used all over in
  50. /// StringHelper and always when multiline text is generated.
  51. /// </summary>
  52. public const string NewLine = "\r\n";
  53. #endregion
  54. #region Compare (Static)
  55. /// <summary>
  56. /// Helps to compare strings, uses case insensitive comparison.
  57. /// String.Compare is also ugly because we have always to check for == 0.
  58. /// </summary>
  59. /// <param name="stringToCheck">String to check</param>
  60. /// <param name="otherString">Other string to compare to</param>
  61. /// <returns>True if both strings are the same, ignoring the case</returns>
  62. public static bool Compare(this string stringToCheck, string otherString)
  63. {
  64. return String.Compare(stringToCheck, otherString,
  65. StringComparison.InvariantCultureIgnoreCase) == 0;
  66. }
  67. /// <summary>
  68. /// Is any of the names in searchNames the same as stringToCheck,
  69. /// will check case insensitive, for a normal case sensitive test
  70. /// use stringToCheck.Compare(searchName).
  71. /// </summary>
  72. /// <param name="stringToCheck">String to check</param>
  73. /// <param name="searchNames">Search names, can be a list or array</param>
  74. /// <returns>True if one of the searchNames was found</returns>
  75. public static bool Compare(this string stringToCheck,
  76. IEnumerable searchNames)
  77. {
  78. if (String.IsNullOrEmpty(stringToCheck))
  79. {
  80. return false;
  81. }
  82. foreach (string name in searchNames)
  83. {
  84. if (String.Compare(name, stringToCheck,
  85. StringComparison.InvariantCultureIgnoreCase) == 0)
  86. {
  87. return true;
  88. }
  89. }
  90. // Nothing found, no searchNames is contained in stringToCheck
  91. return false;
  92. }
  93. #endregion
  94. #region Split (Static)
  95. /// <summary>
  96. /// Split text with given separator and auto-trimming.
  97. /// </summary>
  98. /// <param name="text">Text</param>
  99. /// <param name="separator">Separator</param>
  100. /// <returns>Array of splitted strings, automatically trimmed</returns>
  101. public static string[] Split(this string text, string separator)
  102. {
  103. return Split(text, separator, true);
  104. }
  105. /// <summary>
  106. /// Split text with given separator and optional trimming.
  107. /// </summary>
  108. /// <param name="text">Text to split up</param>
  109. /// <param name="separator">Separator between splitted parts</param>
  110. /// <param name="trimSplittedParts">Trim splitted parts</param>
  111. /// <returns>Array of splitted strings</returns>
  112. public static string[] Split(this string text, string separator,
  113. bool trimSplittedParts)
  114. {
  115. // Validation
  116. if (String.IsNullOrEmpty(text))
  117. {
  118. return new string[0];
  119. }
  120. List<string> splittedParts = new List<string>();
  121. string[] rawSplittedParts = text.Split(new[]
  122. {
  123. separator
  124. },
  125. StringSplitOptions.None);
  126. for (int index = 0; index < rawSplittedParts.Length; index++)
  127. {
  128. string splitPart = rawSplittedParts[index];
  129. if (splitPart.Length > 0)
  130. {
  131. splittedParts.Add(trimSplittedParts
  132. ? splitPart.Trim()
  133. : splitPart);
  134. }
  135. }
  136. return splittedParts.ToArray();
  137. }
  138. #endregion
  139. #region IsNullOrWhiteSpace (Static)
  140. /// <summary>
  141. /// Checks if a string is 'null' or a contains of white space characters
  142. /// only.
  143. /// </summary>
  144. /// <param name="value"></param>
  145. /// <returns></returns>
  146. public static bool IsNullOrWhiteSpace(this string value)
  147. {
  148. return String.IsNullOrWhiteSpace(value);
  149. }
  150. #endregion
  151. #region SplitMultiLineText (Static)
  152. /// <summary>
  153. /// Splits a multi line string to several strings and returns the result as
  154. /// a string array.
  155. /// </summary>
  156. /// <param name="text">Text</param>
  157. /// <returns>the result as a string array</returns>
  158. public static string[] SplitMultiLineText(this string text)
  159. {
  160. // Validation
  161. if (IsNullOrWhiteSpace(text))
  162. {
  163. return new string[0];
  164. }
  165. // text.Split works only with \n strings, for \r\n, \n\r or any mixed
  166. // \r \n string we need special handling (its slow), try to avoid it.
  167. bool containsR = false;
  168. bool containsN = false;
  169. foreach (char ch in text)
  170. {
  171. if (ch == '\n')
  172. {
  173. containsN = true;
  174. if (containsR && containsN)
  175. {
  176. break;
  177. }
  178. }
  179. if (ch == '\r')
  180. {
  181. containsR = true;
  182. if (containsR && containsN)
  183. {
  184. break;
  185. }
  186. }
  187. }
  188. // No lines in this mofo? Then just return it!
  189. if (containsN == false &&
  190. containsR == false)
  191. {
  192. return new[]
  193. {
  194. text
  195. };
  196. }
  197. // First a quick check if this contains any \r chars
  198. else if (containsR == false)
  199. {
  200. // Just return the splitted by '\n' text
  201. return text.Split(new[]
  202. {
  203. '\n'
  204. });
  205. }
  206. else
  207. {
  208. List<string> ret = new List<string>();
  209. // Supports any format, only \r, only \n, normal \n\r,
  210. // crazy \r\n or even mixed \n\r with any format
  211. string[] splitted1 = text.Split(new[]
  212. {
  213. '\n'
  214. });
  215. string[] splitted2 = text.Split(new[]
  216. {
  217. '\r'
  218. });
  219. string[] splitted =
  220. splitted1.Length >= splitted2.Length
  221. ? splitted1
  222. : splitted2;
  223. foreach (string s in splitted)
  224. {
  225. // Never add any \r or \n to the single lines
  226. if (s.EndsWith("\r") ||
  227. s.EndsWith("\n"))
  228. {
  229. ret.Add(s.Substring(0, s.Length - 1));
  230. }
  231. else if (s.StartsWith("\n") ||
  232. s.StartsWith("\r"))
  233. {
  234. ret.Add(s.Substring(1));
  235. }
  236. else
  237. {
  238. ret.Add(s);
  239. }
  240. }
  241. return ret.ToArray();
  242. }
  243. }
  244. #endregion
  245. #region ForceTextIntoMultipleLines (Static)
  246. /// <summary>
  247. /// Just goes through the whole text and add new lines when reaching
  248. /// maxLineLength (will not keep lines below maxLineLength, but is good
  249. /// enough solution for now).
  250. /// </summary>
  251. /// <param name="inputText">Input text with any length</param>
  252. /// <param name="maxLineLength">Maximum line length after we should
  253. /// add newlines</param>
  254. /// <returns>Input text string with added new lines</returns>
  255. public static string ForceTextIntoMultipleLines(string inputText,
  256. int maxLineLength)
  257. {
  258. if (String.IsNullOrEmpty(inputText))
  259. {
  260. return "";
  261. }
  262. string ret = "";
  263. int currentLineLength = 0;
  264. char[] chars = inputText.ToCharArray();
  265. foreach (char letter in chars)
  266. {
  267. // Only split spaces!
  268. if (currentLineLength >= maxLineLength &&
  269. letter == ' ')
  270. {
  271. ret += "\n";
  272. currentLineLength = 0;
  273. }
  274. else
  275. {
  276. ret += letter;
  277. // If the text has already new lines, reset our line length counter!
  278. if (letter == '\n')
  279. {
  280. currentLineLength = 0;
  281. }
  282. else
  283. {
  284. currentLineLength++;
  285. }
  286. }
  287. }
  288. return ret;
  289. }
  290. #endregion
  291. #region IsNumericInt (Static)
  292. /// <summary>
  293. /// Check if string is numeric integer. A decimal point is not accepted.
  294. /// </summary>
  295. /// <param name="str">String to check</param>
  296. /// <returns>bool</returns>
  297. public static bool IsNumericInt(this string str)
  298. {
  299. // Can't be an int if string is not valid!
  300. if (String.IsNullOrEmpty(str))
  301. {
  302. return false;
  303. }
  304. // Go through every letter in str
  305. int strPos = 0;
  306. foreach (char ch in str)
  307. {
  308. // Only 0-9 are allowed
  309. if ("0123456789".IndexOf(ch) < 0 &&
  310. // Allow +/- for first char
  311. (strPos > 0 || (ch != '-' && ch != '+')))
  312. {
  313. return false;
  314. }
  315. strPos++;
  316. }
  317. // All fine, return true, this is a number!
  318. return true;
  319. }
  320. #endregion
  321. #region IsNumericFloat (Static)
  322. /// <summary>
  323. /// Is the given string a numeric float?
  324. /// </summary>
  325. /// <param name="str">Input string text to check</param>
  326. /// <returns>
  327. /// True if str is a numeric float (e.g. "0.0"), false otherwise.
  328. /// </returns>
  329. public static bool IsNumericFloat(this string str)
  330. {
  331. return IsNumericFloat(str, CultureInfo.InvariantCulture.NumberFormat);
  332. }
  333. /// <summary>
  334. /// Checks if string is numeric float value
  335. /// </summary>
  336. /// <param name="str">Input string text to check</param>
  337. /// <param name="numberFormat">Used number format, e.g.
  338. /// CultureInfo.InvariantCulture.NumberFormat</param>
  339. /// <returns>
  340. /// True if str can be converted to a float (e.g. "0.0"), false otherwise.
  341. /// </returns>
  342. public static bool IsNumericFloat(this string str,
  343. NumberFormatInfo numberFormat)
  344. {
  345. // Can't be a float if string is not valid!
  346. if (String.IsNullOrEmpty(str))
  347. {
  348. return false;
  349. }
  350. //not supported by Convert.ToSingle:
  351. //if (str.EndsWith("f"))
  352. // str = str.Substring(0, str.Length - 1);
  353. // Only 1 decimal point is allowed
  354. if (AllowOnlyOneDecimalPoint(str, numberFormat) == false)
  355. {
  356. return false;
  357. }
  358. // + allows in the first, last, don't allow in middle of the string
  359. // - allows in the first, last, don't allow in middle of the string
  360. // $ allows in the first, last, don't allow in middle of the string
  361. // , allows in the last, middle, don't allow in first char of the string
  362. // . allows in the first, last, middle, allows in all the indices
  363. // If string is just 1 letter, don't allow it to be a sign
  364. if (str.Length == 1 &&
  365. "+-$.,".IndexOf(str[0]) >= 0)
  366. {
  367. return false;
  368. }
  369. bool isFloat = false;
  370. for (int index = 0; index < str.Length; index++)
  371. {
  372. // For first index char
  373. char currentChar = char.Parse(str.Substring(index, 1));
  374. isFloat = false;
  375. if (str.IndexOf(currentChar) == 0)
  376. {
  377. isFloat = "+-$.0123456789".IndexOf(currentChar) >= 0;
  378. }
  379. // For middle characters
  380. if (isFloat == false &&
  381. str.IndexOf(currentChar) > 0 &&
  382. str.IndexOf(currentChar) < (str.Length - 1))
  383. {
  384. isFloat = ",.0123456789".IndexOf(currentChar) >= 0;
  385. }
  386. // For last characters
  387. if (isFloat == false &&
  388. str.IndexOf(currentChar) == (str.Length - 1))
  389. {
  390. isFloat = "+-$,.0123456789".IndexOf(currentChar) >= 0;
  391. }
  392. if (isFloat == false)
  393. {
  394. break;
  395. }
  396. }
  397. return isFloat;
  398. }
  399. #endregion
  400. #region AllowOnlyOneDecimalPoint (Static)
  401. /// <summary>
  402. /// Allow only one decimal point, used for IsNumericFloat.
  403. /// </summary>
  404. /// <param name="str">Input string to check</param>
  405. /// <param name="numberFormat">Used number format, e.g.
  406. /// CultureInfo.InvariantCulture.NumberFormat</param>
  407. /// <return>True if check succeeded, false otherwise</return>
  408. public static bool AllowOnlyOneDecimalPoint(string str,
  409. NumberFormatInfo numberFormat)
  410. {
  411. char[] strInChars = str.ToCharArray();
  412. bool hasGroupSeperator = false;
  413. int decimalSeperatorCount = 0;
  414. for (int i = 0; i < strInChars.Length; i++)
  415. {
  416. if (numberFormat.CurrencyDecimalSeparator.IndexOf(strInChars[i]) == 0)
  417. {
  418. decimalSeperatorCount++;
  419. }
  420. // has float group separators?
  421. if (numberFormat.CurrencyGroupSeparator.IndexOf(strInChars[i]) == 0)
  422. {
  423. hasGroupSeperator = true;
  424. }
  425. }
  426. if (hasGroupSeperator)
  427. {
  428. // If first digit is the group separator or begins with 0,
  429. // there is something wrong, the group separator is used as a comma.
  430. if (str.StartsWith(numberFormat.CurrencyGroupSeparator) ||
  431. strInChars[0] == '0')
  432. {
  433. return false;
  434. }
  435. // look only at the digits in front of the decimal point
  436. string[] splittedByDecimalSeperator = str.Split(
  437. numberFormat.CurrencyDecimalSeparator.ToCharArray());
  438. #region Invert the digits for modulo check
  439. // ==> 1.000 -> 000.1 ==> only after 3 digits
  440. char[] firstSplittedInChars = splittedByDecimalSeperator[0].ToCharArray();
  441. int arrayLength = firstSplittedInChars.Length;
  442. char[] firstSplittedInCharsInverted = new char[arrayLength];
  443. for (int i = 0; i < arrayLength; i++)
  444. {
  445. firstSplittedInCharsInverted[i] =
  446. firstSplittedInChars[arrayLength - 1 - i];
  447. }
  448. #endregion
  449. // group seperators are only allowed between 3 digits -> 1.000.000
  450. for (int i = 0; i < arrayLength; i++)
  451. {
  452. if (i % 3 != 0 &&
  453. numberFormat.CurrencyGroupSeparator.IndexOf(
  454. firstSplittedInCharsInverted[i]) == 0)
  455. {
  456. return false;
  457. }
  458. }
  459. }
  460. if (decimalSeperatorCount > 1)
  461. {
  462. return false;
  463. }
  464. return true;
  465. }
  466. #endregion
  467. #region GetLastWord (Static)
  468. /// <summary>
  469. /// Gets the last word of a text based on the given separator.
  470. /// </summary>
  471. /// <param name="text">Text</param>
  472. /// <param name="separator">Seperator</param>
  473. /// <returns>the last word of a text based on the given separator</returns>
  474. public static string GetLastWord(this string text, char separator)
  475. {
  476. // Validation check
  477. if (String.IsNullOrEmpty(text))
  478. {
  479. return "";
  480. }
  481. int seperatorIndex = text.LastIndexOf(separator);
  482. return (seperatorIndex != MathHelper.InvalidIndex)
  483. ? text.Substring(seperatorIndex + 1)
  484. : text;
  485. }
  486. #endregion
  487. #region GetClassName (Static)
  488. /// <summary>
  489. /// Get class name
  490. /// </summary>
  491. /// <param name="classType">Class type</param>
  492. /// <returns>class name</returns>
  493. public static string GetClassName(this Type classType)
  494. {
  495. //return "<" + GetLastWord(classType.ToString(), '.') + ">";
  496. //return "<" + classType.UnderlyingSystemType.Name + ">";
  497. return classType.UnderlyingSystemType.Name;
  498. }
  499. #endregion
  500. #region GetAllSpacesAndTabsAtBeginning (Static)
  501. /// <summary>
  502. /// Get all spaces and tabs at beginning
  503. /// </summary>
  504. /// <param name="text">Text</param>
  505. /// <returns>ret</returns>
  506. public static string GetAllSpacesAndTabsAtBeginning(this string text)
  507. {
  508. string ret = "";
  509. for (int pos = 0; pos < text.Length; pos++)
  510. {
  511. if (text[pos] == ' ' ||
  512. text[pos] == '\t')
  513. {
  514. ret += text[pos];
  515. }
  516. else
  517. {
  518. break;
  519. }
  520. }
  521. return ret;
  522. }
  523. #endregion
  524. #region GetInListContainsIndex (Static)
  525. /// <summary>
  526. /// Get Index of specific name in list. Case sensitive. Returns
  527. /// MathHelper.InvalidIndex if not found.
  528. /// </summary>
  529. /// <param name="name">Name</param>
  530. /// <param name="list">List</param>
  531. /// <param name="startIndex">
  532. /// Start index. Offset value to search from.</param>
  533. /// <returns>Index</returns>
  534. public static int GetInListContainsIndex(string name,
  535. string[] list, int startIndex)
  536. {
  537. if (startIndex >= list.Length)
  538. {
  539. return MathHelper.InvalidIndex;
  540. }
  541. for (int i = startIndex; i < list.Length; i++)
  542. {
  543. if (list[i].Contains(name))
  544. {
  545. return i;
  546. }
  547. }
  548. return MathHelper.InvalidIndex;
  549. }
  550. #endregion
  551. #region GetInListContainsSpecialIndex (Static)
  552. /// <summary>
  553. /// Get Index of specific name in list. Case sensitive. Returns
  554. /// MathHelper.InvalidIndex if not found.
  555. /// <para />
  556. /// Special Version: Ignores commented lines: "/*" ... "*/"; "//"
  557. /// <para />
  558. /// Ignores code in same line as a closing: "*/".
  559. /// </summary>
  560. /// <param name="name">Name</param>
  561. /// <param name="list">List</param>
  562. /// <param name="startIndex">
  563. /// Start index. Offset value to search from.</param>
  564. /// <returns>Int</returns>
  565. public static int GetInListContainsSpecialIndex(string name,
  566. string[] list, int startIndex)
  567. {
  568. if (startIndex >= list.Length)
  569. {
  570. return MathHelper.InvalidIndex;
  571. }
  572. // if in range of multi-line comments (/* ... */)
  573. bool ignoreLines = false;
  574. for (int i = startIndex; i < list.Length; i++)
  575. {
  576. string s = list[i];
  577. if (s.Contains("*/"))
  578. {
  579. ignoreLines = false;
  580. }
  581. else if (s.Contains("/*"))
  582. {
  583. // only ignoreLines if multi-Lines comment not out-commented
  584. ignoreLines = IsMultiBeginCommentValid(s);
  585. }
  586. else if (!ignoreLines &&
  587. s.Contains(name))
  588. {
  589. return i;
  590. }
  591. }
  592. return MathHelper.InvalidIndex;
  593. }
  594. #endregion
  595. #region IsMultiBeginCommentValid (Static)
  596. /// <summary>
  597. /// Returns if Multiline comment "/*" is not commented out,
  598. /// with "//".
  599. /// </summary>
  600. /// <param name="testString">Test string</param>
  601. /// <returns>True if this is a multiline comment, that is not commented
  602. /// out</returns>
  603. public static bool IsMultiBeginCommentValid(string testString)
  604. {
  605. int pos = testString.IndexOf("/*");
  606. int pos2 = testString.IndexOf("//");
  607. return (pos < pos2);
  608. }
  609. #endregion
  610. #region StartsWith (Static)
  611. /// <summary>
  612. /// Checks if a string starts with the given expression.
  613. /// </summary>
  614. /// <param name="stringToCheck">String to check</param>
  615. /// <param name="expression">Expression</param>
  616. /// <returns>True if the expression was found</returns>
  617. public static bool StartsWith(this string stringToCheck, string expression)
  618. {
  619. if (String.IsNullOrEmpty(stringToCheck))
  620. {
  621. return false;
  622. }
  623. return stringToCheck.ToLower().StartsWith(expression.ToLower());
  624. }
  625. /// <summary>
  626. /// Checks if a string starts with one of the strings in searchNames. This
  627. /// method will check case insensitive and is often used for file checks.
  628. /// </summary>
  629. /// <param name="stringToCheck">String to check</param>
  630. /// <param name="searchNames">Search names</param>
  631. /// <returns>True if one of the searchNames was found</returns>
  632. public static bool StartsWith(this string stringToCheck,
  633. string[] searchNames)
  634. {
  635. if (String.IsNullOrEmpty(stringToCheck))
  636. {
  637. return false;
  638. }
  639. string stringToCheckLower = stringToCheck.ToLower();
  640. foreach (string name in searchNames)
  641. {
  642. if (stringToCheckLower.StartsWith(name.ToLower()))
  643. {
  644. return true;
  645. }
  646. }
  647. // Nothing found, no searchNames is contained in stringToCheck
  648. return false;
  649. }
  650. #endregion
  651. #region EndsWith (Static)
  652. /// <summary>
  653. /// Checks if a string ends with the given expression.
  654. /// </summary>
  655. /// <param name="stringToCheck">String to check</param>
  656. /// <param name="expression">Expression</param>
  657. /// <returns>True if the expression was found</returns>
  658. public static bool EndsWith(this string stringToCheck, string expression)
  659. {
  660. if (String.IsNullOrEmpty(stringToCheck))
  661. {
  662. return false;
  663. }
  664. return stringToCheck.ToLower().EndsWith(expression.ToLower());
  665. }
  666. /// <summary>
  667. /// Checks if a string ends with one of the strings in searchNames. This
  668. /// method will check case insensitive and is often used for file checks.
  669. /// </summary>
  670. /// <param name="stringToCheck">String to check</param>
  671. /// <param name="searchNames">Search names</param>
  672. /// <returns>True if one of the searchNames was found</returns>
  673. public static bool EndsWith(this string stringToCheck,
  674. string[] searchNames)
  675. {
  676. if (String.IsNullOrEmpty(stringToCheck))
  677. {
  678. return false;
  679. }
  680. string stringToCheckLower = stringToCheck.ToLower();
  681. foreach (string name in searchNames)
  682. {
  683. if (stringToCheckLower.EndsWith(name.ToLower()))
  684. {
  685. return true;
  686. }
  687. }
  688. // Nothing found, no searchNames is contained in stringToCheck
  689. return false;
  690. }
  691. #endregion
  692. #region RemoveKeyWords (Static)
  693. /// <summary>
  694. /// Remove keywords from the stringToCheck. Useful to get rid of C#
  695. /// keywords like public, private, internal, etc. in source code lines.
  696. /// For example RemoveKeyWords("public static class Program",
  697. /// new string[] { "public", "private", "internal", "static" }) would
  698. /// return "class Program".
  699. /// </summary>
  700. /// <param name="stringToCheck">String to check</param>
  701. /// <param name="keywords">List of keywords to remove</param>
  702. /// <returns>Trimmed string without keywords</returns>
  703. public static string RemoveKeyWords(string stringToCheck,
  704. string[] keywords)
  705. {
  706. foreach (string keyword in keywords)
  707. {
  708. stringToCheck = stringToCheck.Replace(keyword, "");
  709. }
  710. return stringToCheck.Trim();
  711. }
  712. #endregion
  713. #region Contains (Static)
  714. /// <summary>
  715. /// Is searchName contained in stringToCheck, will check case insensitive,
  716. /// for a normal case sensitive test use stringToCheck.Contains(searchName)
  717. /// </summary>
  718. /// <param name="stringToCheck">String to check</param>
  719. /// <param name="searchName">Search name</param>
  720. /// <returns>True if stringToCheck contains searchName</returns>
  721. public static bool Contains(this string stringToCheck, string searchName)
  722. {
  723. if (String.IsNullOrEmpty(stringToCheck) ||
  724. String.IsNullOrEmpty(searchName))
  725. {
  726. return false;
  727. }
  728. return stringToCheck.ToLower().Contains(searchName.ToLower());
  729. }
  730. /// <summary>
  731. /// Is any of the names in searchNames contained in stringToCheck,
  732. /// will check case insensitive, for a normal case sensitive test
  733. /// use stringToCheck.Contains(searchName).
  734. /// </summary>
  735. /// <param name="stringToCheck">String to check</param>
  736. /// <param name="searchNames">Search names</param>
  737. /// <returns>True if one of the searchNames was found</returns>
  738. public static bool Contains(this string stringToCheck,
  739. string[] searchNames)
  740. {
  741. if (String.IsNullOrEmpty(stringToCheck))
  742. {
  743. return false;
  744. }
  745. string stringToCheckLower = stringToCheck.ToLower();
  746. foreach (string name in searchNames)
  747. {
  748. if (stringToCheckLower.Contains(name.ToLower()))
  749. {
  750. return true;
  751. }
  752. }
  753. // Nothing found, no searchNames is contained in stringToCheck
  754. return false;
  755. }
  756. /// <summary>
  757. /// Is any of the names in stringsToCheck contain searchName,
  758. /// will check case insensitive, for a normal case sensitive test
  759. /// use stringsToCheck.Contains(searchName).
  760. /// </summary>
  761. /// <param name="stringsToCheck">Array of strings to check</param>
  762. /// <param name="searchName">Search name</param>
  763. /// <returns>True if searchName was found</returns>
  764. public static bool Contains(List<string> stringsToCheck, string searchName)
  765. {
  766. if (stringsToCheck == null)
  767. {
  768. return false;
  769. }
  770. string searchNameLower = searchName.ToLower();
  771. foreach (string stringToCheck in stringsToCheck)
  772. {
  773. if (stringToCheck.ToLower().Contains(searchNameLower))
  774. {
  775. return true;
  776. }
  777. }
  778. // Nothing found, searchName is not contained in any stringsToCheck
  779. return false;
  780. }
  781. #endregion
  782. #region ToIntArray (Static)
  783. /// <summary>
  784. /// Convert string data to int array, string must be in the form
  785. /// "1, 3, 8, 7", etc. WriteArrayData is the complementary function.
  786. /// </summary>
  787. /// <param name="str">Input string</param>
  788. /// <returns>int array, will be null if string is invalid!</returns>
  789. public static int[] ToIntArray(this string str)
  790. {
  791. // Invalid?
  792. if (str == null ||
  793. str.Length == 0)
  794. {
  795. return null;
  796. }
  797. string[] splitted = str.Split(new[]
  798. {
  799. " ", ","
  800. },
  801. StringSplitOptions.RemoveEmptyEntries);
  802. List<int> ret = new List<int>();
  803. for (int i = 0; i < splitted.Length; i++)
  804. {
  805. int number;
  806. if (int.TryParse(splitted[i], out number))
  807. {
  808. ret.Add(number);
  809. }
  810. //try
  811. //{
  812. //ret.Add(Convert.ToInt32(splitted[i]));
  813. //} // try
  814. //catch { } // ignore
  815. }
  816. return ret.ToArray();
  817. }
  818. #endregion
  819. #region ToFloatArray (Static)
  820. /// <summary>
  821. /// Convert string data to float array, string must be in the form
  822. /// "1.5, 3.534, 8.76, 7.49", etc. WriteArrayData is the complementar
  823. /// function.
  824. /// </summary>
  825. /// <param name="s">s</param>
  826. /// <returns>float array, will be null if string is invalid!</returns>
  827. public static float[] ToFloatArray(this string s)
  828. {
  829. // Invalid?
  830. if (s == null ||
  831. s.Length == 0)
  832. {
  833. return null;
  834. }
  835. // Note: The input string must be well formed, else this won't work,
  836. // only 0-9, . and spaces are allowed!
  837. List<float> ret = new List<float>();
  838. float numberSoFar = 0.0f;
  839. // Decimal factor, goes to 10, 100, etc. and to 0.1, 0.01, etc.
  840. float decimalFactor = 1;
  841. bool afterPoint = false;
  842. bool negativeNumber = false;
  843. // Go through every letter
  844. for (int i = 0; i < s.Length; i++)
  845. {
  846. Char ch = s[i];
  847. // Is this a digit?
  848. if (ch >= '0' &&
  849. ch <= '9')
  850. {
  851. int digit = ch - '0';
  852. // Add either before or after decimal point
  853. if (afterPoint == false)
  854. {
  855. //Log.Write("before: numberSoFar=" + numberSoFar +
  856. // ", decimalFactor=" + decimalFactor);
  857. // Reverse engineering ^^
  858. numberSoFar = numberSoFar * decimalFactor + digit;
  859. decimalFactor = 10;
  860. //Log.Write("numberSoFar=" + numberSoFar +
  861. // ", decimalFactor=" + decimalFactor);
  862. }
  863. else
  864. {
  865. //Log.Write("digit before: numberSoFar=" + numberSoFar +
  866. // ", decimalFactor=" + decimalFactor);
  867. // Its a little bit easier for digits after the point
  868. numberSoFar += digit * decimalFactor;
  869. decimalFactor /= 10.0f;
  870. //Log.Write("digit: numberSoFar=" + numberSoFar +
  871. // ", decimalFactor=" + decimalFactor);
  872. }
  873. }
  874. else if (ch == '-')
  875. {
  876. negativeNumber = true;
  877. }
  878. else if (ch == '.')
  879. {
  880. decimalFactor = 0.1f;
  881. afterPoint = true;
  882. }
  883. else if (ch == ' ' ||
  884. ch == '\n')
  885. {
  886. // Flush
  887. if (negativeNumber)
  888. {
  889. numberSoFar = -numberSoFar;
  890. }
  891. ret.Add(numberSoFar);
  892. numberSoFar = 0;
  893. decimalFactor = 1;
  894. afterPoint = false;
  895. negativeNumber = false;
  896. }
  897. }
  898. // Add the last number we got
  899. if (negativeNumber)
  900. {
  901. numberSoFar = -numberSoFar;
  902. }
  903. ret.Add(numberSoFar);
  904. //Log.Write("s=" + s);
  905. //Log.Write("ret=" + ArrayHelper.Write(ret));
  906. return ret.ToArray();
  907. //*/
  908. }
  909. /// <summary>
  910. /// Convert string data to float array.
  911. /// <para />
  912. /// Note: The string numbers must be in the invariant number format.
  913. /// </summary>
  914. /// <param name="s">s</param>
  915. /// <returns>float array, will be null if string is invalid!</returns>
  916. public static float[] ToFloatArray(this string s, string separator = " ")
  917. {
  918. string[] textNumbers = Split(s, separator);
  919. float[] numbers = new float[textNumbers.Length];
  920. for (int index = 0; index < numbers.Length; index++)
  921. {
  922. numbers[index] = FromInvariantString(textNumbers[index], 0.0f);
  923. }
  924. return numbers;
  925. }
  926. #endregion
  927. #region ToInvariantString (Static)
  928. /// <summary>
  929. /// Write invariant string, which is helpful to write out floats, doubles
  930. /// or decimals in a invariant number format (not in german, spanish
  931. /// or whatever current language is running format, which can cause
  932. /// problems when importing the exported string number back).
  933. /// <para />
  934. /// Note: Not longer an extension method as it is annoying to type
  935. /// "To" for strings and intellisense brings this up first instead of
  936. /// the usual "ToString", which we almost always want instead.
  937. /// </summary>
  938. /// <param name="someObj">Some object, should be a number</param>
  939. /// <returns>Invariant string of the object</returns>
  940. public static string ToInvariantString(object someObj)
  941. {
  942. // No valid object given? Then don't return anything.
  943. if (someObj == null)
  944. {
  945. return "";
  946. }
  947. if (someObj is float)
  948. {
  949. return ((float)someObj).ToString(NumberFormatInfo.InvariantInfo);
  950. }
  951. if (someObj is double)
  952. {
  953. return ((double)someObj).ToString(NumberFormatInfo.InvariantInfo);
  954. }
  955. if (someObj is decimal)
  956. {
  957. return ((decimal)someObj).ToString(NumberFormatInfo.InvariantInfo);
  958. }
  959. // Dunno format, don't care (works fine for integers, enums, etc.)
  960. return someObj.ToString();
  961. }
  962. /// <summary>
  963. /// Extension to convert a float into an invariant string, which makes sure
  964. /// that the number format is always in the same for saving and parsing
  965. /// back to avoid problems because of the differences in the number format
  966. /// of the system languages.
  967. /// </summary>
  968. /// <param name="number">Any float number</param>
  969. /// <returns>Invariant string of the object</returns>
  970. public static string ToInvariantString(this float number)
  971. {
  972. return number.ToString(NumberFormatInfo.InvariantInfo);
  973. }
  974. /// <summary>
  975. /// Extension to convert a float into an invariant string, which makes sure
  976. /// that the number format is always in the same for saving and parsing
  977. /// back to avoid problems because of the differences in the number format
  978. /// of the system languages.
  979. /// </summary>
  980. /// <param name="number">Any float number</param>
  981. /// <param name="format">Custom format to use like "0.00"</param>
  982. /// <returns>Invariant string of the object</returns>
  983. public static string ToInvariantString(this float number, string format)
  984. {
  985. return number.ToString(format, NumberFormatInfo.InvariantInfo);
  986. }
  987. /// <summary>
  988. /// Extension to convert a double into an invariant string, which makes
  989. /// sure that the number format is always in the same for saving and
  990. /// parsing back to avoid problems because of the differences in the number
  991. /// format of the system languages.
  992. /// </summary>
  993. /// <param name="number">Any float number</param>
  994. /// <returns>Invariant string of the object</returns>
  995. public static string ToInvariantString(this double number)
  996. {
  997. return number.ToString(NumberFormatInfo.InvariantInfo);
  998. }
  999. /// <summary>
  1000. /// Extension to convert a decimal to an invariant string, which makes sure
  1001. /// that the number format is always in the same for saving and parsing
  1002. /// back to avoid problems because of the differences in the number format
  1003. /// of the system languages.
  1004. /// </summary>
  1005. /// <param name="number">Any float number</param>
  1006. /// <returns>Invariant string of the object</returns>
  1007. public static string ToInvariantString(this decimal number)
  1008. {
  1009. return number.ToString(NumberFormatInfo.InvariantInfo);
  1010. }
  1011. #endregion
  1012. #region FromInvariantString (Static)
  1013. /// <summary>
  1014. /// Converts string to type, for example: integer, boolean or other stuff.
  1015. /// </summary>
  1016. /// <typeparam name="T">Type to convert into</typeparam>
  1017. /// <param name="value">Input text containing value of T</param>
  1018. /// <param name="defaultValue">The default value</param>
  1019. /// <param name="extraWarningTextIfAnythingGoesWrong">A warning if anything
  1020. /// goes wrong</param>
  1021. /// <returns>Type or default value if failed</returns>
  1022. public static T FromInvariantString<T>(this string value, T defaultValue,
  1023. string extraWarningTextIfAnythingGoesWrong = "")
  1024. {
  1025. if (String.IsNullOrEmpty(value))
  1026. {
  1027. if (extraWarningTextIfAnythingGoesWrong != "")
  1028. {
  1029. Log.Warning(
  1030. "The value is invalid, using the defaultValue '" + defaultValue +
  1031. "' instead. " + extraWarningTextIfAnythingGoesWrong);
  1032. }
  1033. return defaultValue;
  1034. }
  1035. try
  1036. {
  1037. if (defaultValue is string)
  1038. {
  1039. // Note: It is already an string, but we can't cast it directly to T
  1040. return (T)(Convert.ToString(value) as object);
  1041. }
  1042. else if (defaultValue is int)
  1043. {
  1044. return (T)(Convert.ToInt32(value) as object);
  1045. }
  1046. else if (defaultValue is double)
  1047. {
  1048. return (T)(Convert.ToDouble(value,
  1049. CultureInfo.InvariantCulture) as object);
  1050. }
  1051. else if (defaultValue is float)
  1052. {
  1053. return (T)(Convert.ToSingle(value,
  1054. CultureInfo.InvariantCulture) as object);
  1055. }
  1056. else if (defaultValue is bool)
  1057. {
  1058. return (T)(Convert.ToBoolean(value) as object);
  1059. }
  1060. else if (defaultValue is char)
  1061. {
  1062. return (T)(Convert.ToChar(value) as object);
  1063. }
  1064. else if (defaultValue is DateTime)
  1065. {
  1066. return (T)(Convert.ToDateTime(value) as object);
  1067. }
  1068. else if (defaultValue is Color)
  1069. {
  1070. return (T)(Color.FromString(value) as object);
  1071. }
  1072. else if (defaultValue is Point)
  1073. {
  1074. return (T)(Point.FromString(value) as object);
  1075. }
  1076. else if (defaultValue is Size)
  1077. {
  1078. return (T)(Size.FromString(value) as object);
  1079. }
  1080. else if (defaultValue is Vector)
  1081. {
  1082. return (T)(Vector.FromString(value) as object);
  1083. }
  1084. else if (defaultValue is Matrix)
  1085. {
  1086. return (T)(Matrix.FromString(value) as object);
  1087. }
  1088. else if (defaultValue is Rectangle)
  1089. {
  1090. return (T)(Rectangle.FromCommaString(value) as object);
  1091. }
  1092. else if (defaultValue is Enum)
  1093. {
  1094. return EnumHelper.ToEnum<T>(value);
  1095. }
  1096. else if (defaultValue != null)
  1097. {
  1098. // Try it the .NET way (won't work on some platforms, only fallback)
  1099. // See http://predicatet.blogspot.com/2009/04/c-string-to-generic-type-conversion.html
  1100. return (T)Convert.ChangeType(value, typeof(T));
  1101. }
  1102. else
  1103. {
  1104. Log.Warning(
  1105. "Unsupported type " + defaultValue.GetType() + ", needs to be " +
  1106. "implemented first! " + extraWarningTextIfAnythingGoesWrong);
  1107. }
  1108. }
  1109. catch (Exception ex)
  1110. {
  1111. Log.Warning(
  1112. "The value '" + value + "' couldn't be converted to a " +
  1113. typeof(T) + ". " + extraWarningTextIfAnythingGoesWrong +
  1114. " Reason:\n" + ex);
  1115. }
  1116. return defaultValue;
  1117. }
  1118. #endregion
  1119. #region WriteIntoSpaceString (Static)
  1120. /// <summary>
  1121. /// Write into space string, useful for writing parameters without
  1122. /// knowing the length of each string, e.g. when writing numbers
  1123. /// (-1, 1.45, etc.). You can use this function to give all strings
  1124. /// the same width in a table. Maybe there is already a string function
  1125. /// for this, but I dont found any useful stuff.
  1126. /// </summary>
  1127. /// <param name="msg">Message to write</param>
  1128. /// <param name="spaces">Number of spaces to fill</param>
  1129. /// <returns>Same text as msg, but at least as long as spaces</returns>
  1130. public static string WriteIntoSpaceString(this string msg, int spaces)
  1131. {
  1132. // Msg is already that long or longer?
  1133. if (msg.Length >= spaces)
  1134. {
  1135. return msg;
  1136. }
  1137. // Create string with number of specified spaces
  1138. char[] ret = new char[spaces];
  1139. // Copy data
  1140. int i;
  1141. for (i = 0; i < msg.Length; i++)
  1142. {
  1143. ret[i] = msg[i];
  1144. }
  1145. // Fill rest with spaces
  1146. for (i = msg.Length; i < spaces; i++)
  1147. {
  1148. ret[i] = ' ';
  1149. }
  1150. // Return result
  1151. return new string(ret);
  1152. }
  1153. #endregion
  1154. #region WriteInternetTime (Static)
  1155. /// <summary>
  1156. /// Write internet time
  1157. /// </summary>
  1158. public static string WriteInternetTime(
  1159. this DateTime time, bool daylightSaving)
  1160. {
  1161. return "@" + (((int)(time.ToUniversalTime().AddHours(
  1162. daylightSaving
  1163. ? 1
  1164. : 0).TimeOfDay.
  1165. TotalSeconds * 100000 / (24 * 60 * 60))) / 100.0f).
  1166. ToInvariantString();
  1167. }
  1168. #endregion
  1169. #region WriteKbMbGbNumber (Static)
  1170. /// <summary>
  1171. /// Write bytes, KB, MB, GB, TB message.
  1172. /// 1 KB = 1024 Bytes
  1173. /// 1 MB = 1024 KB = 1048576 Bytes
  1174. /// 1 GB = 1024 MB = 1073741824 Bytes
  1175. /// 1 TB = 1024 GB = 1099511627776 Bytes
  1176. /// E.g. 100 will return "100 Bytes"
  1177. /// 2048 will return "2.00 KB"
  1178. /// 2500 will return "2.44 KB"
  1179. /// 1534905 will return "1.46 MB"
  1180. /// 23045904850904 will return "20.96 TB"
  1181. /// </summary>
  1182. /// <param name="decimalSeperator">Decimal Separator</param>
  1183. /// <param name="num">Number of bytes to write out</param>
  1184. /// <returns>
  1185. /// String with number of bytes in text form, e.g. "3.23 MB"
  1186. /// </returns>
  1187. public static string WriteKbMbGbNumber(long num,
  1188. string decimalSeperator)
  1189. {
  1190. if (num < 0)
  1191. {
  1192. return "-" + WriteKbMbGbNumber(-num);
  1193. }
  1194. if (num <= 999)
  1195. {
  1196. return num + " Bytes";
  1197. }
  1198. if (num <= 999 * 1024)
  1199. {
  1200. double fKB = num / 1024.0;
  1201. return (int)fKB + decimalSeperator +
  1202. ((int)(fKB * 100.0f) % 100).ToString("00") + " KB";
  1203. }
  1204. if (num <= 999 * 1024 * 1024)
  1205. {
  1206. double fMB = num / (1024.0 * 1024.0);
  1207. return (int)fMB + decimalSeperator +
  1208. ((int)(fMB * 100.0f) % 100).ToString("00") + " MB";
  1209. }
  1210. // this is very big ^^ will not fit into int
  1211. if (num <= 999L * 1024L * 1024L * 1024L)
  1212. {
  1213. double fGB = num / (1024.0 * 1024.0 * 1024.0);
  1214. return (int)fGB + decimalSeperator +
  1215. ((int)(fGB * 100.0f) % 100).ToString("00") + " GB";
  1216. }
  1217. //if ( num <= 999*1024*1024*1024*1024 )
  1218. //{
  1219. double fTB = num / (1024.0 * 1024.0 * 1024.0 * 1024.0);
  1220. return (int)fTB + decimalSeperator +
  1221. ((int)(fTB * 100.0f) % 100).ToString("00") + " TB";
  1222. //} // if
  1223. }
  1224. /// <summary>
  1225. /// Write bytes, KB, MB, GB, TB message.
  1226. /// 1 KB = 1024 Bytes
  1227. /// 1 MB = 1024 KB = 1048576 Bytes
  1228. /// 1 GB = 1024 MB = 1073741824 Bytes
  1229. /// 1 TB = 1024 GB = 1099511627776 Bytes
  1230. /// E.g. 100 will return "100 Bytes"
  1231. /// 2048 will return "2.00 KB"
  1232. /// 2500 will return "2.44 KB"
  1233. /// 1534905 will return "1.46 MB"
  1234. /// 23045904850904 will return "20.96 TB"
  1235. /// </summary>
  1236. /// <param name="num">Number of bytes to write out</param>
  1237. /// <returns>
  1238. /// String with number of bytes in text form, e.g. "3.23 MB"
  1239. /// </returns>
  1240. public static string WriteKbMbGbNumber(long num)
  1241. {
  1242. string decimalSeperator = CultureInfo.CurrentCulture.
  1243. NumberFormat.CurrencyDecimalSeparator;
  1244. return WriteKbMbGbNumber(num, decimalSeperator);
  1245. }
  1246. #endregion
  1247. #region Save (Static)
  1248. /// <summary>
  1249. /// Saves a string value to the given data stream writer. Since saving
  1250. /// null is not allowed, we always store a string (empty string in this
  1251. /// case). Loading the string can just be done with reader.ReadString().
  1252. /// </summary>
  1253. /// <param name="value">Value to save</param>
  1254. /// <param name="dataWriter">Data writer</param>
  1255. public static void Save(this string value, BinaryWriter dataWriter)
  1256. {
  1257. #region Validation
  1258. if (dataWriter == null)
  1259. {
  1260. // Without a valid writer stream where can store the value into we
  1261. // don't need to continue
  1262. Log.Warning("Unable to save string, writer is not valid!");
  1263. return;
  1264. }
  1265. #endregion
  1266. dataWriter.Write(value ?? "");
  1267. }
  1268. #endregion
  1269. #region BuildStringFromLines (Static)
  1270. /// <summary>
  1271. /// Build string from lines
  1272. /// </summary>
  1273. public static string BuildStringFromLines(
  1274. this string[] lines,
  1275. int startLine, int startOffset,
  1276. int endLine, int endOffset,
  1277. string separator)
  1278. {
  1279. // Check if all values are in range (correct if not)
  1280. if (startLine >= lines.Length)
  1281. {
  1282. startLine = lines.Length - 1;
  1283. }
  1284. if (endLine >= lines.Length)
  1285. {
  1286. endLine = lines.Length - 1;
  1287. }
  1288. if (startLine < 0)
  1289. {
  1290. startLine = 0;
  1291. }
  1292. if (endLine < 0)
  1293. {
  1294. endLine = 0;
  1295. }
  1296. if (startOffset >= lines[startLine].Length)
  1297. {
  1298. startOffset = lines[startLine].Length - 1;
  1299. }
  1300. if (endOffset >= lines[endLine].Length)
  1301. {
  1302. endOffset = lines[endLine].Length - 1;
  1303. }
  1304. if (startOffset < 0)
  1305. {
  1306. startOffset = 0;
  1307. }
  1308. if (endOffset < 0)
  1309. {
  1310. endOffset = 0;
  1311. }
  1312. StringBuilder builder = new StringBuilder((endLine - startLine) * 80);
  1313. for (int lineNumber = startLine; lineNumber <= endLine; lineNumber++)
  1314. {
  1315. if (lineNumber == startLine)
  1316. {
  1317. builder.Append(lines[lineNumber].Substring(startOffset));
  1318. }
  1319. else if (lineNumber == endLine)
  1320. {
  1321. builder.Append(lines[lineNumber].Substring(0, endOffset + 1));
  1322. }
  1323. else
  1324. {
  1325. builder.Append(lines[lineNumber]);
  1326. }
  1327. if (lineNumber != endLine)
  1328. {
  1329. builder.Append(separator);
  1330. }
  1331. }
  1332. return builder.ToString();
  1333. }
  1334. /// <summary>
  1335. /// Build string from lines
  1336. /// </summary>
  1337. /// <param name="lines">Input lines</param>
  1338. /// <param name="separator">
  1339. /// Separator between lines (by default NewLine).
  1340. /// </param>
  1341. /// <returns>
  1342. /// Long text string with all the lines in in separated with NewLines.
  1343. /// </returns>
  1344. public static string BuildStringFromLines(this string[] lines,
  1345. string separator = NewLine)
  1346. {
  1347. StringBuilder builder = new StringBuilder(lines.Length * 80);
  1348. for (int lineNumber = 0; lineNumber < lines.Length; lineNumber++)
  1349. {
  1350. builder.Append(lines[lineNumber]);
  1351. if (lineNumber != lines.Length - 1)
  1352. {
  1353. builder.Append(separator);
  1354. }
  1355. }
  1356. return builder.ToString();
  1357. }
  1358. /// <summary>
  1359. /// Build string from lines
  1360. /// </summary>
  1361. /// <param name="lines">Input lines, but only used partically</param>
  1362. /// <param name="startLine">Start line to start writing out</param>
  1363. /// <param name="endLine">End line to write</param>
  1364. /// <param name="separator">
  1365. /// Separator between lines (by default NewLine).
  1366. /// </param>
  1367. /// <returns>
  1368. /// Long text string with all the lines in in separated with NewLines.
  1369. /// </returns>
  1370. public static string BuildStringFromLines(this string[] lines,
  1371. int startLine, int endLine, string separator = NewLine)
  1372. {
  1373. // Check if all values are in range (correct if not)
  1374. if (startLine < 0)
  1375. {
  1376. startLine = 0;
  1377. }
  1378. if (endLine < 0)
  1379. {
  1380. endLine = 0;
  1381. }
  1382. if (startLine >= lines.Length)
  1383. {
  1384. startLine = lines.Length - 1;
  1385. }
  1386. if (endLine >= lines.Length)
  1387. {
  1388. endLine = lines.Length - 1;
  1389. }
  1390. StringBuilder builder = new StringBuilder((endLine - startLine) * 80);
  1391. for (int lineNumber = startLine; lineNumber <= endLine; lineNumber++)
  1392. {
  1393. builder.Append(lines[lineNumber]);
  1394. if (lineNumber != endLine)
  1395. {
  1396. builder.Append(separator);
  1397. }
  1398. }
  1399. return builder.ToString();
  1400. }
  1401. #endregion
  1402. #region SplitAndTrim (Static)
  1403. /// <summary>
  1404. /// Performs basically the same job as String.Split, but does
  1405. /// trim all parts, no empty parts are returned, e.g.
  1406. /// "hi there" (thats 2 spaces) returns "hi", "there",
  1407. /// String.Split would return "hi", "", "there".
  1408. /// Or another example: "Flak, Shootgun".Split(',') would return
  1409. /// "Flak" and " Shotgun", this function returns "Flak" and "Shotgun"
  1410. /// </summary>
  1411. /// <param name="text">Text</param>
  1412. /// <param name="separator">Seperator</param>
  1413. /// <returns>Array of strings</returns>
  1414. public static string[] SplitAndTrim(this string text, char separator)
  1415. {
  1416. List<string> ret = new List<string>();
  1417. string[] splitted = text.Split(new[]
  1418. {
  1419. separator
  1420. });
  1421. foreach (string s in splitted)
  1422. {
  1423. if (s.Length > 0)
  1424. {
  1425. ret.Add(s.Trim());
  1426. }
  1427. }
  1428. return ret.ToArray();
  1429. }
  1430. /// <summary>
  1431. /// Performs basically the same job as String.Split, but does
  1432. /// trim all parts, no empty parts are returned, e.g.
  1433. /// "hi there" (thats 2 spaces) returns "hi", "there",
  1434. /// String.Split would return "hi", "", "there".
  1435. /// Or another example: "Flak, Shootgun".Split(',') would return
  1436. /// "Flak" and " Shotgun", this function returns "Flak" and "Shotgun"
  1437. /// </summary>
  1438. /// <param name="text">Text</param>
  1439. /// <param name="separator">Separator</param>
  1440. /// <returns>Array of strings</returns>
  1441. public static string[] SplitAndTrim(this string text, string separator)
  1442. {
  1443. List<string> ret = new List<string>();
  1444. string[] splitted = text.Split(new[]
  1445. {
  1446. separator
  1447. },
  1448. StringSplitOptions.None);
  1449. foreach (string s in splitted)
  1450. {
  1451. if (s.Length > 0)
  1452. {
  1453. ret.Add(s.Trim());
  1454. }
  1455. }
  1456. return ret.ToArray();
  1457. }
  1458. /// <summary>
  1459. /// Performs basically the same job as String.Split, but does
  1460. /// trim all parts, no empty parts are returned, e.g.
  1461. /// "hi there" (thats 2 spaces) returns "hi", "there",
  1462. /// String.Split would return "hi", "", "there".
  1463. /// Or another example: "Flak, Shootgun".Split(',') would return
  1464. /// "Flak" and " Shotgun", this function returns "Flak" and "Shotgun"
  1465. /// </summary>
  1466. /// <param name="text">Text</param>
  1467. /// <param name="separators">Separators</param>
  1468. /// <returns>Array of strings</returns>
  1469. public static string[] SplitAndTrim(this string text, char[] separators)
  1470. {
  1471. if (String.IsNullOrEmpty(text))
  1472. {
  1473. return new string[0];
  1474. }
  1475. List<string> ret = new List<string>();
  1476. string[] splitted = text.Split(separators);
  1477. foreach (string s in splitted)
  1478. {
  1479. if (s.Trim().Length > 0)
  1480. {
  1481. ret.Add(s.Trim());
  1482. }
  1483. }
  1484. return ret.ToArray();
  1485. }
  1486. #endregion
  1487. #region IsMultiline (Static)
  1488. /// <summary>
  1489. /// Is text multiline checks if the string text has newline characters.
  1490. /// </summary>
  1491. /// <param name="text">Text to check.</param>
  1492. /// <returns>True if the text is multiline, otherwise False.</returns>
  1493. public static bool IsMultiline(this string text)
  1494. {
  1495. if (String.IsNullOrEmpty(text))
  1496. {
  1497. return false;
  1498. }
  1499. return text.Split(new[]
  1500. {
  1501. '\n', '\r'
  1502. }).Length > 1;
  1503. }
  1504. #endregion
  1505. #region HasMultipleWords (Static)
  1506. /// <summary>
  1507. /// Has multiple words checks if the string text, splitted at spaces,
  1508. /// tabs or new lines, contains multiple words.
  1509. /// </summary>
  1510. /// <param name="text">Text to check.</param>
  1511. /// <returns>True if the text has multiple words, otherwise False.</returns>
  1512. public static bool HasMultipleWords(this string text)
  1513. {
  1514. if (String.IsNullOrEmpty(text))
  1515. {
  1516. return false;
  1517. }
  1518. return text.Split(new[]
  1519. {
  1520. ' ', '\t', '\n'
  1521. }).Length > 1;
  1522. }
  1523. #endregion
  1524. #region SplitWords (Static)
  1525. /// <summary>
  1526. /// Split words, the line can contain characters like whitespaces,
  1527. /// newlines, spaces, commas, points or semicolons, everything is used
  1528. /// to split words. Only words with at least one other characters are
  1529. /// returned. Other delimiters characters: ~!@%^()-+=|\/{}[]:;"',?
  1530. /// and the following ones (can't display here): amp, star and brackets.
  1531. /// E.g. "He, she, it, yo man!" returns "He", "she", "it", "yo", "man".
  1532. /// </summary>
  1533. /// <param name="line">Line</param>
  1534. /// <returns>Array of strings containing the splitted and trimmed words,
  1535. /// can be an empty array if there were no words in the input text.
  1536. /// </returns>
  1537. public static string[] SplitWords(this string line)
  1538. {
  1539. string[] words = line.Split(new[]
  1540. {
  1541. ' ', '\t', '\n', '\r',
  1542. '~', '!', '@', '%', '^', '&', '*', '(', ')',
  1543. '-', '_', '+', '=', '|', '\\', '/', '{', '}', '[', ']', ':', ';',
  1544. '"', '\'', '<', '>', ',', '?'
  1545. },
  1546. StringSplitOptions.RemoveEmptyEntries);
  1547. List<string> ret = new List<string>();
  1548. foreach (string word in words)
  1549. {
  1550. string trimmedWord = word.Trim();
  1551. if (trimmedWord.Length > 0)
  1552. {
  1553. ret.Add(trimmedWord);
  1554. }
  1555. }
  1556. return ret.ToArray();
  1557. }
  1558. #endregion
  1559. #region LimitAllWordLengths (Static)
  1560. /// <summary>
  1561. /// Limit all word lengths
  1562. /// </summary>
  1563. /// <param name="textSnippet">Text snippet</param>
  1564. /// <param name="maxWordLength">Maximum word length</param>
  1565. /// <returns>String</returns>
  1566. public static string LimitAllWordLengths(this string textSnippet,
  1567. int maxWordLength)
  1568. {
  1569. string[] words = textSnippet.Split(new[]
  1570. {
  1571. ' ', ',', '<', '>'
  1572. });
  1573. foreach (string word in words)
  1574. {
  1575. if (word.Length > maxWordLength)
  1576. {
  1577. textSnippet =
  1578. textSnippet.Replace(word, word.Substring(0, maxWordLength));
  1579. }
  1580. }
  1581. return textSnippet;
  1582. }
  1583. #endregion
  1584. #region MaxStringLength (Static)
  1585. /// <summary>
  1586. /// Return the same string back, but reduce it if it is too long. Often
  1587. /// used for SQL databases table entries, which often only allow a certain
  1588. /// string length for data fields.
  1589. /// </summary>
  1590. /// <param name="originalString">Original string</param>
  1591. /// <param name="maxLength">Maximum length for the string</param>
  1592. /// <param name="cutMode">Cut mode</param>
  1593. /// <returns>
  1594. /// String with the maximum length of maxLength characters.
  1595. /// </returns>
  1596. public static string MaxStringLength(this string originalString,
  1597. int maxLength, CutModes cutMode)
  1598. {
  1599. if (String.IsNullOrEmpty(originalString))
  1600. {
  1601. return "";
  1602. }
  1603. if (originalString.Length <= maxLength)
  1604. {
  1605. return originalString;
  1606. }
  1607. if (cutMode == CutModes.Begin)
  1608. {
  1609. return originalString.Substring(
  1610. originalString.Length - maxLength, maxLength);
  1611. }
  1612. else if (cutMode == CutModes.End)
  1613. {
  1614. return originalString.Substring(0, maxLength);
  1615. }
  1616. else if (cutMode == CutModes.EndWithDots)
  1617. {
  1618. if (maxLength < 2)
  1619. {
  1620. maxLength = 2;
  1621. }
  1622. return originalString.Substring(0, maxLength - 2).TrimEnd() + "..";
  1623. }
  1624. else // logic: if ( cutMode == CutModes.BothEnds )
  1625. {
  1626. return originalString.Substring(
  1627. (originalString.Length - maxLength) / 2, maxLength);
  1628. }
  1629. }
  1630. #endregion
  1631. #region CreatePasswordString (Static)
  1632. /// <summary>
  1633. /// Create password string
  1634. /// </summary>
  1635. /// <param name="originalString">Original String</param>
  1636. /// <returns>Password string</returns>
  1637. public static string CreatePasswordString(this string originalString)
  1638. {
  1639. if (String.IsNullOrEmpty(originalString))
  1640. {
  1641. return "";
  1642. }
  1643. string passwordString = "";
  1644. for (int i = 0; i < originalString.Length; i++)
  1645. {
  1646. passwordString += "*";
  1647. }
  1648. return passwordString;
  1649. }
  1650. #endregion
  1651. #region SplitFunctionNameToWordString (Static)
  1652. /// <summary>
  1653. /// Splits a function name to words, was used for CR_Commenter in the past.
  1654. /// E.g. "MakeDamageOnUnit" gets "Make damage on unit".
  1655. /// Will also detect abbreviation like TCP and leave them
  1656. /// intact, e.g. "CreateTCPListener" gets "Create TCP listener".
  1657. /// </summary>
  1658. /// <param name="functionString">Function String</param>
  1659. /// <param name="upperLetterWords">Handle upper letter words</param>
  1660. public static string SplitFunctionNameToWordString(
  1661. this string functionString, bool upperLetterWords = false)
  1662. {
  1663. if (string.IsNullOrEmpty(functionString))
  1664. {
  1665. return "";
  1666. }
  1667. // Remove all underscores and dashes
  1668. functionString = functionString.Replace("_", " ");
  1669. functionString = functionString.Replace("-", " ");
  1670. string ret = "";
  1671. // Go through functionString and find big letters!
  1672. for (int pos = 0; pos < functionString.Length; pos++)
  1673. {
  1674. char letter = functionString[pos];
  1675. // First letter is always big!
  1676. if (pos == 0 ||
  1677. pos == 1 && functionString[1].IsUppercaseLetter() &&
  1678. functionString[0].IsUppercaseLetter() ||
  1679. pos == 2 && functionString[2].IsUppercaseLetter() &&
  1680. functionString[1].IsUppercaseLetter() &&
  1681. functionString[0].IsUppercaseLetter())
  1682. {
  1683. ret += letter.ToUpper();
  1684. }
  1685. // Found uppercase letter?
  1686. else if (
  1687. letter.IsUppercaseLetter() &&
  1688. //also support numbers and other symbols not lower/upper letter:
  1689. //StringHelper.IsLowercaseLetter(letter) == false &&
  1690. // But don't allow space or any punctuation (. , : ; ' " ! ?)
  1691. letter.IsSpaceOrPunctuation() == false &&
  1692. ret.EndsWith(" ") == false)
  1693. {
  1694. // Could be new word, but we have to check if its an abbreviation
  1695. int abbreviationLength = GetAbbreviationLengthInFunctionName(
  1696. functionString, pos);
  1697. // Found valid abbreviation?
  1698. if (abbreviationLength > 1)
  1699. {
  1700. // Then add it
  1701. ret += " " + functionString.Substring(pos, abbreviationLength);
  1702. // And advance pos (abbreviation is longer than 1 letter)
  1703. pos += abbreviationLength - 1;
  1704. }
  1705. // Else just add new word (in lower letter)
  1706. else
  1707. {
  1708. if (upperLetterWords)
  1709. {
  1710. // Stay upper letter (looks better on web page)
  1711. ret += " " + letter;
  1712. }
  1713. else
  1714. {
  1715. ret += " " + letter.ToLower();
  1716. }
  1717. }
  1718. }
  1719. else
  1720. {
  1721. // Just add letter
  1722. ret += letter;
  1723. }
  1724. }
  1725. return ret;
  1726. }
  1727. #endregion
  1728. #region GetLeftPartAtFirstOccurence (Static)
  1729. /// <summary>
  1730. /// Get left part of everything to the left of the first occurrence of a
  1731. /// character.
  1732. /// </summary>
  1733. /// <param name="ch">character</param>
  1734. /// <param name="sourceString">Source String</param>
  1735. /// <returns>String on the left side of ch</returns>
  1736. public static string GetLeftPartAtFirstOccurence(
  1737. this string sourceString, char ch)
  1738. {
  1739. int index = sourceString.IndexOf(ch);
  1740. if (index == -1)
  1741. {
  1742. return sourceString;
  1743. }
  1744. return sourceString.Substring(0, index);
  1745. }
  1746. #endregion
  1747. #region GetRightPartAtFirstOccurence (Static)
  1748. /// <summary>
  1749. /// Get right part of everything to the right of the first
  1750. /// occurrence of a character.
  1751. /// </summary>
  1752. /// <param name="ch">character</param>
  1753. /// <param name="sourceString">Source String</param>
  1754. /// <returns>String on the right of ch</returns>
  1755. public static string GetRightPartAtFirstOccurence(
  1756. this string sourceString, char ch)
  1757. {
  1758. int index = sourceString.IndexOf(ch);
  1759. if (index == -1)
  1760. {
  1761. return "";
  1762. }
  1763. return sourceString.Substring(index + 1);
  1764. }
  1765. #endregion
  1766. #region GetLeftPartAtLastOccurence (Static)
  1767. /// <summary>
  1768. /// Get left part of everything to the left of the last
  1769. /// occurrence of a character.
  1770. /// </summary>
  1771. /// <param name="ch">character</param>
  1772. /// <param name="sourceString">Source String</param>
  1773. /// <returns>String on the left side of ch</returns>
  1774. public static string GetLeftPartAtLastOccurence(
  1775. this string sourceString, char ch)
  1776. {
  1777. int index = sourceString.LastIndexOf(ch);
  1778. if (index == -1)
  1779. {
  1780. return sourceString;
  1781. }
  1782. return sourceString.Substring(0, index);
  1783. }
  1784. #endregion
  1785. #region GetRightPartAtLastOccurence (Static)
  1786. /// <summary>
  1787. /// Get right part of everything to the right of the last
  1788. /// occurrence of a character.
  1789. /// </summary>
  1790. /// <param name="ch">character</param>
  1791. /// <param name="sourceString">Source String</param>
  1792. /// <returns>String on the right side of ch</returns>
  1793. public static string GetRightPartAtLastOccurence(
  1794. this string sourceString, char ch)
  1795. {
  1796. int index = sourceString.LastIndexOf(ch);
  1797. if (index == -1)
  1798. {
  1799. return sourceString;
  1800. }
  1801. return sourceString.Substring(index + 1);
  1802. }
  1803. #endregion
  1804. #region SearchTextBetweenChars (Static)
  1805. /// <summary>
  1806. /// Search text between chars, e.g. "hello" returns "ell" if
  1807. /// firstChar is 'h' and lastChar is 'o'.
  1808. /// </summary>
  1809. /// <example>
  1810. /// "ell" == SearchTextBetweenChars("hello", 'h', 'o');
  1811. /// </example>
  1812. /// <param name="sourceString">source string</param>
  1813. /// <param name="firstChar">First char</param>
  1814. /// <param name="lastChar">Last char</param>
  1815. /// <returns>String</returns>
  1816. public static string SearchTextBetweenChars(
  1817. this string sourceString, char firstChar, char lastChar)
  1818. {
  1819. string ret = "";
  1820. int firstIndex = sourceString.IndexOf(firstChar);
  1821. if (firstIndex != -1)
  1822. {
  1823. firstIndex++;
  1824. int lastIndex = sourceString.IndexOf(lastChar, firstIndex);
  1825. if (lastIndex != -1)
  1826. {
  1827. ret = sourceString.Substring(firstIndex, lastIndex - firstIndex);
  1828. }
  1829. }
  1830. return ret;
  1831. }
  1832. #endregion
  1833. #region ToLower (Static)
  1834. /// <summary>
  1835. /// Helper function to convert letter to lowercase. Could someone
  1836. /// tell me the reason why there is no function for that in char?
  1837. /// </summary>
  1838. /// <param name="letter">Letter</param>
  1839. /// <returns>Letter in lower case</returns>
  1840. public static char ToLower(this char letter)
  1841. {
  1842. return letter.ToString().ToLower()[0];
  1843. }
  1844. #endregion
  1845. #region ToUpper (Static)
  1846. /// <summary>
  1847. /// Helper function to convert letter to uppercase. Could someone
  1848. /// tell me the reason why there is no function for that in char?
  1849. /// </summary>
  1850. /// <param name="letter">Letter</param>
  1851. /// <returns>Letter in upper case</returns>
  1852. public static char ToUpper(this char letter)
  1853. {
  1854. return letter.ToString().ToUpper()[0];
  1855. }
  1856. #endregion
  1857. #region IsLowercaseLetter (Static)
  1858. /// <summary>
  1859. /// Helper function to check if this is an lowercase letter.
  1860. /// </summary>
  1861. /// <param name="letter">Letter to check</param>
  1862. /// <returns>True if this a lowercase letter</returns>
  1863. public static bool IsLowercaseLetter(this char letter)
  1864. {
  1865. return letter == ToLower(letter);
  1866. }
  1867. #endregion
  1868. #region IsUppercaseLetter (Static)
  1869. /// <summary>
  1870. /// Helper function to check if this is an uppercase letter.
  1871. /// </summary>
  1872. /// <param name="letter">Letter</param>
  1873. /// <returns>True if this an uppercase letter</returns>
  1874. public static bool IsUppercaseLetter(this char letter)
  1875. {
  1876. return letter == ToUpper(letter);
  1877. }
  1878. #endregion
  1879. #region ToLowerJustFirstLetterUpper (Static)
  1880. /// <summary>
  1881. /// Convert text to lower case letters, make just first letter upper case
  1882. /// </summary>
  1883. /// <param name="someText">Some Text</param>
  1884. /// <returns>String with just the first letter as uppercase</returns>
  1885. public static string ToLowerJustFirstLetterUpper(this string someText)
  1886. {
  1887. // Make sure name is lower case, only first letter is upper case
  1888. return ToUpper(someText[0]) + someText.ToLower().Substring(1);
  1889. }
  1890. #endregion
  1891. #region IsSpaceOrPunctuation (Static)
  1892. /// <summary>
  1893. /// Checks if letter is space ' ' or any punctuation (. , : ; ' " ! ?)
  1894. /// </summary>
  1895. /// <param name="letter">Letter</param>
  1896. /// <returns>True if this letter is space or any punctuation</returns>
  1897. public static bool IsSpaceOrPunctuation(this char letter)
  1898. {
  1899. return
  1900. letter == ' ' ||
  1901. letter == '.' ||
  1902. letter == ',' ||
  1903. letter == ':' ||
  1904. letter == ';' ||
  1905. letter == '\'' ||
  1906. letter == '\"' ||
  1907. letter == '!' ||
  1908. letter == '?' ||
  1909. letter == '*';
  1910. }
  1911. #endregion
  1912. #region GetAllIndicesOf (Static)
  1913. /// <summary>
  1914. /// Get all indices of the given string. Good to check how many occurances
  1915. /// are in a string (e.g. how many special characters are in a code line).
  1916. /// </summary>
  1917. /// <param name="str">String to check</param>
  1918. /// <param name="charValue">Char Value</param>
  1919. /// <returns>Array of indices with the charValue we found</returns>
  1920. public static int[] GetAllIndicesOf(this string str, char charValue)
  1921. {
  1922. List<int> indices = new List<int>();
  1923. string s = str;
  1924. int lastindex = 0;
  1925. int count = 0;
  1926. while (true)
  1927. {
  1928. s = s.Substring(lastindex);
  1929. lastindex = s.IndexOf(charValue);
  1930. if (lastindex < 0)
  1931. {
  1932. return indices.ToArray();
  1933. }
  1934. count += lastindex;
  1935. indices.Add(count);
  1936. lastindex++;
  1937. count++;
  1938. }
  1939. }
  1940. /// <summary>
  1941. /// Get all indices of the given string. Good to check how many occurances
  1942. /// are in a string (e.g. how many special characters are in a code line).
  1943. /// </summary>
  1944. /// <param name="str">String to check</param>
  1945. /// <param name="stringValue">String Value</param>
  1946. /// <returns>Array of indices with the stringValue we found</returns>
  1947. public static int[] GetAllIndicesOf(this string str, string stringValue)
  1948. {
  1949. List<int> indices = new List<int>();
  1950. string s = str;
  1951. int lastindex = 0;
  1952. int count = 0;
  1953. while (true)
  1954. {
  1955. s = s.Substring(lastindex);
  1956. lastindex = s.IndexOf(stringValue);
  1957. if (lastindex < 0)
  1958. {
  1959. return indices.ToArray();
  1960. }
  1961. count += lastindex;
  1962. indices.Add(count);
  1963. lastindex++;
  1964. count++;
  1965. }
  1966. }
  1967. #endregion
  1968. #region IsInList (Static)
  1969. /// <summary>
  1970. /// Is a specific name in a list of strings? This allows multiple strings
  1971. /// to be checked, if any of them matches with the specified "name" (e.g.
  1972. /// ("hi", {"hey", "hello", "hi"}) will return true). Does not do a
  1973. /// contains check, the string has to be in the list.
  1974. /// </summary>
  1975. /// <param name="list">List</param>
  1976. /// <param name="name">Name</param>
  1977. /// <returns>Is name in any of the list entries</returns>
  1978. public static bool IsInList(string name, IEnumerable<string> list)
  1979. {
  1980. return IsInList(name, list, true);
  1981. }
  1982. /// <summary>
  1983. /// Is a specific name in a list of strings? This allows multiple strings
  1984. /// to be checked, if any of them matches with the specified "name" (e.g.
  1985. /// ("hi", {"hey", "hello", "hi"}) will return true). Does not do a
  1986. /// contains check, the string has to be in the list.
  1987. /// </summary>
  1988. /// <param name="list">List</param>
  1989. /// <param name="name">Name</param>
  1990. /// <param name="ignoreCase">Ignore Case</param>
  1991. /// <returns>Is name in any of the list entries</returns>
  1992. public static bool IsInList(string name, IEnumerable<string> list,
  1993. bool ignoreCase)
  1994. {
  1995. StringComparison compareMode = ignoreCase
  1996. ? StringComparison.InvariantCultureIgnoreCase
  1997. : StringComparison.InvariantCulture;
  1998. foreach (string listEntry in list)
  1999. {
  2000. if (String.Compare(name, listEntry, compareMode) == 0)
  2001. {
  2002. return true;
  2003. }
  2004. }
  2005. return false;
  2006. }
  2007. #endregion
  2008. #region GetLastWord (Static)
  2009. /// <summary>
  2010. /// Get last word
  2011. /// </summary>
  2012. /// <param name="text">Text</param>
  2013. /// <returns>Last word of Text</returns>
  2014. public static string GetLastWord(string text)
  2015. {
  2016. return GetLastWord(text, new[]
  2017. {
  2018. ' '
  2019. });
  2020. }
  2021. /// <summary>
  2022. /// Get last word
  2023. /// </summary>
  2024. /// <param name="splitCharacters">Split Characters</param>
  2025. /// <param name="text">Text</param>
  2026. /// <returns>Last word of Text</returns>
  2027. public static string GetLastWord(string text, char[] splitCharacters)
  2028. {
  2029. string[] words = text.Split(splitCharacters);
  2030. if (words.Length > 0)
  2031. {
  2032. return words[words.Length - 1];
  2033. }
  2034. return text;
  2035. }
  2036. #endregion
  2037. #region RemoveFirstWord (Static)
  2038. /// <summary>
  2039. /// Remove first word
  2040. /// </summary>
  2041. /// <param name="text">Text</param>
  2042. /// <returns>String with the first word removed</returns>
  2043. public static string RemoveFirstWord(string text)
  2044. {
  2045. string[] words = text.TrimStart().Split(new char[] { ' ' }, 2);
  2046. if (words.Length > 0)
  2047. {
  2048. string firstWord = words[0];
  2049. if (text == firstWord)
  2050. {
  2051. return "";
  2052. }
  2053. else if (firstWord.Length == 0 ||
  2054. text.Length == 0 ||
  2055. text.Length - firstWord.Length - 1 <= 0)
  2056. {
  2057. return text;
  2058. }
  2059. else
  2060. {
  2061. return text.TrimStart().Substring(firstWord.Length + 1);
  2062. }
  2063. }
  2064. return text;
  2065. }
  2066. #endregion
  2067. #region RemoveLastWord (Static)
  2068. /// <summary>
  2069. /// Remove last word
  2070. /// </summary>
  2071. /// <param name="text">Text</param>
  2072. /// <returns>String with the last word removed</returns>
  2073. public static string RemoveLastWord(string text)
  2074. {
  2075. string lastWord = GetLastWord(text);
  2076. // Fix 2004-10-08: new length can be 0 for killing first word
  2077. if (text == lastWord)
  2078. {
  2079. return "";
  2080. }
  2081. else if (lastWord.Length == 0 ||
  2082. text.Length == 0 ||
  2083. text.Length - lastWord.Length - 1 <= 0)
  2084. {
  2085. return text;
  2086. }
  2087. else
  2088. {
  2089. return text.Substring(0, text.Length - lastWord.Length - 1);
  2090. }
  2091. }
  2092. #endregion
  2093. #region TryToConvertToFloat (Static)
  2094. /// <summary>
  2095. /// Try to convert to float. Will not modify value if that does not work.
  2096. /// This uses also always the invariant culture.
  2097. /// </summary>
  2098. /// <param name="value">Value</param>
  2099. /// <param name="textToConv