// --------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // --------------------------------------------------------------------------- // --------------------------------------------------------------------- // // // --------------------------------------------------------------------- namespace Microsoft.Database.Isam { using System; using System.Globalization; using System.Text; using Microsoft.Isam.Esent.Interop; using Microsoft.Isam.Esent.Interop.Vista; /// /// Convert an array of Bytes to/from a CLR object, given the type of the underlying column /// /// /// The Interop layer operates with Byte arrays. The Converter class provides methods to convert /// an array of bytes retrieved from the Interop layer into a CLR object and to convert a CLR /// object into an array of bytes. /// internal class Converter { /// /// Given a column type and an object, convert the object to an array of bytes /// /// /// This method uses System.Convert and System.BitConverter to do automatic type conversion (e.g. String -> Boolean) /// /// The type of the database column that this object is to be stored in /// For text columns, is the column an ASCII column. Ignored for other types /// The object to be converted /// An array of bytes representing the object /// This conversion is not supported /// Unknown column type public static byte[] BytesFromObject(JET_coltyp type, bool isASCII, object o) { if (o is DBNull) { return null; } if (null == o) { return null; } switch (type) { case JET_coltyp.Nil: throw new ArgumentOutOfRangeException("type", "Nil is not valid"); case JET_coltyp.Bit: return BitConverter.GetBytes(Convert.ToBoolean(o)); case JET_coltyp.UnsignedByte: byte[] bytes = new byte[1]; bytes[0] = (byte)o; return bytes; case JET_coltyp.Short: return BitConverter.GetBytes(Convert.ToInt16(o)); case JET_coltyp.Long: return BitConverter.GetBytes(Convert.ToInt32(o)); case VistaColtyp.LongLong: return BitConverter.GetBytes(Convert.ToInt64(o)); case JET_coltyp.Currency: return BitConverter.GetBytes(Convert.ToInt64(o)); case JET_coltyp.IEEESingle: return BitConverter.GetBytes(Convert.ToSingle(o)); case JET_coltyp.IEEEDouble: return BitConverter.GetBytes(Convert.ToDouble(o)); case VistaColtyp.UnsignedShort: return BitConverter.GetBytes(Convert.ToUInt16(o)); case VistaColtyp.UnsignedLong: return BitConverter.GetBytes(Convert.ToUInt32(o)); case JET_coltyp.Binary: return (byte[])o; case JET_coltyp.LongBinary: return (byte[])o; case JET_coltyp.DateTime: // Internally DateTime is stored as a double, mapping to a COLEDateTime DateTime datetime = Convert.ToDateTime(o); double oleDateTime = datetime.ToOADate(); return BitConverter.GetBytes(oleDateTime); case JET_coltyp.Text: if (isASCII) { return Encoding.ASCII.GetBytes(o.ToString()); } else { return Encoding.Unicode.GetBytes(o.ToString()); } case JET_coltyp.LongText: if (isASCII) { return Encoding.ASCII.GetBytes(o.ToString()); } else { return Encoding.Unicode.GetBytes(o.ToString()); } case VistaColtyp.GUID: if (o is string) { Guid guid = new Guid((string)o); return guid.ToByteArray(); } else if (o is byte[]) { Guid guid = new Guid((byte[])o); return guid.ToByteArray(); } else { // if o isn't a Guid, this will throw an exception return ((Guid)o).ToByteArray(); } default: throw new ArgumentOutOfRangeException("type", "unknown type"); } } /// /// Given a column type and a Byte array, convert the bytes into a CLR object /// /// /// This method uses System.BitConverter to do the conversion /// /// The type of the database column that this bytes were retrieved from /// For text columns, is the column an ASCII column. Ignored for other types /// The bytes to be converted /// An Object constructed from the bytes or DBNull for a null value /// Unknown column type or incorrect Byte array size public static object ObjectFromBytes(JET_coltyp type, bool isASCII, byte[] value) { if (null == value) { return DBNull.Value; } switch (type) { case JET_coltyp.Nil: throw new ArgumentOutOfRangeException("type", "Nil is not valid"); case JET_coltyp.Bit: return BitConverter.ToBoolean(value, 0); case JET_coltyp.UnsignedByte: return value[0]; case JET_coltyp.Short: return BitConverter.ToInt16(value, 0); case JET_coltyp.Long: return BitConverter.ToInt32(value, 0); case VistaColtyp.LongLong: return BitConverter.ToInt64(value, 0); case JET_coltyp.Currency: return BitConverter.ToInt64(value, 0); case JET_coltyp.IEEESingle: return BitConverter.ToSingle(value, 0); case JET_coltyp.IEEEDouble: return BitConverter.ToDouble(value, 0); case VistaColtyp.UnsignedShort: return BitConverter.ToUInt16(value, 0); case VistaColtyp.UnsignedLong: return BitConverter.ToUInt32(value, 0); case JET_coltyp.Binary: return value; case JET_coltyp.LongBinary: return value; case JET_coltyp.Text: if (isASCII) { return new string(Encoding.ASCII.GetChars(value)); } else { return new string(Encoding.Unicode.GetChars(value)); } case JET_coltyp.LongText: if (isASCII) { return new string(Encoding.ASCII.GetChars(value)); } else { return new string(Encoding.Unicode.GetChars(value)); } case VistaColtyp.GUID: return new Guid(value); case JET_coltyp.DateTime: // Internally DateTime is stored as a double, mapping to a COLEDateTime return DateTime.FromOADate(BitConverter.ToDouble(value, 0)); default: throw new ArgumentOutOfRangeException("type", "unknown type"); } } /// /// Converts from to . /// /// The value to convert. /// A value equivalent to . /// CompareOptions.Ordinal is not supported;compareOptions internal static UnicodeIndexFlags UnicodeFlagsFromCompareOptions(CompareOptions options) { UnicodeIndexFlags unicodeflags = UnicodeIndexFlags.None; if (IsCompareOptionSet(options, CompareOptions.IgnoreCase)) { unicodeflags |= UnicodeIndexFlags.CaseInsensitive; } if (IsCompareOptionSet(options, CompareOptions.IgnoreKanaType)) { unicodeflags |= UnicodeIndexFlags.KanaInsensitive; } if (IsCompareOptionSet(options, CompareOptions.IgnoreNonSpace)) { unicodeflags |= UnicodeIndexFlags.AccentInsensitive; } if (IsCompareOptionSet(options, CompareOptions.IgnoreSymbols)) { unicodeflags |= UnicodeIndexFlags.IgnoreSymbols; } if (IsCompareOptionSet(options, CompareOptions.IgnoreWidth)) { unicodeflags |= UnicodeIndexFlags.WidthInsensitive; } if (IsCompareOptionSet(options, CompareOptions.StringSort)) { unicodeflags |= UnicodeIndexFlags.StringSort; } if (IsCompareOptionSet(options, CompareOptions.Ordinal)) { throw new ArgumentException("CompareOptions.Ordinal is not supported", "compareOptions"); } return unicodeflags; } /// /// Converts unicodeIndexFlags to a ulong, suitable for dwMapFlags. /// /// A UnicodeIndexFlags value. /// A value suitable for calling by LCMapString. internal static uint MapFlagsFromUnicodeIndexFlags(UnicodeIndexFlags unicodeIndexFlags) { return (uint)unicodeIndexFlags; } /// /// Converts to a , suitable for ESE function calls. /// /// A value. /// A ColumndefGrbit suitable for function calls. internal static ColumndefGrbit ColumndefGrbitFromColumnFlags(ColumnFlags columnFlags) { return (ColumndefGrbit)columnFlags; } /// /// Determines whether all of the the specified options in /// are set in . /// /// The value to test. /// The optionsMask. /// /// Whether all of the the specified options in /// private static bool IsCompareOptionSet(CompareOptions optionsToTest, CompareOptions optionsMask) { if ((optionsToTest & optionsMask) == optionsMask) { return true; } return false; } } }