优化ETL过滤模块
大石头 编写于 2017-08-29 17:11:46
X
using System;

namespace NewLife.Serialization
{
    /// <summary>字段位大小特性。</summary>
    /// <remarks>
    /// 用于模仿C/C++的位域
    /// </remarks>
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
    public class BitSizeAttribute : Attribute
    {
        private Int32 _Size;
        /// <summary>大小</summary>
        public Int32 Size { get { return _Size; } set { _Size = value; } }

        /// <summary>通过Offset指定字段的偏移位置</summary>
        /// <param name="size"></param>
        public BitSizeAttribute(Int32 size) { Size = size; }

        #region 方法
        /// <summary>把当前字段所属部分附加到目标数字</summary>
        /// <param name="target">目标数字</param>
        /// <param name="value">当前字段的数值</param>
        /// <param name="offset">当前字段偏移</param>
        /// <returns></returns>
        public Int32 Set(Int32 target, Int32 value, Int32 offset)
        {
            // 过滤数字中的干扰数据
            var mask = GetMask();
            value &= mask;

            // 先清零所属位,避免其它地方干扰
            target &= ~(mask << offset);

            // 当前字段移位到它所属部分
            target |= (value << offset);

            return target;
        }

        /// <summary>从目标数字里面获取当前字段所属部分</summary>
        /// <param name="target">目标数字</param>
        /// <param name="offset">当前字段偏移</param>
        /// <returns></returns>
        public Int32 Get(Int32 target, Int32 offset)
        {
            var mask = GetMask();

            // 移位到它应该在的位置
            var value = target >> offset;
            value &= mask;

            return value;
        }

        /// <summary>根据大小计算掩码</summary>
        /// <returns></returns>
        Int32 GetMask()
        {
            var v = 0;
            for (var i = 0; i < Size; i++)
            {
                v <<= 1;
                v++;
            }
            return v;
        }
        #endregion
    }
}