// // ExtensionMethods.cs - various useful (maybe?) extension methods // // Author: // Michael Becker // // Copyright (c) 2011-2020 Mike Becker's Software // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . using System; using System.Collections.Generic; using System.Text; namespace UniversalEditor { public static class ExtensionMethods { public static long GetItemOffset(this List list, int index, int additionalPadding = 0) { long offset = 0; for (int i = 0; i < index; i++) { if (list[i] == null) { offset += additionalPadding; } else { offset += list[i].Length + additionalPadding; } } return offset; } public static bool get_EndOfStream(this System.IO.Stream stream) { return (stream.Position == stream.Length); } /// /// Gets an int value representing the subset of bits from a single Byte. /// /// The Byte used to get the subset of bits from. /// The offset of bits starting from the right. /// The number of bits to read. /// /// An int value representing the subset of bits. /// /// /// Given -> b = 00110101 /// A call to GetBits(b, 2, 4) /// GetBits looks at the following bits in the byte -> 00{1101}00 /// Returns 1101 as an int (13) /// public static int GetBits(this byte value, int offset, int count) { return (value >> offset) & ((1 << count) - 1); } public static int GetBits(this short value, int offset, int count) { return (value >> offset) & ((1 << count) - 1); } public static int GetBits(this int value, int offset, int count) { return (value >> offset) & ((1 << count) - 1); } public static byte[] ToBits(this byte value) { byte[] bits = new byte[8]; for (int i = 0; i < bits.Length; i++) { bits[i] = (byte)value.GetBits(i, 1); } return bits; } [CLSCompliant(false)] public static int GetBits(this ushort value, int offset, int count) { return (value >> offset) & ((1 << count) - 1); } [CLSCompliant(false)] public static byte[] ToBits(this ushort value) { byte[] bits = new byte[16]; for (int i = 0; i < bits.Length; i++) { bits[i] = (byte)value.GetBits(i, 1); } return bits; } public static void AddRange(this System.Collections.Specialized.StringCollection coll, params string[] values) { coll.AddRange(values); } public static bool Match(this Array array1, Array array2) { if (array1.Length != array2.Length) { return false; } System.Collections.IEnumerator en1 = array1.GetEnumerator(); System.Collections.IEnumerator en2 = array2.GetEnumerator(); en1.MoveNext(); en2.MoveNext(); try { while (en1.Current != null) { if (en2.Current == null) return false; if (!en1.Current.Equals(en2.Current)) return false; en1.MoveNext(); en2.MoveNext(); } } catch (InvalidOperationException) { } return true; } /// /// Returns if is equal /// to any one of the values in . /// /// true, if a match was found; false otherwise. /// The value to test. /// /// An array of items of type to check equality /// against . /// public static bool EqualsAny(this IEquatable value, params T[] anyOf) { for (int i = 0; i < anyOf.Length; i++) { T any = anyOf[i]; if (value.Equals(any)) { return true; } } return false; } public static bool ContainsAny(this string value, params string[] anyOf) { bool result; for (int i = 0; i < anyOf.Length; i++) { string any = anyOf[i]; if (value.Contains(any)) { result = true; return result; } } result = false; return result; } public static bool ContainsAny(this string value, params char[] anyOf) { bool result; for (int i = 0; i < anyOf.Length; i++) { char any = anyOf[i]; if (value.Contains(any.ToString())) { result = true; return result; } } result = false; return result; } public static int IndexOfAny(this string value, params string[] anyOf) { int result; for (int i = 0; i < anyOf.Length; i++) { string any = anyOf[i]; int index = value.IndexOf(any); if (index > -1) { result = index; return result; } } result = -1; return result; } public static string Capitalize(this string value) { string result; if (string.IsNullOrEmpty(value)) { result = value; } else { if (value.Length == 1) { result = value.ToUpper(); } else { result = value.Substring(0, 1).ToUpper() + value.Substring(1); } } return result; } #region Endianness [CLSCompliant(false)] public static ushort SwapEndian(this ushort x) { return (ushort)(x >> 8 | (int)x << 8); } [CLSCompliant(false)] public static ushort SwapEndian(this short x) { return ((ushort)x).SwapEndian(); } [CLSCompliant(false)] public static uint SwapEndian(this uint x) { return x >> 24 | (x << 8 & 16711680u) | (x >> 8 & 65280u) | x << 24; } [CLSCompliant(false)] public static uint SwapEndian(this int x) { return ((uint)x).SwapEndian(); } [CLSCompliant(false)] public static ushort Swap(short x) { return x.SwapEndian(); } [CLSCompliant(false)] public static ushort Swap(ushort x) { return x.SwapEndian(); } [CLSCompliant(false)] public static uint Swap(int x) { return x.SwapEndian(); } [CLSCompliant(false)] public static uint Swap(uint x) { return x.SwapEndian(); } #endregion #region Number [CLSCompliant(false)] public static uint RoundUp(this uint number, int multiple) { uint result; if ((ulong)number % (ulong)((long)multiple) == 0uL) { result = number; } else { result = (uint)((ulong)number + (ulong)((long)multiple - (long)((ulong)number % (ulong)((long)multiple)))); } return result; } [CLSCompliant(false)] public static ulong RoundUp(this ulong number, int multiple) { ulong result; if ((ulong)number % (ulong)((long)multiple) == 0uL) { result = number; } else { result = (ulong)((ulong)number + (ulong)((long)multiple - (long)((ulong)number % (ulong)((long)multiple)))); } return result; } public static int RoundUp(this int number, int multiple) { int result; if (number % multiple == 0) { result = number; } else { result = number + (multiple - number % multiple); } return result; } public static int Digits(this int number) { return number.ToString().Length; } public static int Digits(this long number) { return number.ToString().Length; } public static short UpperWord(this short number) { return (short)(number >> 16); } public static short LowerWord(this short number) { return (short)(number & 0xFFFF); } [CLSCompliant(false)] public static ushort UpperWord(this ushort number) { return (ushort)(number >> 16); } [CLSCompliant(false)] public static ushort LowerWord(this ushort number) { return (ushort)(number & 0xFFFF); } public static int UpperWord(this int number) { return (int)(number >> 16); } public static int LowerWord(this int number) { return (int)(number & 0xFFFF); } [CLSCompliant(false)] public static uint UpperWord(this uint number) { return (uint)(number >> 16); } [CLSCompliant(false)] public static uint LowerWord(this uint number) { return (uint)(number & 0xFFFF); } public static long UpperWord(this long number) { return (long)(number >> 16); } public static long LowerWord(this long number) { return (long)(number & 0xFFFF); } [CLSCompliant(false)] public static ulong UpperWord(this ulong number) { return (ulong)(number >> 16); } [CLSCompliant(false)] public static ulong LowerWord(this ulong number) { return (ulong)(number & 0xFFFF); } #endregion #region StreamReader Extensions public static byte ReadByte(this System.IO.Stream stream, long offset) { stream.Position = offset; return (byte)stream.ReadByte(); } public static byte[] ReadBytes(this System.IO.Stream stream, long offset, int length) { byte[] array = new byte[length]; stream.Position = offset; stream.Read(array, 0, length); return array; } [CLSCompliant(false)] public static byte[] ReadBytes(this System.IO.Stream stream, long offset, uint length) { return stream.ReadBytes(offset, (int)length); } public static short ReadShort(this System.IO.Stream stream, long offset) { byte[] array = new byte[2]; stream.Position = offset; stream.Read(array, 0, 2); return BitConverter.ToInt16(array, 0); } [CLSCompliant(false)] public static ushort ReadUShort(this System.IO.Stream stream, long offset) { byte[] array = new byte[2]; stream.Position = offset; stream.Read(array, 0, 2); return BitConverter.ToUInt16(array, 0); } public static int ReadInt(this System.IO.Stream stream, long offset) { byte[] array = new byte[4]; stream.Position = offset; stream.Read(array, 0, 4); return BitConverter.ToInt32(array, 0); } [CLSCompliant(false)] public static uint ReadUInt(this System.IO.Stream stream, long offset) { byte[] array = new byte[4]; stream.Position = offset; stream.Read(array, 0, 4); return BitConverter.ToUInt32(array, 0); } public static string ReadString(this System.IO.Stream stream, long offset, int maxLength, bool nullTerminator) { string text = string.Empty; stream.Position = offset; for (int i = 0; i < maxLength; i++) { char c = (char)stream.ReadByte(); if (c == '\0' && nullTerminator) { break; } text += c; } return text; } public static string ReadString(this System.IO.Stream stream, long offset, int maxLength) { return stream.ReadString(offset, maxLength, true); } public static string ReadString(this System.IO.Stream stream, long offset, int maxLength, Encoding encoding, bool nullTerminator) { stream.Position = offset; byte[] array = new byte[maxLength]; stream.Read(array, 0, maxLength); string text = encoding.GetString(array); if (nullTerminator) { string arg_2D_0 = text; char[] trimChars = new char[1]; text = arg_2D_0.TrimEnd(trimChars); } return text; } public static string ReadString(this System.IO.Stream stream, long offset, int maxLength, Encoding encoding) { return stream.ReadString(offset, maxLength, encoding, true); } public static byte[] ToByteArray(this System.IO.Stream stream) { long oldpos = stream.Position; byte[] array = new byte[(int)((IntPtr)stream.Length)]; stream.Position = 0L; stream.Read(array, 0, array.Length); stream.Position = oldpos; return array; } #endregion #region StreamWriter Extensions public static void Write(this System.IO.Stream stream, byte value) { stream.WriteByte(value); } public static void Write(this System.IO.Stream stream, short value) { stream.Write(BitConverter.GetBytes(value), 0, 2); } [CLSCompliant(false)] public static void Write(this System.IO.Stream stream, ushort value) { stream.Write(BitConverter.GetBytes(value), 0, 2); } public static void Write(this System.IO.Stream stream, int value) { stream.Write(BitConverter.GetBytes(value), 0, 4); } [CLSCompliant(false)] public static void Write(this System.IO.Stream stream, uint value) { stream.Write(BitConverter.GetBytes(value), 0, 4); } public static void Write(this System.IO.Stream stream, byte[] values) { stream.Write(values, 0, values.Length); } public static void Write(this System.IO.Stream stream, string value) { for (int i = 0; i < value.Length; i++) { stream.WriteByte((byte)value[i]); } } public static void Write(this System.IO.Stream stream, string value, int length) { for (int i = 0; i < length; i++) { if (i < value.Length) { stream.WriteByte((byte)value[i]); } else { stream.WriteByte(0); } } } public static void Write(this System.IO.Stream stream, string value, int strLength, int length) { for (int i = 0; i < length; i++) { if (i < value.Length && i < strLength) { stream.WriteByte((byte)value[i]); } else { stream.WriteByte(0); } } } public static void Write(this System.IO.Stream stream, string value, int strLength, int length, Encoding encoding) { byte[] bytes = encoding.GetBytes(value); int num = 0; while (bytes.Length > strLength) { num++; bytes = encoding.GetBytes(value.Substring(0, value.Length - num)); } for (int i = 0; i < length; i++) { if (i < bytes.Length && i < strLength) { stream.WriteByte(bytes[i]); } else { stream.WriteByte(0); } } } public static void Write(this System.IO.Stream output, System.IO.Stream input) { byte[] array = new byte[4096]; input.Position = 0L; int count; while ((count = input.Read(array, 0, array.Length)) > 0) { output.Write(array, 0, count); } } public static void Write(this System.IO.Stream output, System.IO.MemoryStream input) { input.Position = 0L; input.WriteTo(output); } public static void Write(this System.IO.Stream output, System.IO.Stream input, long offset, long length) { byte[] array = new byte[4096]; input.Position = offset; int count; while ((count = input.Read(array, 0, (input.Position + (long)array.Length > offset + length) ? ((int)(offset + length - input.Position)) : ((int)((long)array.Length)))) > 0) { output.Write(array, 0, count); } } public static System.IO.MemoryStream Copy(this System.IO.Stream input) { System.IO.MemoryStream memoryStream = new System.IO.MemoryStream((int)input.Length); byte[] array = new byte[4096]; input.Position = 0L; int count; while ((count = input.Read(array, 0, array.Length)) > 0) { memoryStream.Write(array, 0, count); } return memoryStream; } public static System.IO.MemoryStream Copy(this System.IO.Stream input, long offset, int length) { System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(length); byte[] array = new byte[4096]; input.Position = offset; int count; while ((count = input.Read(array, 0, (input.Position + (long)array.Length > offset + (long)length) ? ((int)(offset + (long)length - input.Position)) : ((int)((long)array.Length)))) > 0) { memoryStream.Write(array, 0, count); } return memoryStream; } [CLSCompliant(false)] public static System.IO.MemoryStream Copy(this System.IO.Stream input, long offset, uint length) { System.IO.MemoryStream memoryStream = new System.IO.MemoryStream((int)length); byte[] array = new byte[4096]; input.Position = offset; int count; while ((count = input.Read(array, 0, (input.Position + (long)array.Length > offset + (long)((ulong)length)) ? ((int)(offset + (long)((ulong)length) - input.Position)) : ((int)((long)array.Length)))) > 0) { memoryStream.Write(array, 0, count); } return memoryStream; } #endregion #region Strings public static bool IsAllUpperCase(this string str) { return (!(new System.Text.RegularExpressions.Regex("[a-z]")).IsMatch(str)); } public static string UrlEncode(this string value) { return value; } public static string UrlDecode(this string input) { StringBuilder output = new StringBuilder(); for (int i = 0; i < input.Length; i++) { if (input[i] == '%') { char c = input[i + 1]; string arg_45_0 = c.ToString(); c = input[i + 2]; string numeric = arg_45_0 + c.ToString(); int hexcode = int.Parse(numeric, System.Globalization.NumberStyles.HexNumber); i += 2; output.Append((char)hexcode); } else { output.Append(input[i]); } } return output.ToString(); } public static bool Match(this string input, params string[] filters) { foreach (string filter in filters) { if (input.Match(filter)) return true; } return false; } public static bool Match(this string input, string filter) { if (filter == null) return false; string wildcardToRegex = "^" + System.Text.RegularExpressions.Regex.Escape(filter).Replace("\\*", ".*").Replace("\\?", ".") + "$"; return new System.Text.RegularExpressions.Regex(wildcardToRegex).IsMatch(input); } /// /// Removes all characters past and including the first occurrence of a /// NUL (0x00) byte from the given string. /// /// /// All characters before the first occurrence of a NUL (0x00) byte in /// . /// /// The string to trim. public static string TrimNull(this string value) { int i = value.IndexOf('\0'); if (i > -1) return value.Substring(0, i); return value; } public static string Format(this string input, Dictionary formatWhat) { return Format(input, formatWhat, "$(", ")"); } public static string Format(this string input, Dictionary formatWhat, string formatBegin, string formatEnd) { string val = input; foreach (KeyValuePair kvp in formatWhat) { val = val.Replace(formatBegin + kvp.Key + formatEnd, kvp.Value); } return val; } /// /// Inserts the specified value "count" times, with "spacing" characters between. /// /// The number of times to insert value. /// The amount of characters to leave between insertions. /// The value to insert. /// public static string Insert(this string input, int count, int spacing, string value) { int j = 0; string retval = String.Empty; for (int i = 0; i < count; i++) { retval += input.Substring(j, spacing) + value; j += spacing; } retval += input.Substring(j); return retval; } #endregion #region Dictionary public static KeyValuePair[] ToArray(this Dictionary dictionary) { System.Collections.Generic.List> list = new List>(); foreach (KeyValuePair kvp in dictionary) { list.Add(kvp); } return list.ToArray(); } public static TValue GetValueOrDefault(this Dictionary dictionary, TKey key, TValue value = default(TValue)) { if (dictionary.ContainsKey(key)) { return dictionary[key]; } return value; } #endregion #region Arrays public static void Fill(this T[] data, T value) { for (int i = 0; i < data.Length; i++) { data[i] = value; } } #endregion public static long RoundToNearestPowerOf2(this long input) { long v = input; v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } [CLSCompliant(false)] public static ulong RoundToNearestPowerOf2(this ulong input) { ulong v = input; v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } } }