//-----------------------------------------------------------------------
//
// 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;
}
}
}