| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574 |
- //------------------------------------------------------------------------------
- // <copyright file="SqlNorm.cs" company="Microsoft Corporation">
- // Copyright (c) Microsoft Corporation. All Rights Reserved.
- // Information Contained Herein is Proprietary and Confidential.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="true">daltudov</owner>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="false">beysims</owner>
- // <owner current="true" primary="false">[....]</owner>
- // <owner current="true" primary="false">vadimt</owner>
- // <owner current="false" primary="false">[....]</owner>
- // <owner current="false" primary="false">venkar</owner>
- //------------------------------------------------------------------------------
- //devnote: perf optimization: consider changing the calls to Array.Reverse to inline unsafe code
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Data;
- using System.IO;
- using System.Globalization;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using System.Security.Permissions;
- using System.Text;
- using System.Runtime.CompilerServices;
- namespace Microsoft.SqlServer.Server {
-
- // The class that holds the offset, field, and normalizer for
- // a particular field.
- internal sealed class FieldInfoEx: IComparable {
- internal readonly int offset;
- internal readonly FieldInfo fieldInfo;
- internal readonly Normalizer normalizer;
- internal FieldInfoEx(FieldInfo fi, int offset, Normalizer normalizer) {
- this.fieldInfo = fi;
- this.offset = offset;
- Debug.Assert(normalizer!=null, "normalizer argument should not be null!");
- this.normalizer = normalizer;
- }
- // Sort fields by field offsets.
- public int CompareTo(object other) {
- FieldInfoEx otherF = other as FieldInfoEx;
- if (otherF == null)
- return -1;
- return this.offset.CompareTo(otherF.offset);
- }
- }
- // The most complex normalizer, a udt normalizer
- internal sealed class BinaryOrderedUdtNormalizer: Normalizer {
- internal readonly FieldInfoEx[] m_fieldsToNormalize;
- private int m_size;
- private byte[] m_PadBuffer;
- internal readonly object NullInstance;
- //a boolean that tells us if a udt is a "top-level" udt,
- //i.e. one that does not require a null byte header.
- private bool m_isTopLevelUdt;
- [System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess=true)]
- private FieldInfo[] GetFields (Type t) {
- return t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
- }
- internal BinaryOrderedUdtNormalizer(Type t, bool isTopLevelUdt) {
- this.m_skipNormalize = false;
- if (this.m_skipNormalize) {
- //if skipping normalization, dont write the null
- //byte header for IsNull
- this.m_isTopLevelUdt = true;
- }
- //top level udt logic is disabled until we decide
- //what to do about nested udts
- this.m_isTopLevelUdt = true;
- // else
- // this.m_isTopLevelUdt = isTopLevelUdt;
- //get all the fields
- FieldInfo[] fields = GetFields (t);
- m_fieldsToNormalize = new FieldInfoEx[fields.Length];
- int i = 0;
- foreach (FieldInfo fi in fields) {
- int offset = Marshal.OffsetOf(fi.DeclaringType, fi.Name).ToInt32();
- m_fieldsToNormalize[i++] = new FieldInfoEx(fi, offset, GetNormalizer(fi.FieldType));
- }
- //sort by offset
- Array.Sort(m_fieldsToNormalize);
- //if this is not a top-level udt, do setup for null values.
- //null values need to compare less than all other values,
- //so prefix a null byte indicator.
- if (!this.m_isTopLevelUdt) {
- //get the null value for this type, special case for sql types, which
- //have a null field
- if (typeof(System.Data.SqlTypes.INullable).IsAssignableFrom(t)) {
- PropertyInfo pi = t.GetProperty("Null",
- BindingFlags.Public | BindingFlags.Static);
- if (pi == null || pi.PropertyType != t) {
- FieldInfo fi = t.GetField("Null", BindingFlags.Public | BindingFlags.Static);
- if (fi == null || fi.FieldType != t)
- throw new Exception("could not find Null field/property in nullable type " + t);
- else
- this.NullInstance = fi.GetValue(null);
- }
- else {
- this.NullInstance = pi.GetValue(null, null);
- }
- //create the padding buffer
- this.m_PadBuffer = new byte[this.Size-1];
- }
- }
- }
- internal bool IsNullable {
- get {
- return this.NullInstance != null;
- }
- }
- // Normalize the top-level udt
- internal void NormalizeTopObject(object udt, Stream s) {
- Normalize(null, udt, s);
- }
- // Denormalize a top-level udt and return it
- internal object DeNormalizeTopObject(Type t, Stream s) {
- return DeNormalizeInternal(t, s);
- }
- // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set.
- [MethodImpl(MethodImplOptions.NoInlining)]
- private object DeNormalizeInternal(Type t, Stream s) {
- object result = null;
- //if nullable and not the top object, read the null marker
- if (!this.m_isTopLevelUdt && typeof(System.Data.SqlTypes.INullable).IsAssignableFrom(t)) {
- byte nullByte = (byte) s.ReadByte();
- if (nullByte == 0) {
- result = this.NullInstance;
- s.Read(m_PadBuffer, 0, m_PadBuffer.Length);
- return result;
- }
- }
- if (result == null)
- result = Activator.CreateInstance(t);
- foreach (FieldInfoEx myField in m_fieldsToNormalize) {
- myField.normalizer.DeNormalize(myField.fieldInfo, result, s);
- }
- return result;
- }
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- // if (fi != null)
- // Console.WriteLine("normalizing " + fi.FieldType + " pos " + s.Position);
- object inner;
- if (fi == null) {
- inner = obj;
- }
- else {
- inner = GetValue(fi, obj);
- }
- //If nullable and not the top object, write a null indicator
- System.Data.SqlTypes.INullable oNullable = inner as System.Data.SqlTypes.INullable;
- if (oNullable != null && !this.m_isTopLevelUdt) {
- if (oNullable.IsNull) {
- s.WriteByte(0);
- s.Write(m_PadBuffer, 0, m_PadBuffer.Length);
- return;
- }
- else {
- s.WriteByte(1);
- }
- }
- foreach (FieldInfoEx myField in m_fieldsToNormalize) {
- myField.normalizer.Normalize(myField.fieldInfo, inner, s);
- }
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- SetValue(fi, recvr, DeNormalizeInternal(fi.FieldType, s));
- }
- internal override int Size {
- get {
- if (m_size != 0)
- return m_size;
- if (this.IsNullable && !this.m_isTopLevelUdt)
- m_size = 1;
- foreach (FieldInfoEx myField in m_fieldsToNormalize) {
- m_size += myField.normalizer.Size;
- }
- return m_size;
- }
- }
- }
- internal abstract class Normalizer {
- /*
- protected internal static string GetString(byte[] array)
- {
- StringBuilder sb = new StringBuilder();
- //sb.Append("0x");
- foreach (byte b in array)
- {
- sb.Append(b.ToString("X2", CultureInfo.InvariantCulture));
- }
- return sb.ToString();
- }
- */
- protected bool m_skipNormalize;
- /*
- internal static bool IsByteOrderedUdt(Type t)
- {
- SqlUserDefinedTypeAttribute a = SerializationHelper.GetUdtAttribute(t);
- return a.IsByteOrdered;
- }
- */
- internal static Normalizer GetNormalizer(Type t) {
- Normalizer n = null;
- if (t.IsPrimitive) {
- if (t == typeof(byte))
- n = new ByteNormalizer();
- else if (t == typeof(sbyte))
- n = new SByteNormalizer();
- else if (t == typeof(bool))
- n = new BooleanNormalizer();
- else if (t == typeof(short))
- n = new ShortNormalizer();
- else if (t == typeof(ushort))
- n = new UShortNormalizer();
- else if (t == typeof(int))
- n = new IntNormalizer();
- else if (t == typeof(uint))
- n = new UIntNormalizer();
- else if (t == typeof(float))
- n = new FloatNormalizer();
- else if (t == typeof(double))
- n = new DoubleNormalizer();
- else if (t == typeof(long))
- n = new LongNormalizer();
- else if (t == typeof(ulong))
- n = new ULongNormalizer();
- }
- else if (t.IsValueType) {
- n = new BinaryOrderedUdtNormalizer(t, false);
- }
- if (n == null)
- throw new Exception(Res.GetString(Res.Sql_CanotCreateNormalizer, t.FullName));
- n.m_skipNormalize = false;
- return n;
- }
- internal abstract void Normalize(FieldInfo fi, object recvr, Stream s);
- internal abstract void DeNormalize(FieldInfo fi, object recvr, Stream s);
- protected void FlipAllBits(byte[] b) {
- for (int i = 0; i < b.Length; i++)
- b[i] = (byte) ~b[i];
- }
- [System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess=true)]
- protected object GetValue(FieldInfo fi, object obj) {
- return fi.GetValue(obj);
- }
- [System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess=true)]
- protected void SetValue(FieldInfo fi, object recvr, object value) {
- fi.SetValue(recvr, value);
- }
- internal abstract int Size { get; }
- }
- internal sealed class BooleanNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- bool b = (bool) GetValue(fi, obj);
- // Console.WriteLine("normalized " + fi.FieldType + " " + fi.GetValue(obj)
- // + " to " + (b?"01":"00") + " pos " + s.Position);
- s.WriteByte((byte)(b?1:0));
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte b = (byte) s.ReadByte();
- SetValue(fi, recvr, b==1);
- }
-
- internal override int Size { get { return 1; } }
- }
- // I could not find a simple way to convert a sbyte to a byte
- // and vice versa in the framework api. Convert.ToSByte() checks that
- // the value is in range.
- // So, we just do the conversion inline.
- internal sealed class SByteNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- sbyte sb = (sbyte) GetValue(fi, obj);
- byte b;
- unchecked {
- b = (byte) sb;
- }
- if (!this.m_skipNormalize)
- b ^= 0x80; //flip the sign bit
- s.WriteByte(b);
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte b = (byte) s.ReadByte();
- if (!this.m_skipNormalize)
- b ^= 0x80; //flip the sign bit
- sbyte sb;
- unchecked {
- sb = (sbyte) b;
- }
- SetValue(fi, recvr, sb);
- }
-
- internal override int Size { get { return 1; } }
- }
- internal sealed class ByteNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- byte b = (byte) GetValue(fi, obj);
- s.WriteByte(b);
- }
-
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte b = (byte) s.ReadByte();
- SetValue(fi, recvr, b);
- }
- internal override int Size { get { return 1; } }
- }
- internal sealed class ShortNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- byte[] b = BitConverter.GetBytes((short) GetValue(fi, obj));
- if (!m_skipNormalize) {
- Array.Reverse(b);
- b[0] ^= 0x80;
- }
- s.Write(b, 0, b.Length);
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte[] b = new Byte[2];
- s.Read(b, 0, b.Length);
- if (!m_skipNormalize) {
- b[0] ^= 0x80;
- Array.Reverse(b);
- }
- SetValue(fi, recvr, BitConverter.ToInt16(b, 0));
- }
- internal override int Size { get { return 2; } }
- }
- internal sealed class UShortNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- byte[] b = BitConverter.GetBytes((ushort) GetValue(fi, obj));
- if (!m_skipNormalize) {
- Array.Reverse(b);
- }
- s.Write(b, 0, b.Length);
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte[] b = new Byte[2];
- s.Read(b, 0, b.Length);
- if (!m_skipNormalize) {
- Array.Reverse(b);
- }
- SetValue(fi, recvr, BitConverter.ToUInt16(b, 0));
- }
- internal override int Size { get { return 2; } }
- }
- internal sealed class IntNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- byte[] b = BitConverter.GetBytes((int) GetValue(fi, obj));
- if (!m_skipNormalize) {
- Array.Reverse(b);
- b[0] ^= 0x80;
- }
- // Console.WriteLine("normalized " + fi.FieldType + " " + fi.GetValue(obj)
- // + " to " + GetString(b) + " pos " + s.Position);
- s.Write(b, 0, b.Length);
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte[] b = new Byte[4];
- s.Read(b, 0, b.Length);
- if (!m_skipNormalize) {
- b[0] ^= 0x80;
- Array.Reverse(b);
- }
- SetValue(fi, recvr, BitConverter.ToInt32(b, 0));
- }
- internal override int Size { get { return 4; } }
- }
- internal sealed class UIntNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- byte[] b = BitConverter.GetBytes((uint) GetValue(fi, obj));
- if (!m_skipNormalize) {
- Array.Reverse(b);
- }
- s.Write(b, 0, b.Length);
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte[] b = new byte[4];
- s.Read(b, 0, b.Length);
- if (!m_skipNormalize) {
- Array.Reverse(b);
- }
- SetValue(fi, recvr, BitConverter.ToUInt32(b, 0));
- }
- internal override int Size { get { return 4; } }
- }
- internal sealed class LongNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- byte[] b = BitConverter.GetBytes((long) GetValue(fi, obj));
- if (!m_skipNormalize) {
- Array.Reverse(b);
- b[0] ^= 0x80;
- }
- s.Write(b, 0, b.Length);
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte[] b = new Byte[8];
- s.Read(b, 0, b.Length);
- if (!m_skipNormalize) {
- b[0] ^= 0x80;
- Array.Reverse(b);
- }
- SetValue(fi, recvr, BitConverter.ToInt64(b, 0));
- }
- internal override int Size { get { return 8; } }
- }
- internal sealed class ULongNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- byte[] b = BitConverter.GetBytes((ulong) GetValue(fi, obj));
- if (!m_skipNormalize) {
- Array.Reverse(b);
- }
- // Console.WriteLine("normalized " + fi.FieldType + " " + fi.GetValue(obj)
- // + " to " + GetString(b));
- s.Write(b, 0, b.Length);
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte[] b = new Byte[8];
- s.Read(b, 0, b.Length);
- if (!m_skipNormalize) {
- Array.Reverse(b);
- }
- SetValue(fi, recvr, BitConverter.ToUInt64(b, 0));
- }
-
- internal override int Size { get { return 8; } }
- }
- internal sealed class FloatNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- float f = (float) GetValue(fi, obj);
- byte[] b = BitConverter.GetBytes(f);
- if (!m_skipNormalize) {
- Array.Reverse(b);
- if ((b[0] & 0x80) == 0) {
- // This is a positive number.
- // Flip the highest bit
- b[0] ^= 0x80;
- }
- else {
- // This is a negative number.
- // If all zeroes, means it was a negative zero.
- // Treat it same as positive zero, so that
- // the normalized key will compare equal.
- if (f < 0)
- FlipAllBits(b);
- }
- }
- s.Write(b, 0, b.Length);
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte[] b = new Byte[4];
- s.Read(b, 0, b.Length);
- if (!m_skipNormalize) {
- if ((b[0] & 0x80) > 0) {
- // This is a positive number.
- // Flip the highest bit
- b[0] ^= 0x80;
- }
- else {
- // This is a negative number.
- FlipAllBits(b);
- }
- Array.Reverse(b);
- }
- SetValue(fi, recvr, BitConverter.ToSingle(b, 0));
- }
- internal override int Size { get { return 4; } }
- }
-
- internal sealed class DoubleNormalizer: Normalizer {
- internal override void Normalize(FieldInfo fi, object obj, Stream s) {
- double d = (double) GetValue(fi, obj);
- byte[] b = BitConverter.GetBytes(d);
- if (!m_skipNormalize) {
- Array.Reverse(b);
- if ((b[0] & 0x80) == 0) {
- // This is a positive number.
- // Flip the highest bit
- b[0] ^= 0x80;
- }
- else {
- // This is a negative number.
- if (d < 0) {
- // If all zeroes, means it was a negative zero.
- // Treat it same as positive zero, so that
- // the normalized key will compare equal.
- FlipAllBits(b);
- }
- }
- }
- // Console.WriteLine("normalized " + fi.FieldType + " " + fi.GetValue(obj)
- // + " to " + GetString(b));
- s.Write(b, 0, b.Length);
- }
- internal override void DeNormalize(FieldInfo fi, object recvr, Stream s) {
- byte[] b = new Byte[8];
- s.Read(b, 0, b.Length);
- if (!m_skipNormalize) {
- if ((b[0] & 0x80) > 0) {
- // This is a positive number.
- // Flip the highest bit
- b[0] ^= 0x80;
- }
- else {
- // This is a negative number.
- FlipAllBits(b);
- }
- Array.Reverse(b);
- }
- SetValue(fi, recvr, BitConverter.ToDouble(b, 0));
- }
- internal override int Size { get { return 8; } }
- }
- }
|