//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. // //----------------------------------------------------------------------- namespace Microsoft.Isam.Esent.Interop { using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; /// /// Static utility methods. /// internal static class Util { /// /// Compare two byte arrays to see if they have the same content. /// /// The first array. /// The second array. /// The offset to start comparing at. /// The number of bytes to compare. /// True if the arrays are equal, false otherwise. public static bool ArrayEqual(IList a, IList b, int offset, int count) { if (null == a || null == b) { return ReferenceEquals(a, b); } for (int i = 0; i < count; ++i) { if (a[offset + i] != b[offset + i]) { return false; } } return true; } /// /// Return a string containing (some of) the bytes. /// /// The data to dump. /// The starting offset. /// The count. /// A string version of the data. public static string DumpBytes(byte[] data, int offset, int count) { if (null == data) { return ""; } if (0 == count) { return string.Empty; } if (offset < 0 || count < 0 || offset >= data.Length || offset + count > data.Length) { return ""; } const int MaxBytesToPrint = 8; StringBuilder sb = new StringBuilder(); sb.Append(BitConverter.ToString(data, offset, Math.Min(count, MaxBytesToPrint))); if (count > MaxBytesToPrint) { // The output was truncated sb.AppendFormat(CultureInfo.InvariantCulture, "... ({0} bytes)", count); } return sb.ToString(); } /// /// Compares two objects with ContentEquals. /// If both are null, there are considered equal. /// /// A type that implements IContentEquatable. /// First object to compare. /// Second object to compare. /// Whether the two objects are equal. public static bool ObjectContentEquals(T left, T right) where T : class, IContentEquatable { if (null == left || null == right) { return ReferenceEquals(left, right); } return left.ContentEquals(right); } /// /// Compares two objects with ContentEquals. /// If both are null, there are considered equal. /// /// A type that implements IContentEquatable. /// First object to compare. /// Second object to compare. /// The number of entries to compare. /// Whether the two objects are equal. public static bool ArrayObjectContentEquals(T[] left, T[] right, int length) where T : class, IContentEquatable { if (null == left || null == right) { return ReferenceEquals(left, right); } for (int i = 0; i < length; ++i) { if (!ObjectContentEquals(left[i], right[i])) { return false; } } // All the individual members are equal, all of the elements of the arrays are // equal, so they must be equal! return true; } /// /// Compares items in two arrays using Equals. /// If both arrays are null, there are considered equal. /// /// A value type. /// First array to compare. /// Second array to compare. /// The number of entries to compare. /// Whether the two arrays are equal. public static bool ArrayStructEquals(T[] left, T[] right, int length) where T : struct { if (null == left || null == right) { return ReferenceEquals(left, right); } for (int i = 0; i < length; ++i) { if (!left[i].Equals(right[i])) { return false; } } // All the individual members are equal, all of the elements of the arrays are // equal, so they must be equal! return true; } /// /// Clone an array of objects. /// /// The type of object in the array. /// The values to clone. /// A clone of the values. public static T[] DeepCloneArray(T[] value) where T : class, IDeepCloneable { T[] clone = null; if (null != value) { clone = new T[value.Length]; for (int i = 0; i < clone.Length; ++i) { clone[i] = (null == value[i]) ? null : value[i].DeepClone(); } } return clone; } /// /// Given a list of hash codes calculate a hash of the hashes. /// /// The sub hash codes. /// A hash of the hash codes. public static int CalculateHashCode(IEnumerable hashes) { int hash = 0; foreach (int h in hashes) { hash ^= h; unchecked { hash *= 33; } } return hash; } /// /// Add a trailing directory separator character to the string. /// /// The directory. /// The directory with a separator character added (if necesary). public static string AddTrailingDirectorySeparator(string dir) { if (!string.IsNullOrEmpty(dir)) { var sepChars = new[] { LibraryHelpers.DirectorySeparatorChar, LibraryHelpers.AltDirectorySeparatorChar }; return string.Concat(dir.TrimEnd(sepChars), LibraryHelpers.DirectorySeparatorChar); } return dir; } /// /// Converts a unicode string to a null-terminated Ascii byte array. /// /// The unicode string to be converted. /// The byte array with a null-terminated Ascii representation of the given string. public static byte[] ConvertToNullTerminatedAsciiByteArray(string value) { if (value == null) { return null; } byte[] output = new byte[value.Length + 1]; LibraryHelpers.EncodingASCII.GetBytes(value, 0, value.Length, output, 0); output[output.Length - 1] = (byte)0; return output; } /// /// Converts a unicode string to a null-terminated Unicode byte array. /// /// The unicode string to be converted. /// The byte array with a null-terminated Unicode representation of the given string. public static byte[] ConvertToNullTerminatedUnicodeByteArray(string value) { if (value == null) { return null; } int byteArrayLength = Encoding.Unicode.GetByteCount(value); byte[] output = new byte[byteArrayLength + 2]; Encoding.Unicode.GetBytes(value, 0, value.Length, output, 0); output[output.Length - 2] = (byte)0; output[output.Length - 1] = (byte)0; return output; } } }