Code Coverage Statistics for Source File
Newtonsoft.Json\Utilities\StringUtils.cs
Symbol Coverage: 24.49% (36 of 147)
Branch Coverage: 22.78% (18 of 79)
Cyclomatic Complexity Avg: 2.40 Max:6
Code Lines: 148
Symbol Coverage Trend
View:
L | V | Source |
---|---|---|
1 |
#region License |
|
2 |
// Copyright (c) 2007 James Newton-King |
|
3 |
// |
|
4 |
// Permission is hereby granted, free of charge, to any person |
|
5 |
// obtaining a copy of this software and associated documentation |
|
6 |
// files (the "Software"), to deal in the Software without |
|
7 |
// restriction, including without limitation the rights to use, |
|
8 |
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
9 |
// copies of the Software, and to permit persons to whom the |
|
10 |
// Software is furnished to do so, subject to the following |
|
11 |
// conditions: |
|
12 |
// |
|
13 |
// The above copyright notice and this permission notice shall be |
|
14 |
// included in all copies or substantial portions of the Software. |
|
15 |
// |
|
16 |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
17 |
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|
18 |
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
19 |
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|
20 |
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|
21 |
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
22 |
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|
23 |
// OTHER DEALINGS IN THE SOFTWARE. |
|
24 |
#endregion |
|
25 |
||
26 |
using System; |
|
27 |
using System.Collections.Generic; |
|
28 |
using System.IO; |
|
29 |
using System.Text; |
|
30 |
using System.Text.RegularExpressions; |
|
31 |
using System.Linq; |
|
32 |
using System.Globalization; |
|
33 |
||
34 |
namespace Newtonsoft.Json.Utilities |
|
35 |
{ |
|
36 |
internal static class StringUtils |
|
37 |
{ |
|
38 |
public const string CarriageReturnLineFeed = "\r\n"; |
|
39 |
public const string Empty = ""; |
|
40 |
public const char CarriageReturn = '\r'; |
|
41 |
public const char LineFeed = '\n'; |
|
42 |
public const char Tab = '\t'; |
|
43 |
||
44 |
//public static string FormatWith(this string format, params object[] args) |
|
45 |
//{ |
|
46 |
// return FormatWith(format, null, args); |
|
47 |
//} |
|
48 |
||
49 |
public static string FormatWith(this string format, IFormatProvider provider, params object[] args) |
|
50 |
{ |
|
51 |
209 |
ValidationUtils.ArgumentNotNull(format, "format");
|
52 |
||
53 |
209 |
return string.Format(provider, format, args);
|
54 |
209 |
}
|
55 |
||
56 |
/// <summary> |
|
57 |
/// Determines whether the string contains white space. |
|
58 |
/// </summary> |
|
59 |
/// <param name="s">The string to test for white space.</param> |
|
60 |
/// <returns> |
|
61 |
/// <c>true</c> if the string contains white space; otherwise, <c>false</c>. |
|
62 |
/// </returns> |
|
63 |
public static bool ContainsWhiteSpace(string s) |
|
64 |
{ |
|
65 |
0 |
if (s == null)
|
66 |
0 |
throw new ArgumentNullException("s");
|
67 |
||
68 |
0 |
for (int i = 0; i < s.Length; i++) |
69 |
{ |
|
70 |
0 |
if (char.IsWhiteSpace(s[i]))
|
71 |
0 |
return true;
|
72 |
} |
|
73 |
0 |
return false;
|
74 |
0 |
}
|
75 |
||
76 |
/// <summary> |
|
77 |
/// Determines whether the string is all white space. Empty string will return false. |
|
78 |
/// </summary> |
|
79 |
/// <param name="s">The string to test whether it is all white space.</param> |
|
80 |
/// <returns> |
|
81 |
/// <c>true</c> if the string is all white space; otherwise, <c>false</c>. |
|
82 |
/// </returns> |
|
83 |
public static bool IsWhiteSpace(string s) |
|
84 |
{ |
|
85 |
1 |
if (s == null)
|
86 |
0 |
throw new ArgumentNullException("s");
|
87 |
||
88 |
1 |
if (s.Length == 0)
|
89 |
0 |
return false;
|
90 |
||
91 |
1 |
for (int i = 0; i < s.Length; i++) |
92 |
{ |
|
93 |
2 |
if (!char.IsWhiteSpace(s[i]))
|
94 |
0 |
return false;
|
95 |
} |
|
96 |
||
97 |
1 |
return true;
|
98 |
1 |
}
|
99 |
||
100 |
/// <summary> |
|
101 |
/// Ensures the target string ends with the specified string. |
|
102 |
/// </summary> |
|
103 |
/// <param name="target">The target.</param> |
|
104 |
/// <param name="value">The value.</param> |
|
105 |
/// <returns>The target string with the value string at the end.</returns> |
|
106 |
public static string EnsureEndsWith(string target, string value) |
|
107 |
{ |
|
108 |
0 |
if (target == null)
|
109 |
0 |
throw new ArgumentNullException("target");
|
110 |
||
111 |
0 |
if (value == null)
|
112 |
0 |
throw new ArgumentNullException("value");
|
113 |
||
114 |
0 |
if (target.Length >= value.Length)
|
115 |
{ |
|
116 |
0 |
if (string.Compare(target, target.Length - value.Length, value, 0, value.Length, StringComparison.OrdinalIgnoreCase) ==
|
117 |
0 |
0)
|
118 |
0 |
return target;
|
119 |
||
120 |
0 |
string trimmedString = target.TrimEnd(null);
|
121 |
||
122 |
0 |
if (string.Compare(trimmedString, trimmedString.Length - value.Length, value, 0, value.Length,
|
123 |
0 |
StringComparison.OrdinalIgnoreCase) == 0)
|
124 |
0 |
return target;
|
125 |
} |
|
126 |
||
127 |
0 |
return target + value;
|
128 |
0 |
}
|
129 |
||
130 |
public static bool IsNullOrEmptyOrWhiteSpace(string s) |
|
131 |
{ |
|
132 |
0 |
if (string.IsNullOrEmpty(s))
|
133 |
0 |
return true;
|
134 |
0 |
else if (IsWhiteSpace(s))
|
135 |
0 |
return true;
|
136 |
else |
|
137 |
0 |
return false;
|
138 |
0 |
}
|
139 |
||
140 |
/// <summary> |
|
141 |
/// Perform an action if the string is not null or empty. |
|
142 |
/// </summary> |
|
143 |
/// <param name="value">The value.</param> |
|
144 |
/// <param name="action">The action to perform.</param> |
|
145 |
public static void IfNotNullOrEmpty(string value, Action<string> action) |
|
146 |
{ |
|
147 |
0 |
IfNotNullOrEmpty(value, action, null);
|
148 |
0 |
}
|
149 |
||
150 |
private static void IfNotNullOrEmpty(string value, Action<string> trueAction, Action<string> falseAction) |
|
151 |
{ |
|
152 |
0 |
if (!string.IsNullOrEmpty(value))
|
153 |
{ |
|
154 |
0 |
if (trueAction != null)
|
155 |
0 |
trueAction(value);
|
156 |
} |
|
157 |
else |
|
158 |
{ |
|
159 |
0 |
if (falseAction != null)
|
160 |
0 |
falseAction(value);
|
161 |
} |
|
162 |
0 |
}
|
163 |
||
164 |
/// <summary> |
|
165 |
/// Indents the specified string. |
|
166 |
/// </summary> |
|
167 |
/// <param name="s">The string to indent.</param> |
|
168 |
/// <param name="indentation">The number of characters to indent by.</param> |
|
169 |
/// <returns></returns> |
|
170 |
public static string Indent(string s, int indentation) |
|
171 |
{ |
|
172 |
0 |
return Indent(s, indentation, ' ');
|
173 |
0 |
}
|
174 |
||
175 |
/// <summary> |
|
176 |
/// Indents the specified string. |
|
177 |
/// </summary> |
|
178 |
/// <param name="s">The string to indent.</param> |
|
179 |
/// <param name="indentation">The number of characters to indent by.</param> |
|
180 |
/// <param name="indentChar">The indent character.</param> |
|
181 |
/// <returns></returns> |
|
182 |
public static string Indent(string s, int indentation, char indentChar) |
|
183 |
{ |
|
184 |
0 |
if (s == null)
|
185 |
0 |
throw new ArgumentNullException("s");
|
186 |
||
187 |
0 |
if (indentation <= 0)
|
188 |
0 |
throw new ArgumentException("Must be greater than zero.", "indentation");
|
189 |
||
190 |
0 |
StringReader sr = new StringReader(s);
|
191 |
0 |
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
|
192 |
||
193 |
0 |
ActionTextReaderLine(sr, sw, delegate(TextWriter tw, string line)
|
194 |
0 |
{
|
195 |
0 |
tw.Write(new string(indentChar, indentation));
|
196 |
0 |
tw.Write(line);
|
197 |
0 |
});
|
198 |
||
199 |
0 |
return sw.ToString();
|
200 |
0 |
}
|
201 |
||
202 |
private delegate void ActionLine(TextWriter textWriter, string line); |
|
203 |
||
204 |
private static void ActionTextReaderLine(TextReader textReader, TextWriter textWriter, ActionLine lineAction) |
|
205 |
{ |
|
206 |
string line; |
|
207 |
0 |
bool firstLine = true;
|
208 |
0 |
while ((line = textReader.ReadLine()) != null)
|
209 |
{ |
|
210 |
0 |
if (!firstLine)
|
211 |
0 |
textWriter.WriteLine();
|
212 |
else |
|
213 |
0 |
firstLine = false;
|
214 |
||
215 |
0 |
lineAction(textWriter, line);
|
216 |
} |
|
217 |
0 |
}
|
218 |
||
219 |
/// <summary> |
|
220 |
/// Numbers the lines. |
|
221 |
/// </summary> |
|
222 |
/// <param name="s">The string to number.</param> |
|
223 |
/// <returns></returns> |
|
224 |
public static string NumberLines(string s) |
|
225 |
{ |
|
226 |
0 |
if (s == null)
|
227 |
0 |
throw new ArgumentNullException("s");
|
228 |
||
229 |
0 |
StringReader sr = new StringReader(s);
|
230 |
0 |
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
|
231 |
||
232 |
0 |
int lineNumber = 1;
|
233 |
||
234 |
0 |
ActionTextReaderLine(sr, sw, delegate(TextWriter tw, string line)
|
235 |
0 |
{
|
236 |
0 |
tw.Write(lineNumber.ToString(CultureInfo.InvariantCulture).PadLeft(4));
|
237 |
0 |
tw.Write(". ");
|
238 |
0 |
tw.Write(line);
|
239 |
0 |
|
240 |
0 |
lineNumber++;
|
241 |
0 |
});
|
242 |
||
243 |
0 |
return sw.ToString();
|
244 |
0 |
}
|
245 |
||
246 |
/// <summary> |
|
247 |
/// Nulls an empty string. |
|
248 |
/// </summary> |
|
249 |
/// <param name="s">The string.</param> |
|
250 |
/// <returns>Null if the string was null, otherwise the string unchanged.</returns> |
|
251 |
public static string NullEmptyString(string s) |
|
252 |
{ |
|
253 |
4 |
return (string.IsNullOrEmpty(s)) ? null : s;
|
254 |
4 |
}
|
255 |
||
256 |
public static string ReplaceNewLines(string s, string replacement) |
|
257 |
{ |
|
258 |
0 |
StringReader sr = new StringReader(s);
|
259 |
0 |
StringBuilder sb = new StringBuilder();
|
260 |
||
261 |
0 |
bool first = true;
|
262 |
||
263 |
string line; |
|
264 |
0 |
while ((line = sr.ReadLine()) != null)
|
265 |
{ |
|
266 |
0 |
if (first)
|
267 |
0 |
first = false;
|
268 |
else |
|
269 |
0 |
sb.Append(replacement);
|
270 |
||
271 |
0 |
sb.Append(line);
|
272 |
} |
|
273 |
||
274 |
0 |
return sb.ToString();
|
275 |
0 |
}
|
276 |
||
277 |
public static string Truncate(string s, int maximumLength) |
|
278 |
{ |
|
279 |
0 |
return Truncate(s, maximumLength, "...");
|
280 |
0 |
}
|
281 |
||
282 |
public static string Truncate(string s, int maximumLength, string suffix) |
|
283 |
{ |
|
284 |
0 |
if (suffix == null)
|
285 |
0 |
throw new ArgumentNullException("suffix");
|
286 |
||
287 |
0 |
if (maximumLength <= 0)
|
288 |
0 |
throw new ArgumentException("Maximum length must be greater than zero.", "maximumLength");
|
289 |
||
290 |
0 |
int subStringLength = maximumLength - suffix.Length;
|
291 |
||
292 |
0 |
if (subStringLength <= 0)
|
293 |
0 |
throw new ArgumentException("Length of suffix string is greater or equal to maximumLength");
|
294 |
||
295 |
0 |
if (s != null && s.Length > maximumLength)
|
296 |
{ |
|
297 |
0 |
string truncatedString = s.Substring(0, subStringLength);
|
298 |
// incase the last character is a space |
|
299 |
0 |
truncatedString = truncatedString.Trim();
|
300 |
0 |
truncatedString += suffix;
|
301 |
||
302 |
0 |
return truncatedString;
|
303 |
} |
|
304 |
else |
|
305 |
{ |
|
306 |
0 |
return s;
|
307 |
} |
|
308 |
0 |
}
|
309 |
||
310 |
public static StringWriter CreateStringWriter(int capacity) |
|
311 |
{ |
|
312 |
38 |
StringBuilder sb = new StringBuilder(capacity);
|
313 |
38 |
StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
|
314 |
||
315 |
38 |
return sw;
|
316 |
38 |
}
|
317 |
||
318 |
public static int? GetLength(string value) |
|
319 |
{ |
|
320 |
30 |
if (value == null)
|
321 |
0 |
return null;
|
322 |
else |
|
323 |
30 |
return value.Length;
|
324 |
30 |
}
|
325 |
||
326 |
public static string ToCharAsUnicode(char c) |
|
327 |
{ |
|
328 |
5258 |
char h1 = MathUtils.IntToHex((c >> 12) & '\x000f');
|
329 |
5258 |
char h2 = MathUtils.IntToHex((c >> 8) & '\x000f');
|
330 |
5258 |
char h3 = MathUtils.IntToHex((c >> 4) & '\x000f');
|
331 |
5258 |
char h4 = MathUtils.IntToHex(c & '\x000f');
|
332 |
||
333 |
5258 |
return new string(new[] { '\\', 'u', h1, h2, h3, h4 });
|
334 |
5258 |
}
|
335 |
||
336 |
public static void WriteCharAsUnicode(TextWriter writer, char c) |
|
337 |
{ |
|
338 |
0 |
ValidationUtils.ArgumentNotNull(writer, "writer");
|
339 |
||
340 |
0 |
char h1 = MathUtils.IntToHex((c >> 12) & '\x000f');
|
341 |
0 |
char h2 = MathUtils.IntToHex((c >> 8) & '\x000f');
|
342 |
0 |
char h3 = MathUtils.IntToHex((c >> 4) & '\x000f');
|
343 |
0 |
char h4 = MathUtils.IntToHex(c & '\x000f');
|
344 |
||
345 |
0 |
writer.Write('\\');
|
346 |
0 |
writer.Write('u');
|
347 |
0 |
writer.Write(h1);
|
348 |
0 |
writer.Write(h2);
|
349 |
0 |
writer.Write(h3);
|
350 |
0 |
writer.Write(h4);
|
351 |
0 |
}
|
352 |
||
353 |
public static TSource ForgivingCaseSensitiveFind<TSource>(this IEnumerable<TSource> source, Func<TSource, string> valueSelector, string testValue) |
|
354 |
{ |
|
355 |
28 |
if (source == null)
|
356 |
0 |
throw new ArgumentNullException("source");
|
357 |
28 |
if (valueSelector == null)
|
358 |
0 |
throw new ArgumentNullException("valueSelector");
|
359 |
||
360 |
28 |
var caseInsensitiveResults = source.Where(s => string.Compare(valueSelector(s), testValue, StringComparison.OrdinalIgnoreCase) == 0);
|
361 |
28 |
if (caseInsensitiveResults.Count() <= 1)
|
362 |
{ |
|
363 |
26 |
return caseInsensitiveResults.SingleOrDefault();
|
364 |
} |
|
365 |
else |
|
366 |
{ |
|
367 |
// multiple results returned. now filter using case sensitivity |
|
368 |
2 |
var caseSensitiveResults = source.Where(s => string.Compare(valueSelector(s), testValue, StringComparison.Ordinal) == 0);
|
369 |
2 |
return caseSensitiveResults.SingleOrDefault();
|
370 |
} |
|
371 |
28 |
}
|
372 |
} |
|
373 |
} |