File: System\ServiceModel\Configuration\StandardRuntimeFlagEnumValidatorAttribute.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------
 
namespace System.ServiceModel.Configuration
{
    using System;
    using System.Configuration;
 
    [AttributeUsage(AttributeTargets.Property)]
    internal sealed class StandardRuntimeFlagEnumValidatorAttribute : ConfigurationValidatorAttribute
    {
        Type enumType;
        Type validatorType;
 
        public StandardRuntimeFlagEnumValidatorAttribute(Type enumType)
        {
            StandardRuntimeFlagEnumValidatorAttribute.ValidateFlagEnumType(enumType);
            this.EnumType = enumType;
        }
 
        public Type EnumType
        {
            get { return this.enumType; }
            set
            {
                StandardRuntimeFlagEnumValidatorAttribute.ValidateFlagEnumType(value);
                this.enumType = value;
            }
        }
 
        static bool IsPowerOfTwo(int value)
        {
            return value > 0 && (value & (value - 1)) == 0;
        }
 
 
        internal static void ValidateFlagEnumType(Type value)
        {
            if (value == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("EnumType");
            }
 
            bool hasFlags = value.GetCustomAttributes(typeof(FlagsAttribute), true).Length > 0;
            if (!value.IsEnum || !hasFlags)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("EnumType", SR.GetString(SR.FlagEnumTypeExpected, value));
            }
 
            int[] values = (int[])Enum.GetValues(value);
 
            if (values != null &&
                values.Length > 0)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    if (values[i] != 0 && !IsPowerOfTwo(values[i]))
                    {
                        if (!StandardRuntimeFlagEnumValidatorAttribute.IsCombinedValue(values[i], values, i - 1))
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("EnumType", SR.GetString(SR.InvalidFlagEnumType));
                        }
                    }
                }
            }
        }
 
        internal static bool IsCombinedValue(int combinedValue, int[] allowedValues, int startPosition)
        {
            int n = startPosition;
 
            while (n >= 0 &&
                   combinedValue > 0)
            {
                if ((combinedValue & allowedValues[n]) == allowedValues[n])
                {
                    combinedValue -= allowedValues[n];
                }
 
                n--;
            }
 
            return combinedValue == 0;
        }
 
        private void EnsureValidatorType()
        {
            if (this.validatorType == null)
            {
                validatorType = typeof(StandardRuntimeFlagEnumValidator<>).MakeGenericType(new System.Type[] { this.enumType });
            }
        }
 
        public override ConfigurationValidatorBase ValidatorInstance
        {
            get
            {
                this.EnsureValidatorType();
                return (ConfigurationValidatorBase)Activator.CreateInstance(validatorType, null);
            }
        }
    }
}