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