PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/3.0/Microsoft.Tools.CodeRunner/StringUtility.cs

#
C# | 243 lines | 114 code | 32 blank | 97 comment | 25 complexity | 309a85f043dac4e19b28edffa4ceb690 MD5 | raw file
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Text;
  7. using System.Globalization;
  8. namespace Microsoft.Tools.CodeRunner
  9. {
  10. /// <summary>
  11. /// Flags for TaggedString operations
  12. /// </summary>
  13. [Flags]
  14. public enum TaggedStringOptions
  15. {
  16. /// <summary>
  17. /// Search case insensitively and leave unknown tags in the output
  18. /// </summary>
  19. Default = 0x00,
  20. /// <summary>
  21. /// Tags that are not found in the dictionary are replaced with an empty string
  22. /// instead of being left in the output.
  23. /// </summary>
  24. RemoveUnknownTags = 0x01
  25. }
  26. /// <summary>
  27. /// Groups a set of useful <see cref="string" /> manipulation and validation
  28. /// methods.
  29. /// </summary>
  30. public static class StringUtility
  31. {
  32. /// <summary>
  33. /// Converts an empty string ("") to <see langword="null" />.
  34. /// </summary>
  35. /// <param name="value">The value to convert.</param>
  36. /// <returns>
  37. /// <see langword="null" /> if <paramref name="value" /> is an empty
  38. /// string ("") or <see langword="null" />; otherwise, <paramref name="value" />.
  39. /// </returns>
  40. public static string ConvertEmptyToNull(string value)
  41. {
  42. if (!String.IsNullOrEmpty(value))
  43. {
  44. return value;
  45. }
  46. return null;
  47. }
  48. /// <summary>
  49. /// Converts <see langword="null" /> to an empty string.
  50. /// </summary>
  51. /// <param name="value">The value to convert.</param>
  52. /// <returns>
  53. /// An empty string if <paramref name="value" /> is <see langword="null" />;
  54. /// otherwise, <paramref name="value" />.
  55. /// </returns>
  56. public static string ConvertNullToEmpty(string value)
  57. {
  58. if (value == null)
  59. {
  60. return string.Empty;
  61. }
  62. return value;
  63. }
  64. /// <summary>
  65. /// Concatenates a specified separator <see cref="string" /> between each
  66. /// element of a specified list, yielding a single concatenated string.
  67. /// </summary>
  68. /// <param name="separator">A <see cref="string" />.</param>
  69. /// <param name="value">A string collection.</param>
  70. /// <returns>
  71. /// A <see cref="string" /> consisting of the elements of <paramref name="value" />
  72. /// interspersed with the separator string.
  73. /// </returns>
  74. /// <remarks>
  75. /// <para>
  76. /// For example if <paramref name="separator" /> is ", " and the elements
  77. /// of <paramref name="value" /> are "apple", "orange", "grape", and "pear",
  78. /// the method returns "apple, orange, grape, pear".
  79. /// </para>
  80. /// <para>
  81. /// If <paramref name="separator" /> is <see langword="null" />, an empty
  82. /// string (<see cref="string.Empty" />) is used instead.
  83. /// </para>
  84. /// </remarks>
  85. public static string Join(string separator, List<string> value)
  86. {
  87. if (value == null)
  88. {
  89. throw new ArgumentNullException("value");
  90. }
  91. if (separator == null)
  92. {
  93. separator = string.Empty;
  94. }
  95. // create with size equal to number of elements in collection
  96. string[] elements = new string[value.Count];
  97. // copy elements in collection to array
  98. value.CopyTo(elements, 0);
  99. // concatenate specified separator between each elements
  100. return string.Join(separator, elements);
  101. }
  102. /// <summary>
  103. /// Breaks a string on word boundaries, to the given <paramref name="lineLength"/>.
  104. /// Only space characters are considered when breaking up lines.
  105. /// Embedded <see cref="Environment.NewLine"/> sequences will break a line and are not included in the
  106. /// resulting output.
  107. /// Each line is broken after the first whitespace after the last word on the line, so all space
  108. /// characters are preserved in the resulting output.
  109. /// </summary>
  110. /// <param name="text">The text to break up.</param>
  111. /// <param name="lineLength">The maximum length of a line</param>
  112. /// <returns>An array of strings no longer than the given line length</returns>
  113. public static string[] WordWrap(string text, int lineLength)
  114. {
  115. List<string> lines = new List<string>();
  116. // First, split the string up on any newline boundaries
  117. lines.AddRange(text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None));
  118. // Then further sub-divide the lines on word break boundaries
  119. int i = 0;
  120. while (i < lines.Count)
  121. {
  122. while (lines[i].Length > lineLength)
  123. {
  124. string line = lines[i];
  125. int e = lineLength - 1;
  126. // If we hit a space, break right here
  127. if (line[e] != ' ')
  128. {
  129. while (!Char.IsWhiteSpace(line[e]) && e > 0)
  130. e--;
  131. // We couldn't find any whitespace, so just use truncate to the end of the line
  132. if (e == 0)
  133. e = lineLength - 1;
  134. }
  135. lines[i] = line.Substring(e + 1);
  136. lines.Insert(i, line.Substring(0, e + 1));
  137. i++;
  138. }
  139. i++;
  140. }
  141. return lines.ToArray();
  142. }
  143. /// <summary>Format a string using the invariant culture. Use for persisted strings not returned to user.
  144. /// </summary>
  145. /// <see>string.Format</see> for argument format.
  146. public static string InvariantFormat(string format, params object[] args)
  147. {
  148. return string.Format(CultureInfo.InvariantCulture, format, args);
  149. }
  150. /// <summary> Format a string using the current culture. Use for strings returned to user.</summary>
  151. /// <see>string.Format</see> for argument format.
  152. public static string CultureFormat(string format, params object[] args)
  153. {
  154. return string.Format(CultureInfo.CurrentCulture, format, args);
  155. }
  156. /// <summary>
  157. /// This method searches for each occurrence of a tagged variable in <c>source</c> and
  158. /// replaces it with the value from the a dictionary <c>subs</c>. Comparisons are done case
  159. /// insensitively.
  160. /// </summary>
  161. /// <param name="source">String containing tagged entities</param>
  162. /// <param name="tagPrefix">The tag prefix</param>
  163. /// <param name="tagSuffix">The tag suffix</param>
  164. /// <param name="dict">A dictionary of tag values</param>
  165. /// <returns>A string with all tags replaced</returns>
  166. public static string ReplaceTags(string source, string tagPrefix, string tagSuffix, IDictionary dict)
  167. {
  168. return ReplaceTags(source, tagPrefix, tagSuffix, dict, TaggedStringOptions.Default);
  169. }
  170. /// <summary>
  171. /// This method searches for each occurrence of a tagged variable in a string and
  172. /// replaces it with the value from the a dictionary. Comparisons are done case
  173. /// insensitively.
  174. /// </summary>
  175. /// <param name="source">String containing tagged entities</param>
  176. /// <param name="dict">A dictionary of tag values</param>
  177. /// <param name="tagPrefix">The tag prefix</param>
  178. /// <param name="tagSuffix">The tag suffix</param>
  179. /// <param name="flags"><see cref="TaggedStringOptions"/> for the replace operation</param>
  180. /// <returns>A string with all tags replaced</returns>
  181. public static string ReplaceTags(string source, string tagPrefix, string tagSuffix, IDictionary dict, TaggedStringOptions flags)
  182. {
  183. if (string.IsNullOrEmpty(source))
  184. return source;
  185. StringBuilder sb = new StringBuilder(source);
  186. for (int index = source.Length - 1; index != -1; )
  187. {
  188. int tagEnd = source.LastIndexOf(tagSuffix, index, StringComparison.CurrentCulture);
  189. if (tagEnd <= 0)
  190. break;
  191. int tagStart = source.LastIndexOf(tagPrefix, tagEnd - 1, StringComparison.CurrentCulture);
  192. if (tagStart < 0)
  193. break;
  194. // find a key; use the case sensitivity specified by call
  195. string key = source.Substring(tagStart + tagPrefix.Length, tagEnd - tagStart - tagPrefix.Length);
  196. string val = dict[key] as string;
  197. if (val != null)
  198. {
  199. sb.Remove(tagStart, tagEnd + tagSuffix.Length - tagStart);
  200. sb.Insert(tagStart, val);
  201. }
  202. else if ((flags & TaggedStringOptions.RemoveUnknownTags) != 0)
  203. {
  204. sb.Remove(tagStart, tagEnd + tagSuffix.Length - tagStart);
  205. }
  206. index = tagStart - 1;
  207. }
  208. return sb.ToString();
  209. }
  210. }
  211. }