SHOW:
|
|
- or go back to the newest paste.
1 | public sealed class ASCIIString : IEnumerable<ASCIIChar>, IComparable<ASCIIString> | |
2 | { | |
3 | public static readonly ASCIIString Empty; | |
4 | ||
5 | static ASCIIString() | |
6 | { | |
7 | Empty = new ASCIIString(new byte[] { }); | |
8 | } | |
9 | ||
10 | public static implicit operator String(ASCIIString value) | |
11 | { | |
12 | return value.ToString(); | |
13 | } | |
14 | public static ASCIIString operator +(ASCIIString strA, ASCIIString strB) | |
15 | { | |
16 | return ASCIIString.Concat(strA, strB); | |
17 | } | |
18 | public static ASCIIString operator +(ASCIIString str, ASCIIChar chr) | |
19 | { | |
20 | if (str == null) throw new ArgumentNullException("str"); | |
21 | ||
22 | int totalBytes = str.data.Length + 1; | |
23 | ||
24 | byte[] data = new byte[totalBytes]; | |
25 | ||
26 | Buffer.BlockCopy(str.data, 0, data, 0, str.data.Length); | |
27 | data[totalBytes - 1] = chr.ToByte(); | |
28 | ||
29 | return new ASCIIString(data); | |
30 | } | |
31 | public static bool operator ==(ASCIIString strA, ASCIIString strB) | |
32 | { | |
33 | return ASCIIString.Compare(strA, strB) == 0; | |
34 | } | |
35 | public static bool operator !=(ASCIIString strA, ASCIIString strB) | |
36 | { | |
37 | return ASCIIString.Compare(strA, strB) != 0; | |
38 | } | |
39 | ||
40 | public static int Compare(ASCIIString strA, ASCIIString strB) | |
41 | { | |
42 | return Compare(strA, strB, false); | |
43 | } | |
44 | public static int Compare(ASCIIString strA, ASCIIString strB, bool ignoreCase) | |
45 | { | |
46 | if (strA == null) throw new ArgumentNullException("strA"); | |
47 | if (strB == null) throw new ArgumentNullException("strB"); | |
48 | ||
49 | return SafeCompare(strA, 0, strB, 0, Math.Max(strA.data.Length, strB.data.Length), ignoreCase); | |
50 | } | |
51 | public static int Compare(ASCIIString strA, int indexA, ASCIIString strB, int indexB, int length) | |
52 | { | |
53 | return Compare(strA, indexA, strB, indexB, length, false); | |
54 | } | |
55 | public static int Compare(ASCIIString strA, int indexA, ASCIIString strB, int indexB, int length, bool ignoreCase) | |
56 | { | |
57 | if (strA == null) throw new ArgumentNullException("strA"); | |
58 | if (strB == null) throw new ArgumentNullException("strB"); | |
59 | if (indexA < 0 || indexA > strA.data.Length) throw new ArgumentOutOfRangeException("indexA"); | |
60 | if (indexB < 0 || indexB > strB.data.Length) throw new ArgumentOutOfRangeException("indexB"); | |
61 | if (length < 0 || indexA + length > strA.data.Length || indexB + length > strB.data.Length) throw new ArgumentOutOfRangeException("length"); | |
62 | ||
63 | return SafeCompare(strA, indexA, strB, indexB, length, ignoreCase); | |
64 | } | |
65 | private static int SafeCompare(ASCIIString strA, int indexA, ASCIIString strB, int indexB, int length, bool ignoreCase) | |
66 | { | |
67 | for (int i = 0; i < length; i++) | |
68 | { | |
69 | int iA = i + indexA; | |
70 | int iB = i + indexB; | |
71 | ||
72 | if (iA == strA.data.Length && iB == strB.data.Length) return 0; | |
73 | if (iA == strA.data.Length) return -1; | |
74 | if (iB == strB.data.Length) return 1; | |
75 | ||
76 | byte byteA = strA.data[iA]; | |
77 | byte byteB = strB.data[iB]; | |
78 | ||
79 | if (ignoreCase) | |
80 | { | |
81 | byteA = ASCIIChar.ToLower(byteA); | |
82 | byteB = ASCIIChar.ToLower(byteB); | |
83 | } | |
84 | ||
85 | if (byteA < byteB) return -1; | |
86 | if (byteB < byteA) return 1; | |
87 | } | |
88 | ||
89 | return 0; | |
90 | } | |
91 | public static ASCIIString Copy(ASCIIString value) | |
92 | { | |
93 | byte[] data = new byte[value.data.Length]; | |
94 | Buffer.BlockCopy(value.data, 0, data, 0, value.data.Length); | |
95 | return new ASCIIString(data); | |
96 | } | |
97 | public static ASCIIString Concat(params ASCIIString[] values) | |
98 | { | |
99 | return Concat((IEnumerable<ASCIIString>)values); | |
100 | } | |
101 | public static ASCIIString Concat(IEnumerable<ASCIIString> values) | |
102 | { | |
103 | if (values == null) throw new ArgumentNullException("values"); | |
104 | ||
105 | int totalBytes = 0; | |
106 | int offset = 0; | |
107 | ||
108 | foreach (ASCIIString asciiString in values) | |
109 | { | |
110 | if (asciiString == null) continue; | |
111 | totalBytes += asciiString.data.Length; | |
112 | } | |
113 | ||
114 | byte[] data = new byte[totalBytes]; | |
115 | ||
116 | foreach (ASCIIString asciiString in values) | |
117 | { | |
118 | if (asciiString == null) continue; | |
119 | Buffer.BlockCopy(asciiString.data, 0, data, offset, asciiString.data.Length); | |
120 | offset += asciiString.data.Length; | |
121 | } | |
122 | ||
123 | return new ASCIIString(data); | |
124 | } | |
125 | public static bool IsNullOrEmpty(ASCIIString value) | |
126 | { | |
127 | return value == null || value.data.Length == 0; | |
128 | } | |
129 | public static bool IsNullOrWhitespace(ASCIIString value) | |
130 | { | |
131 | if (value == null || value.data.Length == 0) | |
132 | { | |
133 | return true; | |
134 | } | |
135 | ||
136 | foreach (byte b in value.data) | |
137 | { | |
138 | if (!ASCIIChar.IsWhitespace(b)) | |
139 | { | |
140 | return false; | |
141 | } | |
142 | } | |
143 | ||
144 | return true; | |
145 | } | |
146 | public static ASCIIString Join(ASCIIString seperator, params ASCIIString[] values) | |
147 | { | |
148 | return Join(seperator, (IEnumerable<ASCIIString>)values); | |
149 | } | |
150 | public static ASCIIString Join(ASCIIString seperator, IEnumerable<ASCIIString> values) | |
151 | { | |
152 | if (seperator == null) throw new ArgumentNullException("seperator"); | |
153 | if (values == null) throw new ArgumentNullException("values"); | |
154 | ||
155 | int totalBytes = 0; | |
156 | int offset = 0; | |
157 | ||
158 | foreach (ASCIIString asciiString in values) | |
159 | { | |
160 | if (asciiString == null) continue; | |
161 | totalBytes += asciiString.data.Length; | |
162 | totalBytes += seperator.data.Length; | |
163 | } | |
164 | ||
165 | if (totalBytes > 0) totalBytes -= seperator.data.Length; | |
166 | ||
167 | byte[] data = new byte[totalBytes]; | |
168 | ||
169 | foreach (ASCIIString asciiString in values) | |
170 | { | |
171 | if (asciiString == null) continue; | |
172 | ||
173 | Buffer.BlockCopy(asciiString.data, 0, data, offset, asciiString.data.Length); | |
174 | offset += asciiString.data.Length; | |
175 | ||
176 | if (offset < totalBytes) | |
177 | { | |
178 | Buffer.BlockCopy(seperator.data, 0, data, offset, seperator.data.Length); | |
179 | offset += seperator.data.Length; | |
180 | } | |
181 | } | |
182 | ||
183 | return new ASCIIString(data); | |
184 | } | |
185 | public static ASCIIString Parse(string value) | |
186 | { | |
187 | if (value == null) throw new ArgumentNullException("value"); | |
188 | ||
189 | return new ASCIIString(Encoding.ASCII.GetBytes(value)); | |
190 | } | |
191 | ||
192 | private readonly byte[] data; | |
193 | ||
194 | public int Length | |
195 | { | |
196 | get | |
197 | { | |
198 | return data.Length; | |
199 | } | |
200 | } | |
201 | ||
202 | public ASCIIString(byte[] data, int startIndex, int length) | |
203 | { | |
204 | if (data == null) throw new ArgumentNullException("data"); | |
205 | if (startIndex < 0 || startIndex > data.Length) throw new ArgumentOutOfRangeException("startIndex"); | |
206 | if (length < 0 || startIndex + length > data.Length) throw new ArgumentOutOfRangeException("length"); | |
207 | ||
208 | foreach (byte b in data) | |
209 | { | |
210 | if (!ASCIIChar.ValidateByte(b)) | |
211 | { | |
212 | throw new ArgumentOutOfRangeException("data"); | |
213 | } | |
214 | } | |
215 | ||
216 | this.data = new byte[length]; | |
217 | Buffer.BlockCopy(data, startIndex, this.data, 0, length); | |
218 | } | |
219 | private ASCIIString(byte[] data) | |
220 | { | |
221 | this.data = data; | |
222 | } | |
223 | ||
224 | public ASCIIChar this[int index] | |
225 | { | |
226 | get | |
227 | { | |
228 | return new ASCIIChar(this.data[index]); | |
229 | } | |
230 | } | |
231 | ||
232 | public ASCIIString Clone() | |
233 | { | |
234 | return this; | |
235 | } | |
236 | public int CompareTo(ASCIIString value) | |
237 | { | |
238 | if (value == null) throw new ArgumentNullException("value"); | |
239 | return ASCIIString.Compare(this, value); | |
240 | } | |
241 | public bool Contains(ASCIIString value) | |
242 | { | |
243 | if (value == null) throw new ArgumentNullException("value"); | |
244 | return this.IndexOf(value) >= 0; | |
245 | } | |
246 | public bool Contains(ASCIIChar value) | |
247 | { | |
248 | byte valueByte = value.ToByte(); | |
249 | ||
250 | foreach (byte b in this.data) | |
251 | { | |
252 | if (b.Equals(valueByte)) | |
253 | { | |
254 | return true; | |
255 | } | |
256 | } | |
257 | ||
258 | return false; | |
259 | } | |
260 | public bool EndsWith(ASCIIString value) | |
261 | { | |
262 | return this.EndsWith(value, false); | |
263 | } | |
264 | public bool EndsWith(ASCIIString value, bool ignoreCase) | |
265 | { | |
266 | if (value == null) throw new ArgumentNullException("value"); | |
267 | return ASCIIString.Compare(this, this.data.Length - value.data.Length, value, 0, value.Length, ignoreCase) == 0; | |
268 | } | |
269 | public override bool Equals(object obj) | |
270 | { | |
271 | if (obj is ASCIIString) | |
272 | { | |
273 | return base.Equals((ASCIIString)obj); | |
274 | } | |
275 | else | |
276 | { | |
277 | return false; | |
278 | } | |
279 | } | |
280 | public bool Equals(ASCIIString value) | |
281 | { | |
282 | return this.CompareTo(value) == 0; | |
283 | } | |
284 | public override int GetHashCode() | |
285 | { | |
286 | return base.GetHashCode(); | |
287 | } | |
288 | public int IndexOf(ASCIIString value) | |
289 | { | |
290 | return this.IndexOf(value, 0, this.Length, false); | |
291 | } | |
292 | public int IndexOf(ASCIIString value, bool ignoreCase) | |
293 | { | |
294 | return this.IndexOf(value, 0, this.Length, ignoreCase); | |
295 | } | |
296 | public int IndexOf(ASCIIString value, int startIndex) | |
297 | { | |
298 | return this.IndexOf(value, startIndex, this.Length - startIndex, false); | |
299 | } | |
300 | public int IndexOf(ASCIIString value, int startIndex, bool ignoreCase) | |
301 | { | |
302 | return this.IndexOf(value, startIndex, this.Length - startIndex, ignoreCase); | |
303 | } | |
304 | public int IndexOf(ASCIIString value, int startIndex, int count) | |
305 | { | |
306 | return this.IndexOf(value, startIndex, count, false); | |
307 | } | |
308 | public int IndexOf(ASCIIString value, int startIndex, int count, bool ignoreCase) | |
309 | { | |
310 | if (value == null) throw new ArgumentNullException("value"); | |
311 | if (startIndex < 0 || startIndex > this.data.Length) throw new ArgumentOutOfRangeException("startIndex"); | |
312 | if (count < 0 || startIndex + count > this.data.Length || count < value.data.Length) throw new ArgumentOutOfRangeException("count"); | |
313 | ||
314 | int charactersFound = 0; | |
315 | ||
316 | for (int i = startIndex; i < startIndex + count; i++) | |
317 | { | |
318 | if (i + (value.data.Length - charactersFound) > this.data.Length) return -1; | |
319 | ||
320 | byte byteA = this.data[i]; | |
321 | byte byteB = value.data[charactersFound]; | |
322 | ||
323 | if (ignoreCase) | |
324 | { | |
325 | byteA = ASCIIChar.ToLower(byteA); | |
326 | byteB = ASCIIChar.ToLower(byteB); | |
327 | } | |
328 | ||
329 | if (byteA == byteB) charactersFound++; | |
330 | else charactersFound = 0; | |
331 | ||
332 | if (charactersFound == value.data.Length) return (i - charactersFound + 1); | |
333 | } | |
334 | ||
335 | return -1; | |
336 | } | |
337 | public int IndexOfAny(params ASCIIChar[] values) | |
338 | { | |
339 | return this.IndexOfAny(values, 0, this.data.Length, false); | |
340 | } | |
341 | public int IndexOfAny(IEnumerable<ASCIIChar> values) | |
342 | { | |
343 | return this.IndexOfAny(values, 0, this.data.Length, false); | |
344 | } | |
345 | public int IndexOfAny(IEnumerable<ASCIIChar> values, bool ignoreCase) | |
346 | { | |
347 | return this.IndexOfAny(values, 0, this.data.Length, ignoreCase); | |
348 | } | |
349 | public int IndexOfAny(IEnumerable<ASCIIChar> values, int startIndex) | |
350 | { | |
351 | return this.IndexOfAny(values, startIndex, this.data.Length - startIndex, false); | |
352 | } | |
353 | public int IndexOfAny(IEnumerable<ASCIIChar> values, int startIndex, bool ignoreCase) | |
354 | { | |
355 | return this.IndexOfAny(values, startIndex, this.data.Length - startIndex, ignoreCase); | |
356 | } | |
357 | public int IndexOfAny(IEnumerable<ASCIIChar> values, int startIndex, int count) | |
358 | { | |
359 | return this.IndexOfAny(values, startIndex, count, false); | |
360 | } | |
361 | public int IndexOfAny(IEnumerable<ASCIIChar> values, int startIndex, int count, bool ignoreCase) | |
362 | { | |
363 | if (values == null) throw new ArgumentNullException("values"); | |
364 | if (startIndex < 0 || startIndex > this.data.Length) throw new ArgumentOutOfRangeException("startIndex"); | |
365 | if (count < 0 || startIndex + count > this.data.Length) throw new ArgumentOutOfRangeException("count"); | |
366 | ||
367 | List<byte> valueBytes = new List<byte>(); | |
368 | ||
369 | foreach (ASCIIChar c in values) | |
370 | { | |
371 | if (ignoreCase) valueBytes.Add(ASCIIChar.ToLower(c.ToByte())); | |
372 | else valueBytes.Add(c.ToByte()); | |
373 | } | |
374 | ||
375 | for (int i = 0; i < this.data.Length; i++) | |
376 | { | |
377 | byte b = this.data[i]; | |
378 | if (ignoreCase) b = ASCIIChar.ToLower(b); | |
379 | if (valueBytes.Contains(this.data[i])) return i; | |
380 | } | |
381 | ||
382 | return -1; | |
383 | } | |
384 | public ASCIIString Insert(ASCIIString value, int index) | |
385 | { | |
386 | if (value == null) throw new ArgumentNullException("value"); | |
387 | if (index < 0 || index > this.data.Length) throw new ArgumentOutOfRangeException("index"); | |
388 | ||
389 | int totalBytes = this.data.Length + value.data.Length; | |
390 | byte[] data = new byte[totalBytes]; | |
391 | ||
392 | Buffer.BlockCopy(this.data, 0, data, 0, index); | |
393 | Buffer.BlockCopy(value.data, 0, data, index, value.data.Length); | |
394 | Buffer.BlockCopy(this.data, index, data, index + value.data.Length, this.data.Length - index); | |
395 | ||
396 | return new ASCIIString(data); | |
397 | } | |
398 | public int LastIndexOf(ASCIIString value) | |
399 | { | |
400 | return this.LastIndexOf(value, 0, this.Length, false); | |
401 | } | |
402 | public int LastIndexOf(ASCIIString value, bool ignoreCase) | |
403 | { | |
404 | return this.LastIndexOf(value, 0, this.Length, ignoreCase); | |
405 | } | |
406 | public int LastIndexOf(ASCIIString value, int startIndex) | |
407 | { | |
408 | return this.LastIndexOf(value, startIndex, this.Length - startIndex, false); | |
409 | } | |
410 | public int LastIndexOf(ASCIIString value, int startIndex, bool ignoreCase) | |
411 | { | |
412 | return this.LastIndexOf(value, startIndex, this.Length - startIndex, ignoreCase); | |
413 | } | |
414 | public int LastIndexOf(ASCIIString value, int startIndex, int count) | |
415 | { | |
416 | return this.LastIndexOf(value, startIndex, count, false); | |
417 | } | |
418 | public int LastIndexOf(ASCIIString value, int startIndex, int count, bool ignoreCase) | |
419 | { | |
420 | if (value == null) throw new ArgumentNullException("value"); | |
421 | if (startIndex < 0 || startIndex > this.data.Length) throw new ArgumentOutOfRangeException("startIndex"); | |
422 | if (count < 0 || startIndex + count > this.data.Length) throw new ArgumentOutOfRangeException("count"); | |
423 | ||
424 | int lastIndexFound = -1; | |
425 | int result = startIndex - 1; | |
426 | ||
427 | do | |
428 | { | |
429 | result = this.IndexOf(value, result + 1, count - (result + 1), ignoreCase); | |
430 | ||
431 | if (result >= 0) | |
432 | { | |
433 | lastIndexFound = result; | |
434 | } | |
435 | } | |
436 | while (result >= 0 && result + 1 < this.data.Length - value.data.Length); | |
437 | ||
438 | return lastIndexFound; | |
439 | } | |
440 | public int LastIndexOfAny(params ASCIIChar[] values) | |
441 | { | |
442 | return this.LastIndexOfAny(values, 0, this.data.Length, false); | |
443 | } | |
444 | public int LastIndexOfAny(IEnumerable<ASCIIChar> values) | |
445 | { | |
446 | return this.LastIndexOfAny(values, 0, this.data.Length, false); | |
447 | } | |
448 | public int LastIndexOfAny(IEnumerable<ASCIIChar> values, bool ignoreCase) | |
449 | { | |
450 | return this.LastIndexOfAny(values, 0, this.data.Length, ignoreCase); | |
451 | } | |
452 | public int LastIndexOfAny(IEnumerable<ASCIIChar> values, int startIndex) | |
453 | { | |
454 | return this.LastIndexOfAny(values, startIndex, this.data.Length - startIndex, false); | |
455 | } | |
456 | public int LastIndexOfAny(IEnumerable<ASCIIChar> values, int startIndex, bool ignoreCase) | |
457 | { | |
458 | return this.LastIndexOfAny(values, startIndex, this.data.Length - startIndex, ignoreCase); | |
459 | } | |
460 | public int LastIndexOfAny(IEnumerable<ASCIIChar> values, int startIndex, int count) | |
461 | { | |
462 | return this.LastIndexOfAny(values, startIndex, count, false); | |
463 | } | |
464 | public int LastIndexOfAny(IEnumerable<ASCIIChar> values, int startIndex, int count, bool ignoreCase) | |
465 | { | |
466 | if (values == null) throw new ArgumentNullException("values"); | |
467 | if (startIndex < 0 || startIndex > this.data.Length) throw new ArgumentOutOfRangeException("startIndex"); | |
468 | if (count < 0 || startIndex + count > this.data.Length) throw new ArgumentOutOfRangeException("count"); | |
469 | ||
470 | List<byte> valueBytes = new List<byte>(); | |
471 | ||
472 | foreach (ASCIIChar c in values) | |
473 | { | |
474 | if (ignoreCase) valueBytes.Add(ASCIIChar.ToLower(c.ToByte())); | |
475 | else valueBytes.Add(c.ToByte()); | |
476 | } | |
477 | ||
478 | int lastIndex = -1; | |
479 | ||
480 | for (int i = 0; i < this.data.Length; i++) | |
481 | { | |
482 | byte b = this.data[i]; | |
483 | if (ignoreCase) b = ASCIIChar.ToLower(b); | |
484 | if (valueBytes.Contains(this.data[i])) lastIndex = i; | |
485 | } | |
486 | ||
487 | return lastIndex; | |
488 | } | |
489 | public ASCIIString PadLeft(int totalLength) | |
490 | { | |
491 | return this.PadLeft(totalLength, ASCIIChars.Space); | |
492 | } | |
493 | public ASCIIString PadLeft(int totalLength, ASCIIChar c) | |
494 | { | |
495 | if (totalLength < this.data.Length) throw new ArgumentOutOfRangeException("totalLength"); | |
496 | ||
497 | byte[] data = new byte[totalLength]; | |
498 | byte charByte = c.ToByte(); | |
499 | ||
500 | int i = 0; | |
501 | ||
502 | for (; i + this.data.Length < totalLength; i++) | |
503 | { | |
504 | data[i] = charByte; | |
505 | } | |
506 | ||
507 | Buffer.BlockCopy(this.data, 0, data, i, this.data.Length); | |
508 | ||
509 | return new ASCIIString(data); | |
510 | } | |
511 | public ASCIIString PadRight(int totalLength) | |
512 | { | |
513 | return this.PadRight(totalLength, ASCIIChars.Space); | |
514 | } | |
515 | public ASCIIString PadRight(int totalLength, ASCIIChar c) | |
516 | { | |
517 | if (totalLength < this.data.Length) throw new ArgumentOutOfRangeException("totalLength"); | |
518 | ||
519 | byte[] data = new byte[totalLength]; | |
520 | byte charByte = c.ToByte(); | |
521 | ||
522 | Buffer.BlockCopy(this.data, 0, data, 0, this.data.Length); | |
523 | ||
524 | for (int i = this.data.Length; i < totalLength; i++) | |
525 | - | public ASCIIString Parse(string value) |
525 | + | |
526 | data[i] = charByte; | |
527 | } | |
528 | ||
529 | return new ASCIIString(data); | |
530 | } | |
531 | public ASCIIString Remove(int startIndex) | |
532 | { | |
533 | return this.Remove(startIndex, this.data.Length - startIndex); | |
534 | } | |
535 | public ASCIIString Remove(int startIndex, int count) | |
536 | { | |
537 | if (startIndex < 0 || startIndex > this.data.Length) throw new ArgumentOutOfRangeException("startIndex"); | |
538 | if (count < 0 || startIndex + count > this.data.Length) throw new ArgumentOutOfRangeException("count"); | |
539 | ||
540 | byte[] data = new byte[this.data.Length - count]; | |
541 | ||
542 | Buffer.BlockCopy(this.data, 0, data, 0, startIndex); | |
543 | Buffer.BlockCopy(this.data, startIndex + count, data, startIndex, this.data.Length - count - startIndex); | |
544 | ||
545 | return new ASCIIString(data); | |
546 | } | |
547 | public ASCIIString Replace(ASCIIString oldString, ASCIIString newString) | |
548 | { | |
549 | if (oldString == null) throw new ArgumentNullException("oldString"); | |
550 | if (newString == null) throw new ArgumentNullException("newString"); | |
551 | ||
552 | List<int> indexes = new List<int>(); | |
553 | int index = 0; | |
554 | ||
555 | do | |
556 | { | |
557 | index = this.IndexOf(oldString, index, false); | |
558 | ||
559 | if (index >= 0) | |
560 | { | |
561 | indexes.Add(index); | |
562 | index += oldString.data.Length; | |
563 | } | |
564 | } | |
565 | while (index >= 0 && index + oldString.Length < this.data.Length); | |
566 | ||
567 | if (indexes.Count == 0) | |
568 | { | |
569 | return this.Clone(); | |
570 | } | |
571 | ||
572 | byte[] data = new byte[this.data.Length - (oldString.data.Length * indexes.Count) + (newString.data.Length * indexes.Count)]; | |
573 | ||
574 | int oldIndex = 0; | |
575 | int newIndex = 0; | |
576 | ||
577 | foreach (int stringIndex in indexes) | |
578 | { | |
579 | Buffer.BlockCopy(this.data, oldIndex, data, newIndex, stringIndex - oldIndex); | |
580 | newIndex += stringIndex - oldIndex; | |
581 | oldIndex = stringIndex + oldString.data.Length; | |
582 | Buffer.BlockCopy(newString.data, 0, data, newIndex, newString.data.Length); | |
583 | newIndex += newString.data.Length; | |
584 | } | |
585 | ||
586 | Buffer.BlockCopy(this.data, oldIndex, data, newIndex, this.data.Length - oldIndex); | |
587 | ||
588 | return new ASCIIString(data); | |
589 | } | |
590 | public ASCIIString Replace(ASCIIChar oldChar, ASCIIChar newChar) | |
591 | { | |
592 | if (oldChar == newChar) return this.Clone(); | |
593 | ||
594 | ASCIIChar[] oldChars = new ASCIIChar[] { oldChar }; | |
595 | ||
596 | List<int> indexes = new List<int>(); | |
597 | int index = 0; | |
598 | ||
599 | do | |
600 | { | |
601 | index = this.IndexOfAny(oldChars, index, false); | |
602 | ||
603 | if (index >= 0) | |
604 | { | |
605 | indexes.Add(index); | |
606 | index ++; | |
607 | } | |
608 | } | |
609 | while (index >= 0 && index + 1 < this.data.Length); | |
610 | ||
611 | if (indexes.Count == 0) return this.Clone(); | |
612 | ||
613 | byte[] data = new byte[this.data.Length]; | |
614 | ||
615 | int oldIndex = 0; | |
616 | int newIndex = 0; | |
617 | ||
618 | foreach (int stringIndex in indexes) | |
619 | { | |
620 | Buffer.BlockCopy(this.data, oldIndex, data, newIndex, stringIndex - oldIndex); | |
621 | newIndex += stringIndex - oldIndex; | |
622 | oldIndex = stringIndex + 1; | |
623 | data[newIndex] = newChar.ToByte(); | |
624 | newIndex++; | |
625 | } | |
626 | ||
627 | Buffer.BlockCopy(this.data, oldIndex, data, newIndex, this.data.Length - oldIndex); | |
628 | ||
629 | return new ASCIIString(data); | |
630 | } | |
631 | public ASCIIString[] Split(params ASCIIString[] seperators) | |
632 | { | |
633 | return this.Split(seperators, int.MaxValue, StringSplitOptions.None); | |
634 | } | |
635 | public ASCIIString[] Split(IEnumerable<ASCIIString> seperators) | |
636 | { | |
637 | return this.Split(seperators, int.MaxValue, StringSplitOptions.None); | |
638 | } | |
639 | public ASCIIString[] Split(IEnumerable<ASCIIString> seperators, StringSplitOptions options) | |
640 | { | |
641 | return this.Split(seperators, int.MaxValue, options); | |
642 | } | |
643 | public ASCIIString[] Split(IEnumerable<ASCIIString> seperators, int count) | |
644 | { | |
645 | return this.Split(seperators, count, StringSplitOptions.None); | |
646 | } | |
647 | public ASCIIString[] Split(IEnumerable<ASCIIString> seperators, int count, StringSplitOptions options) | |
648 | { | |
649 | List<ASCIIString> parts = new List<ASCIIString>(); | |
650 | ||
651 | int startIndex = 0; | |
652 | ||
653 | for (int dataIndex = 0; dataIndex < this.data.Length; dataIndex++) | |
654 | { | |
655 | int charsFound = 0; | |
656 | bool found = false; | |
657 | ||
658 | foreach (ASCIIString seperator in seperators) | |
659 | { | |
660 | charsFound = 0; | |
661 | ||
662 | if (dataIndex + seperator.data.Length > this.data.Length) break; | |
663 | ||
664 | for (int sepIndex = 0; sepIndex < seperator.Length; sepIndex++) | |
665 | { | |
666 | if (this.data[dataIndex + sepIndex] == seperator[sepIndex]) charsFound++; | |
667 | else charsFound = 0; | |
668 | } | |
669 | ||
670 | if (charsFound == seperator.data.Length) found = true; | |
671 | } | |
672 | ||
673 | if (found) | |
674 | { | |
675 | ASCIIString part = this.Substring(startIndex, dataIndex - startIndex); | |
676 | if (part.data.Length > 0 || options == StringSplitOptions.None) | |
677 | { | |
678 | parts.Add(part); | |
679 | } | |
680 | startIndex = dataIndex + charsFound; | |
681 | dataIndex += charsFound - 1; | |
682 | ||
683 | if (parts.Count + 1 == count) break; | |
684 | } | |
685 | } | |
686 | ||
687 | ASCIIString remainingPart = this.Substring(startIndex); | |
688 | if (remainingPart.data.Length > 0 || options == StringSplitOptions.None) | |
689 | { | |
690 | parts.Add(remainingPart); | |
691 | } | |
692 | ||
693 | return parts.ToArray(); | |
694 | } | |
695 | public ASCIIString[] Split(params ASCIIChar[] seperators) | |
696 | { | |
697 | return this.Split(seperators, int.MaxValue, StringSplitOptions.None); | |
698 | } | |
699 | public ASCIIString[] Split(IEnumerable<ASCIIChar> seperators) | |
700 | { | |
701 | return this.Split(seperators, int.MaxValue, StringSplitOptions.None); | |
702 | } | |
703 | public ASCIIString[] Split(IEnumerable<ASCIIChar> seperators, StringSplitOptions options) | |
704 | { | |
705 | return this.Split(seperators, int.MaxValue, options); | |
706 | } | |
707 | public ASCIIString[] Split(IEnumerable<ASCIIChar> seperators, int count) | |
708 | { | |
709 | return this.Split(seperators, count, StringSplitOptions.None); | |
710 | } | |
711 | public ASCIIString[] Split(IEnumerable<ASCIIChar> seperators, int count, StringSplitOptions options) | |
712 | { | |
713 | List<ASCIIString> parts = new List<ASCIIString>(); | |
714 | ||
715 | int startIndex = 0; | |
716 | ||
717 | for (int dataIndex = 0; dataIndex < this.data.Length; dataIndex++) | |
718 | { | |
719 | bool found = false; | |
720 | ||
721 | foreach (ASCIIChar seperator in seperators) | |
722 | { | |
723 | if (this.data[dataIndex] == seperator) | |
724 | { | |
725 | found = true; | |
726 | } | |
727 | } | |
728 | ||
729 | if (found) | |
730 | { | |
731 | ASCIIString part = this.Substring(startIndex, dataIndex - startIndex); | |
732 | if (part.data.Length > 0 || options == StringSplitOptions.None) | |
733 | { | |
734 | parts.Add(part); | |
735 | } | |
736 | ||
737 | startIndex = dataIndex + 1; | |
738 | ||
739 | if (parts.Count + 1 == count) break; | |
740 | } | |
741 | } | |
742 | ||
743 | ASCIIString remainingPart = this.Substring(startIndex); | |
744 | if (remainingPart.data.Length > 0 || options == StringSplitOptions.None) | |
745 | { | |
746 | parts.Add(remainingPart); | |
747 | } | |
748 | ||
749 | return parts.ToArray(); | |
750 | } | |
751 | public bool StartsWith(ASCIIString value) | |
752 | { | |
753 | return this.StartsWith(value, false); | |
754 | } | |
755 | public bool StartsWith(ASCIIString value, bool ignoreCase) | |
756 | { | |
757 | if (value == null) throw new ArgumentNullException("value"); | |
758 | return ASCIIString.Compare(this, 0, value, 0, value.Length, ignoreCase) == 0; | |
759 | } | |
760 | public ASCIIString Substring(int startIndex) | |
761 | { | |
762 | return this.Substring(startIndex, this.data.Length - startIndex); | |
763 | } | |
764 | public ASCIIString Substring(int startIndex, int length) | |
765 | { | |
766 | if (startIndex < 0 || startIndex > data.Length) throw new ArgumentOutOfRangeException("startIndex"); | |
767 | if (length < 0 || startIndex + length > data.Length) throw new ArgumentOutOfRangeException("length"); | |
768 | ||
769 | byte[] newData = new byte[length]; | |
770 | Buffer.BlockCopy(data, startIndex, newData, 0, length); | |
771 | return new ASCIIString(newData); | |
772 | } | |
773 | public ASCIIChar[] ToCharArray() | |
774 | { | |
775 | ASCIIChar[] chars = new ASCIIChar[this.data.Length]; | |
776 | for (int i = 0; i < this.data.Length; i++) | |
777 | { | |
778 | chars[i] = new ASCIIChar(this.data[i]); | |
779 | } | |
780 | return chars; | |
781 | } | |
782 | public ASCIIString ToLower() | |
783 | { | |
784 | ASCIIString s = ASCIIString.Copy(this); | |
785 | ||
786 | for (int i = 0; i < s.data.Length; i++) | |
787 | { | |
788 | byte b = s.data[i]; | |
789 | if (ASCIIChar.IsUpper(b)) | |
790 | { | |
791 | s.data[i] = ASCIIChar.ToLower(b); | |
792 | } | |
793 | } | |
794 | ||
795 | return s; | |
796 | } | |
797 | public ASCIIString ToUpper() | |
798 | { | |
799 | ASCIIString s = ASCIIString.Copy(this); | |
800 | ||
801 | for (int i = 0; i < s.data.Length; i++) | |
802 | { | |
803 | byte b = s.data[i]; | |
804 | if (ASCIIChar.IsLower(b)) | |
805 | { | |
806 | s.data[i] = ASCIIChar.ToUpper(b); | |
807 | } | |
808 | } | |
809 | ||
810 | return s; | |
811 | } | |
812 | public ASCIIString Trim() | |
813 | { | |
814 | int charsAtStart = 0; | |
815 | int charsAtEnd = 0; | |
816 | ||
817 | for (int i = 0; i < this.data.Length; i++) | |
818 | { | |
819 | if (ASCIIChar.IsWhitespace(this.data[i])) | |
820 | { | |
821 | charsAtStart++; | |
822 | } | |
823 | else | |
824 | { | |
825 | break; | |
826 | } | |
827 | } | |
828 | ||
829 | for (int i = this.data.Length - 1; i >= charsAtStart; i--) | |
830 | { | |
831 | if (ASCIIChar.IsWhitespace(this.data[i])) | |
832 | { | |
833 | charsAtEnd++; | |
834 | } | |
835 | else | |
836 | { | |
837 | break; | |
838 | } | |
839 | } | |
840 | ||
841 | byte[] data = new byte[this.data.Length - charsAtStart - charsAtEnd]; | |
842 | Buffer.BlockCopy(this.data, charsAtStart, data, 0, data.Length); | |
843 | return new ASCIIString(data); | |
844 | } | |
845 | public ASCIIString Trim(params ASCIIChar[] values) | |
846 | { | |
847 | int charsAtStart = 0; | |
848 | int charsAtEnd = 0; | |
849 | ||
850 | for (int i = 0; i < this.data.Length; i++) | |
851 | { | |
852 | bool found = false; | |
853 | ||
854 | foreach (ASCIIChar c in values) | |
855 | { | |
856 | if (this.data[i].Equals(c.ToByte())) | |
857 | { | |
858 | charsAtStart++; | |
859 | found = true; | |
860 | break; | |
861 | } | |
862 | } | |
863 | ||
864 | if (!found) break; | |
865 | } | |
866 | ||
867 | for (int i = this.data.Length - 1; i >= charsAtStart; i--) | |
868 | { | |
869 | bool found = false; | |
870 | ||
871 | foreach (ASCIIChar c in values) | |
872 | { | |
873 | if (this.data[i].Equals(c.ToByte())) | |
874 | { | |
875 | charsAtEnd++; | |
876 | found = true; | |
877 | break; | |
878 | } | |
879 | } | |
880 | ||
881 | if (!found) break; | |
882 | } | |
883 | ||
884 | byte[] data = new byte[this.data.Length - charsAtStart - charsAtEnd]; | |
885 | Buffer.BlockCopy(this.data, charsAtStart, data, 0, data.Length); | |
886 | return new ASCIIString(data); | |
887 | } | |
888 | public ASCIIString TrimEnd() | |
889 | { | |
890 | int charsAtEnd = 0; | |
891 | ||
892 | for (int i = this.data.Length - 1; i >= 0; i--) | |
893 | { | |
894 | if (ASCIIChar.IsWhitespace(this.data[i])) | |
895 | { | |
896 | charsAtEnd++; | |
897 | } | |
898 | else | |
899 | { | |
900 | break; | |
901 | } | |
902 | } | |
903 | ||
904 | byte[] data = new byte[this.data.Length - charsAtEnd]; | |
905 | Buffer.BlockCopy(this.data, 0, data, 0, data.Length); | |
906 | return new ASCIIString(data); | |
907 | } | |
908 | public ASCIIString TrimEnd(params ASCIIChar[] values) | |
909 | { | |
910 | int charsAtEnd = 0; | |
911 | ||
912 | for (int i = this.data.Length - 1; i >= 0; i--) | |
913 | { | |
914 | bool found = false; | |
915 | ||
916 | foreach (ASCIIChar c in values) | |
917 | { | |
918 | if (this.data[i].Equals(c.ToByte())) | |
919 | { | |
920 | charsAtEnd++; | |
921 | found = true; | |
922 | break; | |
923 | } | |
924 | } | |
925 | ||
926 | if (!found) break; | |
927 | } | |
928 | ||
929 | byte[] data = new byte[this.data.Length - charsAtEnd]; | |
930 | Buffer.BlockCopy(this.data, 0, data, 0, data.Length); | |
931 | return new ASCIIString(data); | |
932 | } | |
933 | public ASCIIString TrimStart() | |
934 | { | |
935 | int charsAtStart = 0; | |
936 | ||
937 | for (int i = 0; i < this.data.Length; i++) | |
938 | { | |
939 | if (ASCIIChar.IsWhitespace(this.data[i])) | |
940 | { | |
941 | charsAtStart++; | |
942 | } | |
943 | else | |
944 | { | |
945 | break; | |
946 | } | |
947 | } | |
948 | ||
949 | byte[] data = new byte[this.data.Length - charsAtStart]; | |
950 | Buffer.BlockCopy(this.data, charsAtStart, data, 0, data.Length); | |
951 | return new ASCIIString(data); | |
952 | } | |
953 | public ASCIIString TrimStart(params ASCIIChar[] values) | |
954 | { | |
955 | int charsAtStart = 0; | |
956 | ||
957 | for (int i = 0; i < this.data.Length; i++) | |
958 | { | |
959 | bool found = false; | |
960 | ||
961 | foreach (ASCIIChar c in values) | |
962 | { | |
963 | if (this.data[i].Equals(c.ToByte())) | |
964 | { | |
965 | charsAtStart++; | |
966 | found = true; | |
967 | break; | |
968 | } | |
969 | } | |
970 | ||
971 | if (!found) break; | |
972 | } | |
973 | ||
974 | byte[] data = new byte[this.data.Length - charsAtStart]; | |
975 | Buffer.BlockCopy(this.data, charsAtStart, data, 0, data.Length); | |
976 | return new ASCIIString(data); | |
977 | } | |
978 | ||
979 | public override string ToString() | |
980 | { | |
981 | return Encoding.ASCII.GetString(this.data); | |
982 | } | |
983 | ||
984 | public IEnumerator<ASCIIChar> GetEnumerator() | |
985 | { | |
986 | foreach (byte b in this.data) | |
987 | { | |
988 | yield return new ASCIIChar(b); | |
989 | } | |
990 | } | |
991 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | |
992 | { | |
993 | return this.GetEnumerator(); | |
994 | } | |
995 | ||
996 | int IComparable<ASCIIString>.CompareTo(ASCIIString other) | |
997 | { | |
998 | return this.CompareTo(other); | |
999 | } | |
1000 | } |