source: OniSplit/Utils.cs@ 1145

Last change on this file since 1145 was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 18.8 KB
Line 
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.IO;
5using System.Text;
6using System.Text.RegularExpressions;
7using System.Xml;
8using System.Reflection;
9
10namespace Oni
11{
12#if !NETFX4
13 internal delegate void Action();
14 internal delegate void Action<T>(T arg1);
15 internal delegate void Action<T1, T2>(T1 arg1, T2 args);
16 internal delegate TResult Func<T1, TResult>(T1 arg1);
17 internal delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
18 internal delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
19#endif
20
21 internal static class Utils
22 {
23 private static string version;
24
25 public static string Version
26 {
27 get
28 {
29 if (version == null)
30 {
31#if NETCORE
32 version = typeof(Utils).GetTypeInfo().Assembly.GetName().Version.ToString();
33#else
34 version = typeof(Utils).Assembly.GetName().Version.ToString();
35#endif
36 }
37
38 return version;
39 }
40 }
41
42 public static string TagToString(int tag)
43 {
44 var chars = new char[4];
45
46 chars[0] = (char)((tag >> 00) & 0xff);
47 chars[1] = (char)((tag >> 08) & 0xff);
48 chars[2] = (char)((tag >> 16) & 0xff);
49 chars[3] = (char)((tag >> 24) & 0xff);
50
51 return new string(chars);
52 }
53
54 public static int Align4(int value) => (value + 0x03) & ~0x03;
55 public static int Align32(int value) => (value + 0x1f) & ~0x1f;
56
57 public static short ByteSwap(short value)
58 {
59 return (short)((value >> 8) | (value << 8));
60 }
61
62 public static int ByteSwap(int value)
63 {
64 value = (value >> 16) | (value << 16);
65 return ((value >> 8) & 0x00ff00ff) | ((value & 0x00ff00ff) << 8);
66 }
67
68 public static bool ArrayEquals<T>(T[] a1, T[] a2)
69 {
70 if (a1 == a2)
71 return true;
72
73 if (a1 == null || a2 == null)
74 return false;
75
76 if (a1.Length != a2.Length)
77 return false;
78
79 var comparer = EqualityComparer<T>.Default;
80
81 for (int i = 0; i < a1.Length; i++)
82 {
83 if (!comparer.Equals(a1[i], a2[i]))
84 return false;
85 }
86
87 return true;
88 }
89
90 public static string CleanupTextureName(string name)
91 {
92 name = name.Replace('/', '_');
93
94 if (name == "<none>")
95 name = "none";
96
97 return name;
98 }
99
100 private static readonly char[] wildcards = { '*', '?', '.' };
101
102 private static void WildcardToRegex(string wexp, StringBuilder regexp)
103 {
104 for (int startIndex = 0; startIndex < wexp.Length;)
105 {
106 int i = wexp.IndexOfAny(wildcards, startIndex);
107
108 if (i == -1)
109 {
110 regexp.Append(wexp, startIndex, wexp.Length - startIndex);
111 break;
112 }
113
114 regexp.Append(wexp, startIndex, i - startIndex);
115
116 if (wexp[i] == '.')
117 regexp.Append("\\.");
118 if (wexp[i] == '*')
119 regexp.Append(".*");
120 else if (wexp[i] == '?')
121 regexp.Append('.');
122
123 startIndex = i + 1;
124 }
125 }
126
127 public static Regex WildcardToRegex(string wexp)
128 {
129 if (string.IsNullOrEmpty(wexp))
130 return null;
131
132 var regexp = new StringBuilder();
133 WildcardToRegex(wexp, regexp);
134 return new Regex(regexp.ToString(), RegexOptions.Singleline);
135 }
136
137 public static Regex WildcardToRegex(List<string> wexps)
138 {
139 if (wexps.Count == 0)
140 return null;
141
142 var regex = new StringBuilder();
143
144 foreach (var wexp in wexps)
145 {
146 if (regex.Length != 0)
147 regex.Append('|');
148
149 regex.Append('(');
150 WildcardToRegex(wexp, regex);
151 regex.Append(')');
152 }
153
154 Console.WriteLine(regex.ToString());
155
156 return new Regex(regex.ToString(), RegexOptions.Singleline);
157 }
158
159 private static byte[] buffer1;
160 private static byte[] buffer2;
161
162 public static bool AreFilesEqual(string filePath1, string filePath2)
163 {
164 if (buffer1 == null)
165 {
166 buffer1 = new byte[32768];
167 buffer2 = new byte[32768];
168 }
169
170 using (var s1 = File.OpenRead(filePath1))
171 using (var s2 = File.OpenRead(filePath2))
172 {
173 if (s1.Length != s2.Length)
174 return false;
175
176 while (true)
177 {
178 int r1 = s1.Read(buffer1, 0, buffer1.Length);
179 int r2 = s2.Read(buffer2, 0, buffer2.Length);
180
181 if (r1 != r2)
182 return false;
183
184 if (r1 == 0)
185 return true;
186
187 for (int i = 0; i < r1; i++)
188 {
189 if (buffer1[i] != buffer2[i])
190 return false;
191 }
192 }
193 }
194 }
195
196
197 public static bool IsFlagsEnum(Type enumType)
198 {
199#if NETCORE
200 return (enumType.GetTypeInfo().GetCustomAttributes(typeof(FlagsAttribute), false).Any());
201#else
202 return (enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0);
203#endif
204 }
205
206 public static void WriteEnum(Type enumType)
207 {
208 bool isFlags = IsFlagsEnum(enumType);
209 Type underlyingType = Enum.GetUnderlyingType(enumType);
210
211 if (isFlags)
212 Console.WriteLine("flags {0}", enumType.Name);
213 else
214 Console.WriteLine("enum {0}", enumType.Name);
215
216 foreach (string name in Enum.GetNames(enumType))
217 {
218 object value = Enum.Parse(enumType, name);
219
220 if (isFlags)
221 {
222 if (underlyingType == typeof(ulong))
223 Console.WriteLine("\t{0} = 0x{1:X16}", name, Convert.ToUInt64(value));
224 else
225 Console.WriteLine("\t{0} = 0x{1:X8}", name, Convert.ToUInt32(value));
226 }
227 else
228 {
229 if (underlyingType == typeof(ulong))
230 Console.WriteLine("\t{0} = {1}", name, Convert.ToUInt64(value));
231 else
232 Console.WriteLine("\t{0} = {1}", name, Convert.ToInt32(value));
233 }
234 }
235
236 Console.WriteLine();
237 }
238
239 public static IEnumerable<T> Reverse<T>(this IList<T> list)
240 {
241 for (int i = list.Count - 1; i >= 0; i--)
242 yield return list[i];
243 }
244
245 public static T First<T>(this IList<T> list) => list[0];
246
247 public static T Last<T>(this IList<T> list) => list[list.Count - 1];
248
249 public static T LastOrDefault<T>(this List<T> list)
250 {
251 if (list.Count == 0)
252 return default(T);
253
254 return list[list.Count - 1];
255 }
256
257 public static float[] Negate(this float[] values)
258 {
259 float[] result = new float[values.Length];
260
261 for (int i = 0; i < values.Length; i++)
262 result[i] = -values[i];
263
264 return result;
265 }
266
267 public static string CommonPrefix(List<string> strings)
268 {
269 string first = strings[0];
270
271 for (int prefixLength = 0; prefixLength < first.Length; prefixLength++)
272 {
273 for (int i = 1; i < strings.Count; i++)
274 {
275 string s = strings[i];
276
277 if (prefixLength >= s.Length || first[prefixLength] != s[prefixLength])
278 return first.Substring(0, prefixLength);
279 }
280 }
281
282 return first;
283 }
284
285 public static void SkipSequence(this XmlReader xml, string name)
286 {
287 while (xml.IsStartElement(name))
288 xml.Skip();
289 }
290
291 public static bool SkipEmpty(this XmlReader xml)
292 {
293 if (!xml.IsEmptyElement)
294 return false;
295
296 xml.Skip();
297 return true;
298 }
299
300 //public static int CommonPrefixLength(string s1, string s2)
301 //{
302 // int length = Math.Min(s1.Length, s2.Length);
303
304 // for (int i = 0; i < length; i++)
305 // {
306 // if (s1[i] != s2[i])
307 // return i;
308 // }
309
310 // return length;
311 //}
312 }
313
314 /// <summary>
315 /// A couple of IEnumerable extensions so we can run even on .NET 2.0
316 /// </summary>
317 internal static class Enumerable
318 {
319 public static bool Any<T>(this IEnumerable<T> source)
320 {
321 foreach (var t in source)
322 return true;
323
324 return false;
325 }
326
327 public static bool Any<T>(this IEnumerable<T> source, Func<T, bool> predicate)
328 {
329 foreach (var t in source)
330 {
331 if (predicate(t))
332 return true;
333 }
334
335 return false;
336 }
337
338 public static bool All<T>(this IEnumerable<T> source, Func<T, bool> predicate)
339 {
340 foreach (var t in source)
341 {
342 if (!predicate(t))
343 return false;
344 }
345
346 return true;
347 }
348
349 public static IEnumerable<T> OfType<T>(this System.Collections.IEnumerable source)
350 where T : class
351 {
352 foreach (var obj in source)
353 {
354 var t = obj as T;
355
356 if (t != null)
357 yield return t;
358 }
359 }
360
361 public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source)
362 where T : class
363 {
364 var set = new Dictionary<T, bool>();
365 bool hasNull = false;
366
367 foreach (var t in source)
368 {
369 if (t == null)
370 {
371 if (!hasNull)
372 {
373 hasNull = true;
374 yield return null;
375 }
376 }
377 else if (!set.ContainsKey(t))
378 {
379 set.Add(t, true);
380 yield return t;
381 }
382 }
383 }
384
385 public static int Count<T>(this IEnumerable<T> source, Func<T, bool> predicate)
386 {
387 var count = 0;
388
389 foreach (var t in source)
390 if (predicate(t))
391 count++;
392
393 return count;
394 }
395
396 public static IEnumerable<T> Concatenate<T>(this IEnumerable<T> first, IEnumerable<T> second)
397 {
398 foreach (var t in first)
399 yield return t;
400
401 foreach (var t in second)
402 yield return t;
403 }
404
405 public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate)
406 {
407 foreach (var t in source)
408 {
409 if (predicate(t))
410 yield return t;
411 }
412 }
413
414 public static bool IsEmpty<T>(this IEnumerable<T> source)
415 {
416 foreach (var t in source)
417 return true;
418
419 return false;
420 }
421
422 public static T First<T>(this IEnumerable<T> source)
423 {
424 foreach (var t in source)
425 return t;
426
427 throw new InvalidOperationException();
428 }
429
430 public static T First<T>(this IEnumerable<T> source, Func<T, bool> predicate)
431 {
432 foreach (var t in source)
433 {
434 if (predicate(t))
435 return t;
436 }
437
438 throw new InvalidOperationException();
439 }
440
441 public static T FirstOrDefault<T>(this IEnumerable<T> source)
442 {
443 foreach (var t in source)
444 return t;
445
446 return default(T);
447 }
448
449 public static T FirstOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate)
450 {
451 foreach (var t in source)
452 {
453 if (predicate(t))
454 return t;
455 }
456
457 return default(T);
458 }
459
460 public static IEnumerable<TOut> Select<TIn, TOut>(this IEnumerable<TIn> source, Func<TIn, TOut> selector)
461 {
462 foreach (var t in source)
463 yield return selector(t);
464 }
465
466 public static IEnumerable<TOut> SelectMany<TIn, TOut>(this IEnumerable<TIn> source, Func<TIn, IEnumerable<TOut>> selector)
467 {
468 foreach (var tin in source)
469 {
470 foreach (var tout in selector(tin))
471 yield return tout;
472 }
473 }
474
475 public static float Max(this IEnumerable<float> source)
476 {
477 var max = float.MinValue;
478
479 foreach (var value in source)
480 max = Math.Max(max, value);
481
482 return max;
483 }
484
485 public static float Min<T>(this IEnumerable<T> source, Func<T, float> selector)
486 {
487 var min = float.MaxValue;
488
489 foreach (var value in source)
490 min = Math.Min(min, selector(value));
491
492 return min;
493 }
494
495 public static int Min<T>(this IEnumerable<T> source, Func<T, int> selector)
496 {
497 var min = int.MaxValue;
498
499 foreach (var value in source)
500 min = Math.Min(min, selector(value));
501
502 return min;
503 }
504
505 public static float Min(this IEnumerable<float> source)
506 {
507 var min = float.MaxValue;
508
509 foreach (var value in source)
510 min = Math.Min(min, value);
511
512 return min;
513 }
514
515 public static float Max<T>(this IEnumerable<T> source, Func<T, float> selector)
516 {
517 var max = float.MinValue;
518
519 foreach (var value in source)
520 max = Math.Max(max, selector(value));
521
522 return max;
523 }
524
525 public static int Max(this IEnumerable<int> source)
526 {
527 int max = int.MinValue;
528
529 foreach (var value in source)
530 {
531 if (value > max)
532 max = value;
533 }
534
535 return max;
536 }
537
538 public static int Max<T>(this IEnumerable<T> source, Func<T, int> selector)
539 {
540 int max = int.MinValue;
541
542 foreach (var item in source)
543 {
544 var value = selector(item);
545
546 if (value > max)
547 max = value;
548 }
549
550 return max;
551 }
552
553 public static TOutput[] ConvertAll<TInput, TOutput>(this TInput[] input, Func<TInput, TOutput> converter)
554 {
555 var output = new TOutput[input.Length];
556
557 for (int i = 0; i < output.Length; i++)
558 output[i] = converter(input[i]);
559
560 return output;
561 }
562
563 public static int Sum<T>(this IEnumerable<T> source, Func<T, int> selector)
564 {
565 int sum = 0;
566
567 foreach (var value in source)
568 sum += selector(value);
569
570 return sum;
571 }
572
573 public static IEnumerable<T> Repeat<T>(T value, int count)
574 {
575 for (int i = 0; i < count; i++)
576 yield return value;
577 }
578
579 public static T[] ToArray<T>(this IEnumerable<T> source)
580 {
581 var collection = source as ICollection<T>;
582
583 if (collection != null)
584 {
585 var result = new T[collection.Count];
586 collection.CopyTo(result, 0);
587 return result;
588 }
589
590 return new List<T>(source).ToArray();
591 }
592
593 public static List<T> ToList<T>(this IEnumerable<T> source) => new List<T>(source);
594
595 public static IEnumerable<T> Ring<T>(this IEnumerable<T> source)
596 {
597 foreach (T t in source)
598 {
599 yield return t;
600 }
601
602 foreach (T t in source)
603 {
604 yield return t;
605 break;
606 }
607 }
608
609 public static IEnumerable<T> Skip<T>(this IEnumerable<T> source, int count)
610 {
611 foreach (T t in source)
612 {
613 if (count <= 0)
614 yield return t;
615
616 count--;
617 }
618 }
619 }
620
621 internal struct EmptyArray<T>
622 {
623 public static readonly T[] Value = new T[0];
624 }
625
626 internal struct ReadOnlyArray<T>
627 {
628 private readonly T[] array;
629
630 public ReadOnlyArray(T[] array)
631 {
632 this.array = array;
633 }
634
635 public int Length => array.Length;
636 public T this[int index] => array[index];
637 }
638
639 internal class TreeIterator<T> : IEnumerable<T>
640 {
641 private readonly IEnumerable<T> roots;
642 private readonly Func<T, IEnumerable<T>> children;
643
644 public TreeIterator(IEnumerable<T> roots, Func<T, IEnumerable<T>> children)
645 {
646 this.roots = roots;
647 this.children = children;
648 }
649
650 public class Enumerator : IEnumerator<T>
651 {
652 public bool MoveNext()
653 {
654 throw new NotImplementedException();
655 }
656
657 public T Current
658 {
659 get { throw new NotImplementedException(); }
660 }
661
662 object IEnumerator.Current => Current;
663
664 public void Dispose()
665 {
666 }
667
668 public void Reset()
669 {
670 throw new NotSupportedException();
671 }
672 }
673
674 public IEnumerator<T> GetEnumerator() => new Enumerator();
675 IEnumerator IEnumerable.GetEnumerator() => new Enumerator();
676 }
677}
678
679#if !NETFX4
680namespace System.Runtime.CompilerServices
681{
682 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
683 internal sealed class ExtensionAttribute : Attribute
684 {
685 }
686}
687#endif
Note: See TracBrowser for help on using the repository browser.