// Project: XnaGraphicEngine, File: StringHelper.cs // Namespace: XnaGraphicEngine.Helpers, Class: StringHelper // Creation date: 22.11.2004 09:51 // Last modified: 19.01.2006 04:10 // Generated with Commenter by abi.exDream.com #region Using directives #if DEBUG //using NUnit.Framework; #endif using System; using System.Text; using System.Collections; using System.Collections.Specialized; using System.Globalization; using System.Diagnostics; using System.Collections.Generic; #endregion namespace XnaGraphicEngine.Helpers { /// /// StringHelper: Provides additional or simplified string functions. /// This class does also offer a lot of powerful functions and /// allows complicated string operations. /// Easy functions at the beginning, harder ones later. /// public class StringHelper { #region Constants public const string NewLine = "\r\n"; #endregion #region Constructor (it is not allowed to instantiate) /// /// Don't allow instantiating this class. /// private StringHelper() { } // StringHelper() #endregion #region Comparing, Counting and Extraction /// /// Check if a string (s1, can be longer as s2) begins with another /// string (s2), only if s1 begins with the same string data as s2, /// true is returned, else false. The string compare is case insensitive. /// static public bool BeginsWith(string s1, string s2) { return String.Compare(s1, 0, s2, 0, s2.Length, true, CultureInfo.CurrentCulture) == 0; } // BeginsWith(s1, s2) /// /// Helps to compare strings, uses case insensitive comparison. /// String.Compare is also gay because we have always to check for == 0. /// static public bool Compare(string s1, string s2) { return String.Compare(s1, s2, true, CultureInfo.CurrentCulture) == 0; } // Compare(s1, s2) /// /// Helps to compare strings, uses case insensitive comparison. /// String.Compare is also gay because we have always to check for == 0. /// This overload allows multiple strings to be checked, if any of /// them matches we are good to go (e.g. ("hi", {"hey", "hello", "hi"}) /// will return true). /// static public bool Compare(string s1, string[] anyMatch) { if (anyMatch == null) throw new ArgumentNullException("anyMatch", "Unable to execute method without valid anyMatch array."); foreach (string match in anyMatch) if (String.Compare(s1, match, true, CultureInfo.CurrentCulture) == 0) return true; return false; } // Compare(s1, anyMatch) /// /// Is a specific name in a list of strings? /// static public bool IsInList( string name, ArrayList list, bool ignoreCase) { if (list == null) throw new ArgumentNullException("list", "Unable to execute method without valid list."); foreach (string listEntry in list) if (String.Compare(name, listEntry, ignoreCase, CultureInfo.CurrentCulture) == 0) return true; return false; } // IsInList(name, list, ignoreCase) /// /// Is a specific name in a list of strings? /// static public bool IsInList( string name, string[] list, bool ignoreCase) { if (list == null) throw new ArgumentNullException("list", "Unable to execute method without valid list."); foreach (string listEntry in list) if (String.Compare(name, listEntry, ignoreCase, CultureInfo.CurrentCulture) == 0) return true; return false; } // IsInList(name, list, ignoreCase) /// /// Count words in a text (words are only separated by ' ' (spaces)) /// static public int CountWords(string text) { if (text == null) throw new ArgumentNullException("text", "Unable to execute method without valid text."); return text.Split(new char[] { ' ' }).Length; } // CountWords(text) /// /// Compare char case insensitive /// /// C 1 /// C 2 /// Bool public static bool CompareCharCaseInsensitive(char c1, char c2) { return char.ToLower(c1) == char.ToLower(c2); // Another way (slower): // return String.Compare("" + c1, "" + c2, true) == 0; } // CompareCharCaseInsensitive(c1, c2) /// /// Get last word /// /// Text /// String public static string GetLastWord(string text) { if (text == null) throw new ArgumentNullException("text", "Unable to execute method without valid text."); string[] words = text.Split(new char[] { ' ' }); if (words.Length > 0) return words[words.Length - 1]; return text; } // GetLastWord(text) /// /// Remove last word /// /// Text /// String public static string RemoveLastWord(string text) { string lastWord = GetLastWord(text); // Fix 2004-10-08: new length can be 0 for killing first word if (text == lastWord) return ""; else if (lastWord.Length == 0 || text.Length == 0 || text.Length - lastWord.Length - 1 <= 0) return text; else return text.Substring(0, text.Length - lastWord.Length - 1); } // RemoveLastWord(text) /// /// Get all spaces and tabs at beginning /// /// Text /// String static public string GetAllSpacesAndTabsAtBeginning(string text) { if (text == null) throw new ArgumentNullException("text", "Unable to execute method without valid text."); StringBuilder ret = new StringBuilder(); for (int pos = 0; pos < text.Length; pos++) { if (text[pos] == ' ' || text[pos] == '\t') ret.Append(text[pos]); else break; } // for (pos) return ret.ToString(); } // GetAllSpacesAndTabsAtBeginning(text) /// /// Get tab depth /// /// Text /// Int static public int GetTabDepth(string text) { for (int textPos = 0; textPos < text.Length; textPos++) if (text[textPos] != '\t') return textPos; return text.Length; } // GetTabDepth(text) /// /// Check string word length /// public static string CheckStringWordLength( string originalText, int maxLength) { if (originalText == null) throw new ArgumentNullException("originalText", "Unable to execute method without valid text."); string[] splitted = originalText.Split(new char[] { ' ' }); string ret = ""; foreach (string word in splitted) { if (word.Length <= maxLength) ret += word + " "; else { for (int i = 0; i < word.Length / maxLength; i++) ret += word.Substring(i * maxLength, maxLength) + " "; } // else } // foreach (word, splitted) return ret.TrimEnd(); } // CheckStringWordLength(originalText, maxLength) #endregion #region String contains (for case insensitive compares) /// /// Is searchName contained in textToCheck, will check case insensitive, /// for a normal case sensitive test use textToCheck.Contains(searchName) /// /// Text to check /// Search name /// Bool public static bool Contains(string textToCheck, string searchName) { return textToCheck.ToLower().Contains(searchName.ToLower()); } // Contains(textToCheck, searchName) /// /// Is any of the names in searchNames contained in textToCheck, /// will check case insensitive, for a normal case sensitive test /// use textToCheck.Contains(searchName). /// /// String to check /// Search names /// Bool public static bool Contains(string textToCheck, string[] searchNames) { string stringToCheckLower = textToCheck.ToLower(); foreach (string name in searchNames) if (stringToCheckLower.Contains(name.ToLower())) return true; // Nothing found, no searchNames is contained in textToCheck return false; } // Contains(textToCheck, searchNames) #endregion #region Write data /// /// Returns a string with the array data, byte array version. /// static public string WriteArrayData(byte[] byteArray) { StringBuilder ret = new StringBuilder(); if (byteArray != null) for (int i = 0; i < byteArray.Length; i++) ret.Append((ret.Length == 0 ? "" : ", ") + byteArray[i].ToString(CultureInfo.InvariantCulture.NumberFormat)); return ret.ToString(); } // WriteArrayData(byteArray) /// /// Returns a string with the array data, int array version. /// static public string WriteArrayData(int[] intArray) { StringBuilder ret = new StringBuilder(); if (intArray != null) for (int i = 0; i < intArray.Length; i++) ret.Append((ret.Length == 0 ? "" : ", ") + intArray[i].ToString(CultureInfo.InvariantCulture.NumberFormat)); return ret.ToString(); } // WriteArrayData(intArray) /// /// Returns a string with the array data, general array version. /// static public string WriteArrayData(Array array) { StringBuilder ret = new StringBuilder(); if (array != null) for (int i = 0; i < array.Length; i++) ret.Append((ret.Length == 0 ? "" : ", ") + (array.GetValue(i) == null ? "null" : array.GetValue(i).ToString())); return ret.ToString(); } // WriteArrayData(array) /// /// Returns a string with the array data, general array version /// with maxLength bounding (will return string with max. this /// number of entries). /// static public string WriteArrayData(Array array, int maxLength) { StringBuilder ret = new StringBuilder(); if (array != null) for (int i = 0; i < array.Length && i < maxLength; i++) ret.Append((ret.Length == 0 ? "" : ", ") + array.GetValue(i).ToString()); return ret.ToString(); } // WriteArrayData(array, maxLength) /// /// Returns a string with the array data, ArrayList version. /// static public string WriteArrayData(ArrayList array) { StringBuilder ret = new StringBuilder(); if (array != null) foreach (object obj in array) ret.Append((ret.Length == 0 ? "" : ", ") + obj.ToString()); return ret.ToString(); } // WriteArrayData(array) /// /// Returns a string with the array data, CollectionBase version. /// static public string WriteArrayData(CollectionBase collection) { StringBuilder ret = new StringBuilder(); if (collection != null) foreach (object obj in collection) ret.Append((ret.Length == 0 ? "" : ", ") + obj.ToString()); return ret.ToString(); } // WriteArrayData(collection) #if !XBOX360 /// /// Returns a string with the array data, StringCollection version. /// static public string WriteArrayData(StringCollection textCollection) { StringBuilder ret = new StringBuilder(); if (textCollection != null) foreach (string s in textCollection) ret.Append((ret.Length == 0 ? "" : ", ") + s); return ret.ToString(); } // WriteArrayData(textCollection) #endif /// /// Returns a string with the array data, enumerable class version. /// static public string WriteArrayData(IEnumerable enumerableClass) { StringBuilder ret = new StringBuilder(); if (enumerableClass != null) foreach (object obj in enumerableClass) ret.Append((ret.Length == 0 ? "" : ", ") + obj.ToString()); return ret.ToString(); } // WriteArrayData(enumerableClass) /// /// Write into space string, useful for writing parameters without /// knowing the length of each string, e.g. when writing numbers /// (-1, 1.45, etc.). You can use this function to give all strings /// the same width in a table. Maybe there is already a string function /// for this, but I don't found any useful stuff. /// static public string WriteIntoSpaceString(string message, int spaces) { if (message == null) throw new ArgumentNullException("message", "Unable to execute method without valid text."); // Msg is already that long or longer? if (message.Length >= spaces) return message; // Create string with number of specified spaces char[] ret = new char[spaces]; // Copy data int i; for (i = 0; i < message.Length; i++) ret[i] = message[i]; // Fill rest with spaces for (i = message.Length; i < spaces; i++) ret[i] = ' '; // Return result return new string(ret); } // WriteIntoSpaceString(message, spaces) /// /// Write Iso Date (Year-Month-Day) /// public static string WriteIsoDate(DateTime date) { return date.Year + "-" + date.Month.ToString("00") + "-" + date.Day.ToString("00"); } // WriteIsoDate(date) /// /// Write Iso Date and time (Year-Month-Day Hour:Minute) /// public static string WriteIsoDateAndTime(DateTime date) { return date.Year + "-" + date.Month.ToString("00") + "-" + date.Day.ToString("00") + " " + date.Hour.ToString("00") + ":" + date.Minute.ToString("00"); } // WriteIsoDateAndTime(date) /// /// Write internet time /// /// Time /// Daylight saving /// String public static string WriteInternetTime( DateTime time, bool daylightSaving) { return "@" + ((float)((int)(time.ToUniversalTime().AddHours( daylightSaving ? 1 : 0).TimeOfDay. TotalSeconds * 100000 / (24 * 60 * 60))) / 100.0f).ToString( NumberFormatInfo.InvariantInfo); } // WriteInternetTime(time, daylightSaving) #endregion #region Convert methods /// /// Convert string data to int array, string must be in the form /// "1, 3, 8, 7", etc. WriteArrayData is the complementar function. /// /// int array, will be null if string is invalid! static public int[] ConvertStringToIntArray(string s) { // Invalid? if (s == null || s.Length == 0) return null; string[] splitted = s.Split(new char[] { ' ' }); int[] ret = new int[splitted.Length]; for (int i = 0; i < ret.Length; i++) { try { ret[i] = Convert.ToInt32(splitted[i]); } // try catch { } // ignore } // for (i) return ret; } // ConvertStringToIntArray(str) /// /// Convert string data to float array, string must be in the form /// "1.5, 3.534, 8.76, 7.49", etc. WriteArrayData is the complementar /// function. /// /// float array, will be null if string is invalid! static public float[] ConvertStringToFloatArray(string s) { // Invalid? if (s == null || s.Length == 0) return null; string[] splitted = s.Split(new char[] { ' ' }); float[] ret = new float[splitted.Length]; for (int i = 0; i < ret.Length; i++) { try { ret[i] = Convert.ToSingle(splitted[i], CultureInfo.InvariantCulture); } // try catch { } // ignore } // for (i) return ret; } // ConvertStringToIntArray(str) #endregion #region File stuff /// /// Extracts filename from full path+filename, cuts of extension /// if cutExtension is true. Can be also used to cut of directories /// from a path (only last one will remain). /// static public string ExtractFilename(string pathFile, bool cutExtension) { if (pathFile == null) return ""; // Update 2006-09-29: also checking for normal slashes, needed // for support reading 3ds max stuff. string[] fileName = pathFile.Split(new char[] { '\\', '/' }); if (fileName.Length == 0) { if (cutExtension) return CutExtension(pathFile); return pathFile; } // if (fileName.Length) if (cutExtension) return CutExtension(fileName[fileName.Length - 1]); return fileName[fileName.Length - 1]; } // ExtractFilename(pathFile, cutExtension) /// /// Get directory of path+File, if only a path is given we will cut off /// the last sub path! /// static public string GetDirectory(string pathFile) { if (pathFile == null) return ""; int i = pathFile.LastIndexOf("\\"); if (i >= 0 && i < pathFile.Length) // Return directory return pathFile.Substring(0, i); // No sub directory found (parent of some dir is "") return ""; } // GetDirectory(pathFile) /// /// Same as GetDirectory(): Get directory of path+File, /// if only a path is given we will cut of the last sub path! /// static public string CutOneFolderOff(string path) { // GetDirectory does exactly what we need! return GetDirectory(path); } // CutOneFolderOff(path) /// /// Splits a path into all parts of its directories, /// e.g. "maps\\sub\\kekse" becomes /// {"maps\\sub\\kekse","maps\\sub","maps"} /// static public string[] SplitDirectories(string path) { ArrayList localList = new ArrayList(); localList.Add(path); do { path = CutOneFolderOff(path); if (path.Length > 0) localList.Add(path); } while (path.Length > 0); return (string[])localList.ToArray(typeof(string)); } // SplitDirectories(path) /// /// Remove first directory of path (if one exists). /// e.g. "maps\\mymaps\\hehe.map" becomes "mymaps\\hehe.map" /// Also used to cut first folder off, especially useful for relative /// paths. e.g. "maps\\test" becomes "test" /// static public string RemoveFirstDirectory(string path) { int i = path.IndexOf("\\"); if (i >= 0 && i < path.Length) // Return rest of path return path.Substring(i + 1); // No first directory found, just return original path return path; } // RemoveFirstDirectory(path) /// /// Check if a folder is a direct sub folder of a main folder. /// True is only returned if this is a direct sub folder, not if /// it is some sub folder few levels below. /// static public bool IsDirectSubfolder(string subfolder, string mainFolder) { // First check if subFolder is really a sub folder of mainFolder if (subfolder != null && subfolder.StartsWith(mainFolder)) { // Same order? if (subfolder.Length < mainFolder.Length + 1) // Then it ain't a sub folder! return false; // Ok, now check if this is direct sub folder or some sub folder // of mainFolder sub folder string folder = subfolder.Remove(0, mainFolder.Length + 1); // Check if this is really a direct sub folder for (int i = 0; i < folder.Length; i++) if (folder[i] == '\\') // No, this is a sub folder of mainFolder sub folder return false; // Ok, this is a direct sub folder of mainFolder! return true; } // if (subFolder) // Not even any sub folder! return false; } // IsDirectSubFolder(subFolder, mainFolder) /// /// Cut of extension, e.g. "hi.txt" becomes "hi" /// static public string CutExtension(string file) { if (file == null) return ""; int l = file.LastIndexOf('.'); if (l > 0) return file.Remove(l, file.Length - l); return file; } // CutExtension(file) /// /// Get extension (the stuff behind that '.'), /// e.g. "test.bmp" will return "bmp" /// static public string GetExtension(string file) { if (file == null) return ""; int l = file.LastIndexOf('.'); if (l > 0 && l < file.Length) return file.Remove(0, l + 1); return ""; } // GetExtension(file) #endregion #region String splitting and getting it back together /// /// Performs basically the same job as String.Split, but does /// trim all parts, no empty parts are returned, e.g. /// "hi there" returns "hi", "there", String.Split would return /// "hi", "", "there". /// public static string[] SplitAndTrim(string text, char separator) { ArrayList ret = new ArrayList(); string[] splitted = text.Split(new char[] { separator }); foreach (string s in splitted) if (s.Length > 0) ret.Add(s); return (string[])ret.ToArray(typeof(string)); } // SplitAndTrim(text, separator) /// /// Splits a multi line string to several strings and /// returns the result as a string array. /// Will also remove any \r, \n or space character /// at the end of each line! /// public static string[] SplitMultilineText(string text) { if (text == null) throw new ArgumentNullException("text", "Unable to execute method without valid text."); ArrayList ret = new ArrayList(); // Supports any format, only \r, only \n, normal \n\r, // crazy \r\n or even mixed \n\r with any format string[] splitted1 = text.Split(new char[] { '\n' }); string[] splitted2 = text.Split(new char[] { '\r' }); string[] splitted = splitted1.Length >= splitted2.Length ? splitted1 : splitted2; foreach (string s in splitted) { // Never add any \r or \n to the single lines if (s.EndsWith("\r") || s.EndsWith("\n")) ret.Add(s.Substring(0, s.Length - 1)); else if (s.StartsWith("\n") || s.StartsWith("\r")) ret.Add(s.Substring(1)); else ret.Add(s); } // foreach (s, splitted) return (string[])ret.ToArray(typeof(string)); } // SplitMultiLineText(text) /// /// Build string from lines /// /// Lines /// Start line /// Start offset /// End line /// End offset /// Separator /// String static public string BuildStringFromLines( string[] lines, int startLine, int startOffset, int endLine, int endOffset, string separator) { if (lines == null) throw new ArgumentNullException("lines", "Unable to execute method without valid lines."); // Check if all values are in range (correct if not) if (startLine >= lines.Length) startLine = lines.Length - 1; if (endLine >= lines.Length) endLine = lines.Length - 1; if (startLine < 0) startLine = 0; if (endLine < 0) endLine = 0; if (startOffset >= lines[startLine].Length) startOffset = lines[startLine].Length - 1; if (endOffset >= lines[endLine].Length) endOffset = lines[endLine].Length - 1; if (startOffset < 0) startOffset = 0; if (endOffset < 0) endOffset = 0; StringBuilder builder = new StringBuilder((endLine - startLine) * 80); for (int lineNumber = startLine; lineNumber <= endLine; lineNumber++) { if (lineNumber == startLine) builder.Append(lines[lineNumber].Substring(startOffset)); else if (lineNumber == endLine) builder.Append(lines[lineNumber].Substring(0, endOffset + 1)); else builder.Append(lines[lineNumber]); if (lineNumber != endLine) builder.Append(separator); } // for (lineNumber) return builder.ToString(); } // BuildStringFromLines(lines, startLine, startOffset) static public string BuildStringFromLines( string[] lines, string separator) { StringBuilder builder = new StringBuilder(lines.Length * 80); for (int lineNumber = 0; lineNumber < lines.Length; lineNumber++) { builder.Append(lines[lineNumber]); if (lineNumber != lines.Length - 1) builder.Append(separator); } // for (lineNumber) return builder.ToString(); } // BuildStringFromLines(lines, separator) /// /// Build string from lines /// /// Lines /// String static public string BuildStringFromLines(string[] lines) { return BuildStringFromLines(lines, NewLine); } // BuildStringFromLines(lines) /// /// Build string from lines /// /// Lines /// Start line /// End line /// Separator /// String static public string BuildStringFromLines( string[] lines, int startLine, int endLine, string separator) { // Check if all values are in range (correct if not) if (startLine < 0) startLine = 0; if (endLine < 0) endLine = 0; if (startLine >= lines.Length) startLine = lines.Length - 1; if (endLine >= lines.Length) endLine = lines.Length - 1; StringBuilder builder = new StringBuilder((endLine - startLine) * 80); for (int lineNumber = startLine; lineNumber <= endLine; lineNumber++) { builder.Append(lines[lineNumber]); if (lineNumber != endLine) builder.Append(separator); } // for (lineNumber) return builder.ToString(); } // BuildStringFromLines(lines, startLine, endLine) /// /// Cut modes /// public enum CutMode { Begin, End, BothEnds } // enum CutMode /// /// Maximum string length /// /// Original text /// Maximum length /// Cut mode /// String public static string MaxStringLength(string originalText, int maxLength, CutMode cutMode) { if (originalText.Length <= maxLength) return originalText; if (cutMode == CutMode.Begin) return originalText.Substring( originalText.Length - maxLength, maxLength); else if (cutMode == CutMode.End) return originalText.Substring(0, maxLength); else // logic: if ( cutMode == CutModes.BothEnds ) return originalText.Substring( (originalText.Length - maxLength) / 2, maxLength); } // MaxStringLength(originalText, maxLength, cutMode) /// /// Get left part of everything to the left of the first /// occurrence of a character. /// public static string GetLeftPartAtFirstOccurence( string sourceText, char ch) { if (sourceText == null) throw new ArgumentNullException("sourceText", "Unable to execute this method without valid string."); int index = sourceText.IndexOf(ch); if (index == -1) return sourceText; return sourceText.Substring(0, index); } // GetLeftPartAtFirstOccurence(sourceText, ch) /// /// Get right part of everything to the right of the first /// occurrence of a character. /// public static string GetRightPartAtFirstOccurrence( string sourceText, char ch) { if (sourceText == null) throw new ArgumentNullException("sourceText", "Unable to execute this method without valid string."); int index = sourceText.IndexOf(ch); if (index == -1) return ""; return sourceText.Substring(index + 1); } // GetRightPartAtFirstOccurrence(sourceText, ch) /// /// Get left part of everything to the left of the last /// occurrence of a character. /// public static string GetLeftPartAtLastOccurrence( string sourceText, char ch) { if (sourceText == null) throw new ArgumentNullException("sourceText", "Unable to execute this method without valid string."); int index = sourceText.LastIndexOf(ch); if (index == -1) return sourceText; return sourceText.Substring(0, index); } // GetLeftPartAtLastOccurrence(sourceText, ch) /// /// Get right part of everything to the right of the last /// occurrence of a character. /// public static string GetRightPartAtLastOccurrence( string sourceText, char ch) { if (sourceText == null) throw new ArgumentNullException("sourceText", "Unable to execute this method without valid string."); int index = sourceText.LastIndexOf(ch); if (index == -1) return sourceText; return sourceText.Substring(index + 1); } // GetRightPartAtLastOccurrence(sourceText, ch) /// /// Create password string /// /// Original text /// String public static string CreatePasswordString(string originalText) { if (originalText == null) throw new ArgumentNullException("originalText", "Unable to execute this method without valid string."); string passwordString = ""; for (int i = 0; i < originalText.Length; i++) passwordString += "*"; return passwordString; } // CreatePasswordString(originalText) /// /// Helper function to convert letter to lowercase. Could someone /// tell me the reason why there is no function for that in char? /// public static char ToLower(char letter) { return (char)letter.ToString().ToLower( CultureInfo.InvariantCulture)[0]; } // ToLower(letter) /// /// Helper function to convert letter to uppercase. Could someone /// tell me the reason why there is no function for that in char? /// public static char ToUpper(char letter) { return (char)letter.ToString().ToUpper( CultureInfo.InvariantCulture)[0]; } // ToUpper(letter) /// /// Helper function to check if this is an lowercase letter. /// public static bool IsLowercaseLetter(char letter) { return letter == ToLower(letter); } // IsLowercaseLetter(letter) /// /// Helper function to check if this is an uppercase letter. /// public static bool IsUppercaseLetter(char letter) { return letter == ToUpper(letter); } // IsUppercaseLetter(letter) /// /// Helper function for SplitFunctionNameToWordString to detect /// abbreviations in the function name /// private static int GetAbbreviationLengthInFunctionName( string functionName, int startPos) { StringBuilder abbreviation = new StringBuilder(); // Go through string until we reach a lower letter or it ends for (int pos = startPos; pos < functionName.Length; pos++) { // Quit if its not an uppercase letter if (StringHelper.IsUppercaseLetter(functionName[pos]) == false) break; // Else just add letter abbreviation.Append(functionName[pos]); } // for (pos) // Abbreviation has to be at least 2 letters long. if (abbreviation.Length >= 2) { // If not at end of functionName, last letter belongs to next name, // e.g. "TW" is not a abbreviation in "HiMrTWhatsUp", // "AB" isn't one either in "IsABall", // but "PQ" is in "PQList" and "AB" is in "MyAB" if (startPos + abbreviation.Length >= functionName.Length) // Ok, then return full abbreviation length return abbreviation.Length; // Else return length - 1 because of next word return abbreviation.Length - 1; } // if (abbreviation.Length) // No Abbreviation, just return 1 return 1; } // GetAbbreviationLengthInFunctionName(functionName, startPos) /// /// Checks if letter is space ' ' or any punctuation (. , : ; ' " ! ?) /// public static bool IsSpaceOrPunctuation(char letter) { return letter == ' ' || letter == '.' || letter == ',' || letter == ':' || letter == ';' || letter == '\'' || letter == '\"' || letter == '!' || letter == '?' || letter == '*'; } // IsSpaceOrPunctuation(letter) /// /// Splits a function name to words, e.g. /// "MakeDamageOnUnit" gets "Make damage on unit". /// Will also detect abbreviation like TCP and leave them /// intact, e.g. "CreateTCPListener" gets "Create TCP listener". /// public static string SplitFunctionNameToWordString(string functionName) { if (functionName == null || functionName.Length == 0) return ""; string ret = ""; // Go through functionName and find big letters! for (int pos = 0; pos < functionName.Length; pos++) { char letter = functionName[pos]; // First letter is always big! if (pos == 0 || pos == 1 && StringHelper.IsUppercaseLetter(functionName[1]) && StringHelper.IsUppercaseLetter(functionName[0]) || pos == 2 && StringHelper.IsUppercaseLetter(functionName[2]) && StringHelper.IsUppercaseLetter(functionName[1]) && StringHelper.IsUppercaseLetter(functionName[0])) ret += StringHelper.ToUpper(letter); // Found uppercase letter? else if (StringHelper.IsUppercaseLetter(letter) && //also support numbers and other symbols not lower/upper letter: //StringHelper.IsLowercaseLetter(letter) == false && // But don't allow space or any punctuation (. , : ; ' " ! ?) StringHelper.IsSpaceOrPunctuation(letter) == false && ret.EndsWith(" ") == false) { // Could be new word, but we have to check if its an abbreviation int abbreviationLength = GetAbbreviationLengthInFunctionName( functionName, pos); // Found valid abbreviation? if (abbreviationLength > 1) { // Then add it ret += " " + functionName.Substring(pos, abbreviationLength); // And advance pos (abbreviation is longer than 1 letter) pos += abbreviationLength - 1; } // if (abbreviationLength) // Else just add new word (in lower letter) else ret += " " + StringHelper.ToLower(letter); } // else if else // Just add letter ret += letter; } // for (pos) return ret; } // SplitFunctionNameToWordString(functionName) #endregion #region Remove character /// /// Remove character from text. /// /// Text /// Character to be removed public static void RemoveCharacter(ref string text, char characterToBeRemoved) { if (text == null) throw new ArgumentNullException("text", "Unable to execute method without valid text."); if (text.Contains(characterToBeRemoved.ToString())) text = text.Replace(characterToBeRemoved.ToString(), ""); } // RemoveCharacter(text, characterToBeRemoved) #endregion #region Kb/mb name generator /// /// Write bytes, KB, MB, GB, TB message. /// 1 KB = 1024 Bytes /// 1 MB = 1024 KB = 1048576 Bytes /// 1 GB = 1024 MB = 1073741824 Bytes /// 1 TB = 1024 GB = 1099511627776 Bytes /// E.g. 100 will return "100 Bytes" /// 2048 will return "2.00 KB" /// 2500 will return "2.44 KB" /// 1534905 will return "1.46 MB" /// 23045904850904 will return "20.96 TB" /// public static string WriteBigByteNumber( long bigByteNumber, string decimalSeperator) { if (bigByteNumber < 0) return "-" + WriteBigByteNumber(-bigByteNumber); if (bigByteNumber <= 999) return bigByteNumber + " Bytes"; if (bigByteNumber <= 999 * 1024) { double fKB = (double)bigByteNumber / 1024.0; return (int)fKB + decimalSeperator + ((int)(fKB * 100.0f) % 100).ToString("00") + " KB"; } // if if (bigByteNumber <= 999 * 1024 * 1024) { double fMB = (double)bigByteNumber / (1024.0 * 1024.0); return (int)fMB + decimalSeperator + ((int)(fMB * 100.0f) % 100).ToString("00") + " MB"; } // if // this is very big ^^ will not fit into int if (bigByteNumber <= 999L * 1024L * 1024L * 1024L) { double fGB = (double)bigByteNumber / (1024.0 * 1024.0 * 1024.0); return (int)fGB + decimalSeperator + ((int)(fGB * 100.0f) % 100).ToString("00") + " GB"; } // if //if ( num <= 999*1024*1024*1024*1024 ) //{ double fTB = (double)bigByteNumber / (1024.0 * 1024.0 * 1024.0 * 1024.0); return (int)fTB + decimalSeperator + ((int)(fTB * 100.0f) % 100).ToString("00") + " TB"; //} // if } // WriteBigByteNumber(num, decimalSeperator) /// /// Write bytes, KB, MB, GB, TB message. /// 1 KB = 1024 Bytes /// 1 MB = 1024 KB = 1048576 Bytes /// 1 GB = 1024 MB = 1073741824 Bytes /// 1 TB = 1024 GB = 1099511627776 Bytes /// E.g. 100 will return "100 Bytes" /// 2048 will return "2.00 KB" /// 2500 will return "2.44 KB" /// 1534905 will return "1.46 MB" /// 23045904850904 will return "20.96 TB" /// public static string WriteBigByteNumber(long bigByteNumber) { string decimalSeperator = CultureInfo.CurrentCulture. NumberFormat.CurrencyDecimalSeparator; return WriteBigByteNumber(bigByteNumber, decimalSeperator); } // WriteBigByteNumber(num) #endregion #region Try parse methods that are not available on the XBox360! /// /// Is numeric float /// /// Str /// Bool public static bool IsNumericFloat(string str) { return IsNumericFloat(str, CultureInfo.InvariantCulture.NumberFormat); } // IsNumericFloat(str) /// /// Allow only one decimal point, used for IsNumericFloat. /// /// Input string to check /// Used number format, e.g. /// CultureInfo.InvariantCulture.NumberFormat /// True if check succeeded, false otherwise private static bool AllowOnlyOneDecimalPoint(string str, NumberFormatInfo numberFormat) { char[] strInChars = str.ToCharArray(); bool hasGroupSeperator = false; int decimalSeperatorCount = 0; for (int i = 0; i < strInChars.Length; i++) { if (numberFormat.CurrencyDecimalSeparator.IndexOf(strInChars[i]) == 0) { decimalSeperatorCount++; } // if (numberFormat.CurrencyDecimalSeparator.IndexOf) // has float group seperators ? if (numberFormat.CurrencyGroupSeparator.IndexOf(strInChars[i]) == 0) { hasGroupSeperator = true; } // if (numberFormat.CurrencyGroupSeparator.IndexOf) } // for (int) if (hasGroupSeperator) { // If first digit is the group seperator or begins with 0, // there is something wrong, the group seperator is used as a comma. if (str.StartsWith(numberFormat.CurrencyGroupSeparator) || strInChars[0] == '0') return false; // look only at the digits in front of the decimal point string[] splittedByDecimalSeperator = str.Split( numberFormat.CurrencyDecimalSeparator.ToCharArray()); #region Invert the digits for modulo check // ==> 1.000 -> 000.1 ==> only after 3 digits char[] firstSplittedInChars = splittedByDecimalSeperator[0].ToCharArray(); int arrayLength = firstSplittedInChars.Length; char[] firstSplittedInCharsInverted = new char[arrayLength]; for (int i = 0; i < arrayLength; i++) { firstSplittedInCharsInverted[i] = firstSplittedInChars[arrayLength - 1 - i]; } // for (int) #endregion // group seperators are only allowed between 3 digits -> 1.000.000 for (int i = 0; i < arrayLength; i++) { if (i % 3 != 0 && numberFormat.CurrencyGroupSeparator.IndexOf( firstSplittedInCharsInverted[i]) == 0) { return false; } // if (i) } // for (int) } // if (hasGroupSeperator) if (decimalSeperatorCount > 1) return false; return true; } // AllowOnlyOneDecimalPoint(str, numberFormat) /// /// Checks if string is numeric float value /// /// Input string /// Used number format, e.g. /// CultureInfo.InvariantCulture.NumberFormat /// True if str can be converted to a float, /// false otherwise public static bool IsNumericFloat(string str, NumberFormatInfo numberFormat) { // Can't be a float if string is not valid! if (String.IsNullOrEmpty(str)) return false; //not supported by Convert.ToSingle: //if (str.EndsWith("f")) // str = str.Substring(0, str.Length - 1); // Only 1 decimal point is allowed if (AllowOnlyOneDecimalPoint(str, numberFormat) == false) return false; // + allows in the first,last,don't allow in middle of the string // - allows in the first,last,don't allow in middle of the string // $ allows in the first,last,don't allow in middle of the string // , allows in the last,middle,don't allow in first char of the string // . allows in the first,last,middle, allows in all the indexs bool retVal = false; // If string is just 1 letter, don't allow it to be a sign if (str.Length == 1 && "+-$.,".IndexOf(str[0]) >= 0) return false; for (int i = 0; i < str.Length; i++) { // For first indexchar char pChar = //char.Parse(str.Substring(i, 1)); Convert.ToChar(str.Substring(i, 1)); if (retVal) retVal = false; if ((!retVal) && (str.IndexOf(pChar) == 0)) { retVal = ("+-$.0123456789".IndexOf(pChar) >= 0) ? true : false; } // if () // For middle characters if ((!retVal) && (str.IndexOf(pChar) > 0) && (str.IndexOf(pChar) < (str.Length - 1))) { retVal = (",.0123456789".IndexOf(pChar) >= 0) ? true : false; } // if () // For last characters if ((!retVal) && (str.IndexOf(pChar) == (str.Length - 1))) { retVal = ("+-$,.0123456789".IndexOf(pChar) >= 0) ? true : false; } // if () if (!retVal) break; } // for (int) return retVal; } // IsNumericFloat(str, numberFormat) /// /// Try to convert to float. Will not modify value if that does not work. /// This uses also always the invariant culture. /// /// Value /// Text to convert public static void TryToConvertToFloat( ref float value, string textToConvert) { TryToConvertToFloat(ref value, textToConvert, System.Globalization.NumberFormatInfo.InvariantInfo); } // TryToConvertToFloat(value, textToConvert) /// /// Try to convert to float. Will not modify value if that does not work. /// /// Value /// Text to convert /// Format for converting public static void TryToConvertToFloat( ref float value, string textToConvert, NumberFormatInfo format) { // Basically the same as float.TryParse(), but faster! if (IsNumericFloat(textToConvert, format)) { value = Convert.ToSingle(textToConvert, format); } // if (IsNumericFloat) } // TryToConvertToFloat(value, textToConvert, format) /// /// Check if string is numeric integer. A decimal point is not accepted. /// /// String to check public static bool IsNumericInt(string str) { // Can't be an int if string is not valid! if (String.IsNullOrEmpty(str)) return false; // Go through every letter in str int strPos = 0; foreach (char ch in str) { // Only 0-9 are allowed if ("0123456789".IndexOf(ch) < 0 && // Allow +/- for first char (strPos > 0 || (ch != '-' && ch != '+'))) return false; strPos++; } // foreach (ch in str) // All fine, return true, this is a number! return true; } // IsNumericInt(str) #endregion #region Unit Testing #if DEBUG /*include NUnit.Framework for this /// /// String helper tests /// //[TestFixture] public class StringHelperTests { /// /// Test is in list /// //[Test] public void TestIsInList() { Assert.IsTrue(IsInList("whats", new string[] { "hi", "whats", "up?" }, false)); Assert.IsFalse(IsInList("no way", new string[] { "omg", "no no", "there is no way!" }, false)); } // TestIsInList() /// /// Test write array /// //[Test] public void TestWriteArray() { Assert.AreEqual( "3, 5, 10", WriteArrayData(new int[] { 3, 5, 10 })); Assert.AreEqual( "one, after, another", WriteArrayData(new string[] { "one", "after", "another" })); List genericList = new List(); genericList.Add("whats"); genericList.AddRange(new string[] { "going", "on" }); Assert.AreEqual( "whats, going, on", WriteArrayData(genericList)); } // TestWriteArray() /// /// Test split string and combine again /// //[Test] public void TestSplitStringAndCombineAgain() { string testText = @"using System; namespace TestVs2003 { public class Form1 : System.Windows.Forms.Form { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.Run(new Form1()); } } }"; // Test splitting lines and combine them back together string[] lines = SplitMultilineText(testText); Assert.IsTrue(lines.Length > 0, "no lines were returned"); string reconstructedText = BuildStringFromLines(lines); Assert.AreEqual(testText, reconstructedText, "testText is not equal to reconstructedText"); // Also test other functions string[] words = SplitAndTrim(testText, ' '); Assert.AreEqual(words.Length, CountWords(testText), "words.Length"); Assert.AreEqual(testText, BuildStringFromLines(words, " ")); // Call with some invalid values BuildStringFromLines(words, 1, -3, 4, 6, " "); BuildStringFromLines(words, 1, 3, 400, 6, " "); BuildStringFromLines(words, 1, 3, 4, 600, " "); // Check is we can build a part back together // Check if we can build a part back together Assert.AreEqual( testText.Substring(10, 20), BuildStringFromLines(lines, 0, 10, 2, 12, NewLine)); // Get section code and check if we got everything right Assert.AreEqual( @"static void Main() { Application.Run(new Form1()); }", BuildStringFromLines(lines, 10, 2, 13, 3, NewLine)); // Also check if we change some line we still got the same // number of resulting lines. lines[13] += " // Test comment"; Assert.AreEqual(lines.Length, SplitMultilineText(BuildStringFromLines(lines, NewLine)).Length); } // TestSplitStringAndCombineAgain() /// /// Test split multiline text /// //[Test] public void TestSplitMultilineText() { Assert.AreEqual(4, StringHelper.SplitMultilineText( @"test now an empty lie thats it").Length); // Test few empty lines Assert.AreEqual(6, StringHelper.SplitMultilineText( "hi\n\n\n\n\rthere\n").Length); // Test all combination of '\r' and '\n' Assert.AreEqual(2, StringHelper.SplitMultilineText( "test1" + '\r' + "test2").Length); Assert.AreEqual(2, StringHelper.SplitMultilineText( "test1" + '\n' + "test2").Length); Assert.AreEqual(2, StringHelper.SplitMultilineText( "test1" + "\n\r" + "test2").Length); Assert.AreEqual(2, StringHelper.SplitMultilineText( "test1" + "\r\n" + "test2").Length); // Also test if mixing normal "\n\r" with '\r' or '\n' Assert.AreEqual(3, StringHelper.SplitMultilineText( "test1" + '\n' + "" + '\r' + "test2" + '\r' + "test3").Length); Assert.AreEqual(3, StringHelper.SplitMultilineText( "test1" + '\n' + "" + '\r' + "test2" + '\n' + "test3").Length); } // TestSplitMultilineText() /// /// Test get tab depth /// //[Test] public void TestGetTabDepth() { Assert.AreEqual(4, StringHelper.GetTabDepth("\t\t\t\tWhats up?")); } // TestGetTabDepth() /// /// Test is lowercase or uppercase letter /// //[Test] public void TestIsLowercaseOrUppercaseLetter() { Assert.AreEqual(true, IsLowercaseLetter('u')); Assert.AreEqual(true, IsUppercaseLetter('U')); // Well, numbers don't care if they upper or lower letters. Assert.AreEqual(true, IsLowercaseLetter('3')); Assert.AreEqual(true, IsUppercaseLetter('3')); } // TestIsLowercaseOrUppercaseLetter() /// /// Test split function name to word string /// //[Test] public void TestSplitFunctionNameToWordString() { Assert.AreEqual( "Make damage on unit", SplitFunctionNameToWordString("MakeDamageOnUnit")); Assert.AreEqual( "This is a test", SplitFunctionNameToWordString("ThisIsATest")); Assert.AreEqual( "Create TCP listener", SplitFunctionNameToWordString("CreateTCPListener")); Assert.AreEqual( "Lower letter test", SplitFunctionNameToWordString("lowerLetterTest")); Assert.AreEqual( "Test 3D render function", SplitFunctionNameToWordString("Test3DRenderFunction")); Assert.AreEqual( "Check if CD is inserted", SplitFunctionNameToWordString("CheckIfCDIsInserted")); // Test with text that already got spaces (we expect same stuff // returned) Assert.AreEqual( "Ha ha, I have spaces already", SplitFunctionNameToWordString("ha ha, I have spaces already")); // Test mixed text Assert.AreEqual( "Hey what means What the hell?", SplitFunctionNameToWordString("Hey what means WhatTheHell?")); // Test some crazy strings to test if we get no exceptions SplitFunctionNameToWordString("\0\t\n\raoeu\b\t"); SplitFunctionNameToWordString("@#%#@$ /// Test the GetExtension method. /// //[Test] public void TestGetExtension() { Assert.AreEqual("bmp", StringHelper.GetExtension("SomeBitmap.bmp")); Assert.AreEqual("xml", StringHelper.GetExtension("SomeApplication.config.xml")); } // TestGetExtension() #endregion } // class StringHelperTests */ #endif #endregion } // class StringHelper } // namespace XnaGraphicEngine.Helpers