[sgen] Reenable gc-altstack test
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Dynamic / Utils / StringUtils.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
6  * copy of the license can be found in the License.html file at the root of this distribution. If 
7  * you cannot locate the  Apache License, Version 2.0, please send an email to 
8  * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
9  * by the terms of the Apache License, Version 2.0.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 using System;
17 using System.Collections.Generic;
18 using System.Globalization;
19 using System.Text;
20
21 namespace Microsoft.Scripting.Utils {
22     public static class StringUtils {
23
24         public static Encoding DefaultEncoding {
25             get {
26 #if FEATURE_ENCODING
27                 return Encoding.Default;
28 #else
29                 return Encoding.UTF8;
30 #endif
31             }
32         }
33
34         public static string GetSuffix(string str, char separator, bool includeSeparator) {
35             ContractUtils.RequiresNotNull(str, "str");
36             int last = str.LastIndexOf(separator);
37             return (last != -1) ? str.Substring(includeSeparator ? last : last + 1) : null;
38         }
39
40         public static string GetLongestPrefix(string str, char separator, bool includeSeparator) {
41             ContractUtils.RequiresNotNull(str, "str");
42             int last = str.LastIndexOf(separator);
43             return (last != -1) ? str.Substring(0, (includeSeparator || last == 0) ? last : last - 1) : null;
44         }
45
46         public static int CountOf(string str, char c) {
47             if (System.String.IsNullOrEmpty(str)) return 0;
48
49             int result = 0;
50             for (int i = 0; i < str.Length; i++) {
51                 if (c == str[i]) {
52                     result++;
53                 }
54             }
55             return result;
56         }
57
58         public static string[] Split(string str, string separator, int maxComponents, StringSplitOptions options) {
59             ContractUtils.RequiresNotNull(str, "str");
60 #if SILVERLIGHT || WP75
61             if (string.IsNullOrEmpty(separator)) throw new ArgumentNullException("separator");
62
63             bool keep_empty = (options & StringSplitOptions.RemoveEmptyEntries) != StringSplitOptions.RemoveEmptyEntries;
64
65             List<string> result = new List<string>(maxComponents == Int32.MaxValue ? 1 : maxComponents + 1);
66
67             int i = 0;
68             int next;
69             while (maxComponents > 1 && i < str.Length && (next = str.IndexOf(separator, i)) != -1) {
70
71                 if (next > i || keep_empty) {
72                     result.Add(str.Substring(i, next - i));
73                     maxComponents--;
74                 }
75
76                 i = next + separator.Length;
77             }
78
79             if (i < str.Length || keep_empty) {
80                 result.Add(str.Substring(i));
81             }
82
83             return result.ToArray();
84 #else
85             return str.Split(new string[] { separator }, maxComponents, options);
86 #endif
87         }
88
89         public static string[] Split(string str, char[] separators, int maxComponents, StringSplitOptions options) {
90             ContractUtils.RequiresNotNull(str, "str");
91 #if SILVERLIGHT || WP75
92             if (separators == null) return SplitOnWhiteSpace(str, maxComponents, options);
93
94             bool keep_empty = (options & StringSplitOptions.RemoveEmptyEntries) != StringSplitOptions.RemoveEmptyEntries;
95
96             List<string> result = new List<string>(maxComponents == Int32.MaxValue ? 1 : maxComponents + 1);
97
98             int i = 0;
99             int next;
100             while (maxComponents > 1 && i < str.Length && (next = str.IndexOfAny(separators, i)) != -1) {
101
102                 if (next > i || keep_empty) {
103                     result.Add(str.Substring(i, next - i));
104                     maxComponents--;
105                 }
106
107                 i = next + 1;
108             }
109
110             if (i < str.Length || keep_empty) {
111                 result.Add(str.Substring(i));
112             }
113
114             return result.ToArray();
115 #else
116             return str.Split(separators, maxComponents, options);
117 #endif
118         }
119
120 #if SILVERLIGHT|| WP75
121         public static string[] SplitOnWhiteSpace(string str, int maxComponents, StringSplitOptions options) {
122             ContractUtils.RequiresNotNull(str, "str");
123
124             bool keep_empty = (options & StringSplitOptions.RemoveEmptyEntries) != StringSplitOptions.RemoveEmptyEntries;
125
126             List<string> result = new List<string>(maxComponents == Int32.MaxValue ? 1 : maxComponents + 1);
127
128             int i = 0;
129             int next;
130             while (maxComponents > 1 && i < str.Length && (next = IndexOfWhiteSpace(str, i)) != -1) {
131
132                 if (next > i || keep_empty) {
133                     result.Add(str.Substring(i, next - i));
134                     maxComponents--;
135                 }
136
137                 i = next + 1;
138             }
139
140             if (i < str.Length || keep_empty) {
141                 result.Add(str.Substring(i));
142             }
143
144             return result.ToArray();
145         }
146
147         public static int IndexOfWhiteSpace(string str, int start) {
148             ContractUtils.RequiresNotNull(str, "str");
149             if (start < 0 || start > str.Length) throw new ArgumentOutOfRangeException("start");
150
151             while (start < str.Length && !Char.IsWhiteSpace(str[start])) start++;
152
153             return (start == str.Length) ? -1 : start;
154         }
155 #endif
156
157         /// <summary>
158         /// Splits text and optionally indents first lines - breaks along words, not characters.
159         /// </summary>
160         public static string SplitWords(string text, bool indentFirst, int lineWidth) {
161             ContractUtils.RequiresNotNull(text, "text");
162
163             const string indent = "    ";
164
165             if (text.Length <= lineWidth || lineWidth <= 0) {
166                 if (indentFirst) return indent + text;
167                 return text;
168             }
169
170             StringBuilder res = new StringBuilder();
171             int start = 0, len = lineWidth;
172             while (start != text.Length) {
173                 if (len >= lineWidth) {
174                     // find last space to break on
175                     while (len != 0 && !Char.IsWhiteSpace(text[start + len - 1]))
176                         len--;
177                 }
178
179                 if (res.Length != 0) res.Append(' ');
180                 if (indentFirst || res.Length != 0) res.Append(indent);
181
182                 if (len == 0) {
183                     int copying = System.Math.Min(lineWidth, text.Length - start);
184                     res.Append(text, start, copying);
185                     start += copying;
186                 } else {
187                     res.Append(text, start, len);
188                     start += len;
189                 }
190                 res.AppendLine();
191                 len = System.Math.Min(lineWidth, text.Length - start);
192             }
193             return res.ToString();
194         }
195
196         public static string AddSlashes(string str) {
197             ContractUtils.RequiresNotNull(str, "str");
198
199             // TODO: optimize
200             StringBuilder result = new StringBuilder(str.Length);
201             for (int i = 0; i < str.Length; i++) {
202                 switch (str[i]) {
203                     case '\a': result.Append("\\a"); break;
204                     case '\b': result.Append("\\b"); break;
205                     case '\f': result.Append("\\f"); break;
206                     case '\n': result.Append("\\n"); break;
207                     case '\r': result.Append("\\r"); break;
208                     case '\t': result.Append("\\t"); break;
209                     case '\v': result.Append("\\v"); break;
210                     default: result.Append(str[i]); break;
211                 }
212             }
213
214             return result.ToString();
215         }
216
217         public static bool TryParseDouble(string s, NumberStyles style, IFormatProvider provider, out double result) {
218             return Double.TryParse(s, style, provider, out result);
219         }
220
221         public static bool TryParseInt32(string s, out int result) {
222             return Int32.TryParse(s, out result);
223         }
224
225         public static bool TryParseDateTimeExact(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result) {
226             return DateTime.TryParseExact(s, format, provider, style, out result);
227         }
228
229         public static bool TryParseDateTimeExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result) {
230             return DateTime.TryParseExact(s, formats, provider, style, out result);
231         }
232
233         public static bool TryParseDate(string s, IFormatProvider provider, DateTimeStyles style, out DateTime result) {
234             return DateTime.TryParse(s, provider, style, out result);
235         }
236
237 #if !WIN8
238 #if SILVERLIGHT || WP75
239         private static Dictionary<string, CultureInfo> _cultureInfoCache = new Dictionary<string, CultureInfo>();
240 #endif
241
242         // Aims to be equivalent to Culture.GetCultureInfo for Silverlight
243         public static CultureInfo GetCultureInfo(string name) {
244 #if SILVERLIGHT || WP75
245             lock (_cultureInfoCache) {
246                 CultureInfo result;
247                 if (_cultureInfoCache.TryGetValue(name, out result)) {
248                     return result;
249                 }
250                 _cultureInfoCache[name] = result = new CultureInfo(name);
251                 return result;
252             }
253 #else
254             return CultureInfo.GetCultureInfo(name);
255 #endif
256         }
257 #endif
258         // Like string.Split, but enumerates
259         public static IEnumerable<string> Split(string str, string sep) {
260             int start = 0, end;
261             while ((end = str.IndexOf(sep, start)) != -1) {
262                 yield return str.Substring(start, end - start);
263
264                 start = end + sep.Length;
265             }
266             yield return str.Substring(start);
267         }
268     }
269 }