//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. // //----------------------------------------------------------------------- namespace Microsoft.Isam.Esent.Interop { using System; using System.Collections.Generic; using System.Globalization; /// /// Provide methods to convert data and flags between /// Win32 and the .NET Framework. /// public static class Conversions { /// /// Maps a CompareOption enumeration to the corresponding LCMapString flag. /// private static readonly IDictionary CompareOptionsToLcmapFlags; /// /// Maps an LCMapString flag to the corresponding CompareOption enumeration. /// private static readonly IDictionary LcmapFlagsToCompareOptions; /// /// Initializes static members of the Conversions class. This sets up the /// conversion mapping dictionaries. /// static Conversions() { // Rather than creating both dictionaries, define one as the inverse of the other. CompareOptionsToLcmapFlags = new Dictionary { { CompareOptions.IgnoreCase, NativeMethods.NORM_IGNORECASE }, { CompareOptions.IgnoreKanaType, NativeMethods.NORM_IGNOREKANATYPE }, { CompareOptions.IgnoreNonSpace, NativeMethods.NORM_IGNORENONSPACE }, { CompareOptions.IgnoreSymbols, NativeMethods.NORM_IGNORESYMBOLS }, { CompareOptions.IgnoreWidth, NativeMethods.NORM_IGNOREWIDTH }, { CompareOptions.StringSort, NativeMethods.SORT_STRINGSORT } }; LcmapFlagsToCompareOptions = InvertDictionary(CompareOptionsToLcmapFlags); } /// /// Convert a double (OA date time format) to a DateTime. Unlike DateTime.FromOADate /// this doesn't throw exceptions. /// /// The double value. /// A DateTime. public static DateTime ConvertDoubleToDateTime(double d) { try { return LibraryHelpers.FromOADate(d); } catch (ArgumentException) { // Not all double values are valid OADates. We deal with out-of-range values // by returning either min or max return d < 0 ? DateTime.MinValue : DateTime.MaxValue; } } /// /// Given flags for LCMapFlags, turn them into compare options. Unknown options /// are ignored. /// /// LCMapString flags. /// CompareOptions describing the (known) flags. [CLSCompliant(false)] public static CompareOptions CompareOptionsFromLCMapFlags(uint lcmapFlags) { // This should be a template, but there isn't an elegant way to express than with C# generics CompareOptions options = CompareOptions.None; foreach (uint flag in LcmapFlagsToCompareOptions.Keys) { if (flag == (lcmapFlags & flag)) { options |= LcmapFlagsToCompareOptions[flag]; } } return options; } /// /// Give CompareOptions, turn them into flags from LCMapString. Unknown options are ignored. /// /// The options to convert. /// The LCMapString flags that match the compare options. Unsupported options are ignored. [CLSCompliant(false)] public static uint LCMapFlagsFromCompareOptions(CompareOptions compareOptions) { // This should be a template, but there isn't an elegant way to express than with C# generics uint flags = 0; foreach (CompareOptions option in CompareOptionsToLcmapFlags.Keys) { if (option == (compareOptions & option)) { flags |= CompareOptionsToLcmapFlags[option]; } } return flags; } /// /// Given a Key=>Value dictionary create an inverted dictionary that maps Value=>Key. /// /// The new value type (the key of the current dictionary). /// The new key type (the value if the current dictionary). /// The dictionary to invert. /// An inverted dictionary. private static IDictionary InvertDictionary(ICollection> dict) { var invertedDict = new Dictionary(dict.Count); foreach (KeyValuePair entry in dict) { invertedDict.Add(entry.Value, entry.Key); } return invertedDict; } /// /// This class contains the unmanaged constants used in the conversion. /// internal static class NativeMethods { #region Win32 Constants /// /// Ignore case. /// public const uint NORM_IGNORECASE = 0x00000001; /// /// Ignore nonspacing chars. /// public const uint NORM_IGNORENONSPACE = 0x00000002; /// /// Ignore symbols. /// public const uint NORM_IGNORESYMBOLS = 0x00000004; /// /// Ignore kanatype. /// public const uint NORM_IGNOREKANATYPE = 0x00010000; /// /// Ignore width. /// public const uint NORM_IGNOREWIDTH = 0x00020000; /// /// Treat punctuation the same as symbols. /// public const uint SORT_STRINGSORT = 0x00001000; /// /// Produce a normalized wide-character sort key. /// public const uint LCMAP_SORTKEY = 0x00000400; #endregion Win32 Constants } } }