PageRenderTime 50ms CodeModel.GetById 3ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 1ms

/Utilities/Helpers/StringHelper.cs

#
C# | 2249 lines | 1460 code | 141 blank | 648 comment | 247 complexity | 1997209697b7ee7278fd993a99206ecd MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file