5 // Miguel de Icaza (miguel@ximian.com)
6 // Nick Drochak (ndrochak@gol.com)
7 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
9 // (C) Ximian, Inc. http://www.ximian.com
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.Globalization;
38 using System.Runtime.CompilerServices;
39 using System.Runtime.InteropServices;
43 internal struct MonoEnumInfo
46 internal Array values;
47 internal string[] names;
48 internal Hashtable name_hash;
50 static Hashtable cache;
51 static Hashtable global_cache;
52 static object global_cache_monitor;
54 [MethodImplAttribute (MethodImplOptions.InternalCall)]
55 private static extern void get_enum_info (Type enumType, out MonoEnumInfo info);
58 // These comparers are needed because enumerations must be compared
59 // using unsigned values so that negative numbers can be looked up
62 internal static SByteComparer sbyte_comparer = new SByteComparer ();
63 internal static ShortComparer short_comparer = new ShortComparer ();
64 internal static IntComparer int_comparer = new IntComparer ();
65 internal static LongComparer long_comparer = new LongComparer ();
67 internal class SByteComparer : IComparer, System.Collections.Generic.IComparer<sbyte>
69 public int Compare (object x, object y)
74 return ((byte) ix) - ((byte) iy);
77 public int Compare (sbyte ix, sbyte iy)
79 return ((byte) ix) - ((byte) iy);
83 internal class ShortComparer : IComparer, System.Collections.Generic.IComparer<short>
85 public int Compare (object x, object y)
90 return ((ushort) ix) - ((ushort) iy);
93 public int Compare (short ix, short iy)
95 return ((ushort) ix) - ((ushort) iy);
99 internal class IntComparer : IComparer, System.Collections.Generic.IComparer<int>
101 public int Compare (object x, object y)
109 if (((uint) ix) < ((uint) iy))
114 public int Compare (int ix, int iy)
119 if (((uint) ix) < ((uint) iy))
125 internal class LongComparer : IComparer, System.Collections.Generic.IComparer<long>
127 public int Compare (object x, object y)
134 if (((ulong) ix) < ((ulong) iy))
139 public int Compare (long ix, long iy)
143 if (((ulong) ix) < ((ulong) iy))
149 static MonoEnumInfo ()
151 global_cache_monitor = new object ();
152 global_cache = new Hashtable ();
155 static Hashtable Cache {
158 cache = new Hashtable ();
163 private MonoEnumInfo (MonoEnumInfo other)
166 values = other.values;
168 name_hash = other.name_hash;
171 internal static void GetInfo (Type enumType, out MonoEnumInfo info)
173 /* First check the thread-local cache without locking */
174 if (Cache.ContainsKey (enumType)) {
175 info = (MonoEnumInfo) cache [enumType];
178 /* Threads could die, so keep a global cache too */
179 lock (global_cache_monitor) {
180 if (global_cache.ContainsKey (enumType)) {
181 object boxedInfo = global_cache [enumType];
182 cache [enumType] = boxedInfo;
183 info = (MonoEnumInfo)boxedInfo;
188 get_enum_info (enumType, out info);
190 Type et = Enum.GetUnderlyingType (enumType);
191 SortEnums (et, info.values, info.names);
193 if (info.names.Length > 50) {
194 info.name_hash = new Hashtable (info.names.Length);
195 for (int i = 0; i < info.names.Length; ++i)
196 info.name_hash [info.names [i]] = i;
198 MonoEnumInfo cached = new MonoEnumInfo (info);
199 lock (global_cache_monitor) {
200 global_cache [enumType] = cached;
204 internal static void SortEnums (Type et, Array values, Array names)
207 if (et == typeof (int))
209 else if (et == typeof (short))
211 else if (et == typeof (sbyte))
213 else if (et == typeof (long))
216 Array.Sort (values, names, ic);
222 public abstract class Enum : ValueType, IComparable, IConvertible, IFormattable
228 // IConvertible methods Start -->
229 public TypeCode GetTypeCode ()
231 return Type.GetTypeCode (GetUnderlyingType (this.GetType ()));
234 bool IConvertible.ToBoolean (IFormatProvider provider)
236 return Convert.ToBoolean (Value, provider);
239 byte IConvertible.ToByte (IFormatProvider provider)
241 return Convert.ToByte (Value, provider);
244 char IConvertible.ToChar (IFormatProvider provider)
246 return Convert.ToChar (Value, provider);
249 DateTime IConvertible.ToDateTime (IFormatProvider provider)
251 return Convert.ToDateTime (Value, provider);
254 decimal IConvertible.ToDecimal (IFormatProvider provider)
256 return Convert.ToDecimal (Value, provider);
259 double IConvertible.ToDouble (IFormatProvider provider)
261 return Convert.ToDouble (Value, provider);
264 short IConvertible.ToInt16 (IFormatProvider provider)
266 return Convert.ToInt16 (Value, provider);
269 int IConvertible.ToInt32 (IFormatProvider provider)
271 return Convert.ToInt32 (Value, provider);
274 long IConvertible.ToInt64 (IFormatProvider provider)
276 return Convert.ToInt64 (Value, provider);
279 sbyte IConvertible.ToSByte (IFormatProvider provider)
281 return Convert.ToSByte (Value, provider);
284 float IConvertible.ToSingle (IFormatProvider provider)
286 return Convert.ToSingle (Value, provider);
289 object IConvertible.ToType (Type targetType, IFormatProvider provider)
291 if (targetType == null)
292 throw new ArgumentNullException ("targetType");
293 if (targetType == typeof (string))
294 return ToString (provider);
295 return Convert.ToType (Value, targetType, provider, false);
298 ushort IConvertible.ToUInt16 (IFormatProvider provider)
300 return Convert.ToUInt16 (Value, provider);
303 uint IConvertible.ToUInt32 (IFormatProvider provider)
305 return Convert.ToUInt32 (Value, provider);
308 ulong IConvertible.ToUInt64 (IFormatProvider provider)
310 return Convert.ToUInt64 (Value, provider);
313 // <-- End IConvertible methods
315 [MethodImplAttribute (MethodImplOptions.InternalCall)]
316 private extern object get_value ();
318 // wrap the icall into a property so we don't hav to use the icall everywhere
319 private object Value {
320 get { return get_value (); }
324 public static Array GetValues (Type enumType)
326 if (enumType == null)
327 throw new ArgumentNullException ("enumType");
329 if (!enumType.IsEnum)
330 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
333 MonoEnumInfo.GetInfo (enumType, out info);
334 return (Array) info.values.Clone ();
338 public static string[] GetNames (Type enumType)
340 if (enumType == null)
341 throw new ArgumentNullException ("enumType");
343 if (!enumType.IsEnum)
344 throw new ArgumentException ("enumType is not an Enum type.");
347 MonoEnumInfo.GetInfo (enumType, out info);
348 return (string []) info.names.Clone ();
352 // The faster, non-boxing version. It must use the special MonoEnumInfo.xxx_comparers
353 // to ensure that we are perfoming bitwise compares, and not signed compares.
355 // It also tries to use the non-boxing version of the various Array.BinarySearch methods
357 static int FindPosition (Type enumType, object value, Array values)
359 switch (Type.GetTypeCode (GetUnderlyingType (enumType))) {
361 sbyte [] sbyte_array = values as sbyte [];
362 return Array.BinarySearch (sbyte_array, (sbyte) value, MonoEnumInfo.sbyte_comparer);
365 byte [] byte_array = values as byte [];
366 return Array.BinarySearch (byte_array, (byte) value);
369 short [] short_array = values as short [];
370 return Array.BinarySearch (short_array, (short)value, MonoEnumInfo.short_comparer);
372 case TypeCode.UInt16:
373 ushort [] ushort_array = values as ushort [];
374 return Array.BinarySearch (ushort_array, (ushort)value);
377 int[] int_array = values as int[];
378 return Array.BinarySearch (int_array, (int)value, MonoEnumInfo.int_comparer);
380 case TypeCode.UInt32:
381 uint[] uint_array = values as uint [];
382 return Array.BinarySearch (uint_array, (uint)value);
385 long [] long_array = values as long [];
386 return Array.BinarySearch (long_array, (long) value, MonoEnumInfo.long_comparer);
388 case TypeCode.UInt64:
389 ulong [] ulong_array = values as ulong [];
390 return Array.BinarySearch (ulong_array, (ulong) value);
393 // This should never happen
394 return Array.BinarySearch (values, value);
399 public static string GetName (Type enumType, object value)
401 if (enumType == null)
402 throw new ArgumentNullException ("enumType");
404 throw new ArgumentNullException ("value");
406 if (!enumType.IsEnum)
407 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
410 value = ToObject (enumType, value);
411 MonoEnumInfo.GetInfo (enumType, out info);
413 int i = FindPosition (enumType, value, info.values);
414 return (i >= 0) ? info.names [i] : null;
418 public static bool IsDefined (Type enumType, object value)
420 if (enumType == null)
421 throw new ArgumentNullException ("enumType");
423 throw new ArgumentNullException ("value");
425 if (!enumType.IsEnum)
426 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
429 MonoEnumInfo.GetInfo (enumType, out info);
431 Type vType = value.GetType ();
432 if (vType == typeof(String)) {
433 return ((IList)(info.names)).Contains (value);
434 } else if ((vType == info.utype) || (vType == enumType)) {
435 value = ToObject (enumType, value);
436 MonoEnumInfo.GetInfo (enumType, out info);
438 return FindPosition (enumType, value, info.values) >= 0;
440 throw new ArgumentException("The value parameter is not the correct type. "
441 + "It must be type String or the same type as the underlying type "
446 [MethodImplAttribute (MethodImplOptions.InternalCall)]
447 private static extern Type get_underlying_type (Type enumType);
450 public static Type GetUnderlyingType (Type enumType)
452 if (enumType == null)
453 throw new ArgumentNullException ("enumType");
455 if (!enumType.IsEnum)
456 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
458 return get_underlying_type (enumType);
462 public static object Parse (Type enumType, string value)
464 // Note: Parameters are checked in the other overload
465 return Parse (enumType, value, false);
468 private static int FindName (Hashtable name_hash, string [] names, string name, bool ignoreCase)
471 /* For enums with many values, use a hash table */
472 if (name_hash != null) {
473 object val = name_hash [name];
477 for (int i = 0; i < names.Length; ++i) {
478 if (name == names [i])
483 for (int i = 0; i < names.Length; ++i) {
484 if (String.Compare (name, names [i], ignoreCase, CultureInfo.InvariantCulture) == 0)
491 // Helper function for dealing with [Flags]-style enums.
492 private static ulong GetValue (object value, TypeCode typeCode)
498 return (byte) ((sbyte) value);
500 return (ushort) ((short) value);
502 return (uint) ((int) value);
504 return (ulong) ((long) value);
505 case TypeCode.UInt16:
506 return (ushort) value;
507 case TypeCode.UInt32:
509 case TypeCode.UInt64:
510 return (ulong) value;
512 throw new ArgumentException ("typeCode is not a valid type code for an Enum");
515 private static char [] split_char = { ',' };
518 public static object Parse (Type enumType, string value, bool ignoreCase)
520 if (enumType == null)
521 throw new ArgumentNullException ("enumType");
524 throw new ArgumentNullException ("value");
526 if (!enumType.IsEnum)
527 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
529 value = value.Trim ();
530 if (value.Length == 0)
531 throw new ArgumentException ("An empty string is not considered a valid value.");
534 if (!Parse (enumType, value, ignoreCase, out result))
535 throw new ArgumentException (String.Format ("The requested value '{0}' was not found.", value));
540 static bool Parse<TEnum> (Type enumType, string value, bool ignoreCase, out TEnum result)
542 result = default (TEnum);
545 MonoEnumInfo.GetInfo (enumType, out info);
547 // is 'value' a named constant?
548 int loc = FindName (info.name_hash, info.names, value, ignoreCase);
550 result = (TEnum) info.values.GetValue (loc);
554 TypeCode typeCode = ((Enum) info.values.GetValue (0)).GetTypeCode ();
556 // is 'value' a list of named constants?
557 if (value.IndexOf (',') != -1) {
558 string [] names = value.Split (split_char);
560 for (int i = 0; i < names.Length; ++i) {
561 loc = FindName (info.name_hash, info.names, names [i].Trim (), ignoreCase);
565 retVal |= GetValue (info.values.GetValue (loc), typeCode);
567 result = (TEnum) ToObject (enumType, retVal);
571 // is 'value' a number?
575 if (!SByte.TryParse (value, out sb))
577 result = (TEnum) ToObject (enumType, sb);
581 if (!Byte.TryParse (value, out b))
583 result = (TEnum) ToObject (enumType, b);
587 if (!Int16.TryParse (value, out i16))
589 result = (TEnum) ToObject (enumType, i16);
591 case TypeCode.UInt16:
593 if (!UInt16.TryParse (value, out u16))
595 result = (TEnum) ToObject (enumType, u16);
599 if (!Int32.TryParse (value, out i32))
601 result = (TEnum) ToObject (enumType, i32);
603 case TypeCode.UInt32:
605 if (!UInt32.TryParse (value, out u32))
607 result = (TEnum) ToObject (enumType, u32);
611 if (!Int64.TryParse (value, out i64))
613 result = (TEnum) ToObject (enumType, i64);
615 case TypeCode.UInt64:
617 if (!UInt64.TryParse (value, out u64))
619 result = (TEnum) ToObject (enumType, u64);
628 #if NET_4_0 || MOONLIGHT || MOBILE
629 public static bool TryParse<TEnum> (string value, out TEnum result) where TEnum : struct
631 return TryParse (value, false, out result);
634 public static bool TryParse<TEnum> (string value, bool ignoreCase, out TEnum result) where TEnum : struct
636 Type tenum_type = typeof (TEnum);
637 if (!tenum_type.IsEnum)
638 throw new ArgumentException("TEnum is not an Enum type.", "enumType");
640 result = default (TEnum);
642 if (value == null || value.Trim ().Length == 0)
645 return Parse (tenum_type, value, ignoreCase, out result);
649 [MethodImplAttribute (MethodImplOptions.InternalCall)]
650 private extern int compare_value_to (object other);
653 /// Compares the enum value with another enum value of the same type.
657 public int CompareTo (object target)
664 thisType = this.GetType ();
665 if (target.GetType() != thisType) {
666 throw new ArgumentException (String.Format (
667 "Object must be the same type as the enum. The type passed in was {0}; the enum type was {1}.",
668 target.GetType(), thisType));
671 return compare_value_to (target);
674 public override string ToString ()
676 return ToString ("G");
679 [Obsolete("Provider is ignored, just use ToString")]
680 public string ToString (IFormatProvider provider)
682 return ToString ("G", provider);
685 public string ToString (String format)
687 if (format == String.Empty || format == null)
690 return Format (this.GetType (), this.Value, format);
693 [Obsolete("Provider is ignored, just use ToString")]
694 public string ToString (String format, IFormatProvider provider)
696 // provider is not used for Enums
698 if (format == String.Empty || format == null) {
701 return Format (this.GetType(), this.Value, format);
705 public static object ToObject (Type enumType, byte value)
707 return ToObject (enumType, (object)value);
711 public static object ToObject (Type enumType, short value)
713 return ToObject (enumType, (object)value);
717 public static object ToObject (Type enumType, int value)
719 return ToObject (enumType, (object)value);
723 public static object ToObject (Type enumType, long value)
725 return ToObject (enumType, (object)value);
729 [MethodImplAttribute(MethodImplOptions.InternalCall)]
730 public static extern object ToObject (Type enumType, object value);
733 [CLSCompliant (false)]
734 public static object ToObject (Type enumType, sbyte value)
736 return ToObject (enumType, (object)value);
740 [CLSCompliant (false)]
741 public static object ToObject (Type enumType, ushort value)
743 return ToObject (enumType, (object)value);
747 [CLSCompliant (false)]
748 public static object ToObject (Type enumType, uint value)
750 return ToObject (enumType, (object)value);
754 [CLSCompliant (false)]
755 public static object ToObject (Type enumType, ulong value)
757 return ToObject (enumType, (object)value);
760 public override bool Equals (object obj)
762 return DefaultEquals (this, obj);
765 [MethodImplAttribute (MethodImplOptions.InternalCall)]
766 private extern int get_hashcode ();
768 public override int GetHashCode ()
770 return get_hashcode ();
773 private static string FormatSpecifier_X (Type enumType, object value, bool upper)
775 switch (Type.GetTypeCode (enumType)) {
777 return ((sbyte)value).ToString (upper ? "X2" : "x2");
779 return ((byte)value).ToString (upper ? "X2" : "x2");
781 return ((short)value).ToString (upper ? "X4" : "x4");
782 case TypeCode.UInt16:
783 return ((ushort)value).ToString (upper ? "X4" : "x4");
785 return ((int)value).ToString (upper ? "X8" : "x8");
786 case TypeCode.UInt32:
787 return ((uint)value).ToString (upper ? "X8" : "x8");
789 return ((long)value).ToString (upper ? "X16" : "x16");
790 case TypeCode.UInt64:
791 return ((ulong)value).ToString (upper ? "X16" : "x16");
793 throw new Exception ("Invalid type code for enumeration.");
797 static string FormatFlags (Type enumType, object value)
799 string retVal = String.Empty;
801 MonoEnumInfo.GetInfo (enumType, out info);
802 string asString = value.ToString ();
803 if (asString == "0") {
804 retVal = GetName (enumType, value);
809 // This is ugly, yes. We need to handle the different integer
810 // types for enums. If someone else has a better idea, be my guest.
811 switch (((Enum)info.values.GetValue (0)).GetTypeCode ()) {
812 case TypeCode.SByte: {
813 sbyte flags = (sbyte) value;
815 for (int i = info.values.Length - 1; i >= 0; i--) {
816 enumValue = (sbyte) info.values.GetValue (i);
820 if ((flags & enumValue) == enumValue) {
821 retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
825 if (flags != 0) return asString;
828 case TypeCode.Byte: {
829 byte flags = (byte) value;
831 for (int i = info.values.Length - 1; i >= 0; i--) {
832 enumValue = (byte) info.values.GetValue (i);
836 if ((flags & enumValue) == enumValue) {
837 retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
841 if (flags != 0) return asString;
844 case TypeCode.Int16: {
845 short flags = (short) value;
847 for (int i = info.values.Length - 1; i >= 0; i--) {
848 enumValue = (short) info.values.GetValue (i);
852 if ((flags & enumValue) == enumValue) {
853 retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
857 if (flags != 0) return asString;
860 case TypeCode.Int32: {
861 int flags = (int) value;
863 for (int i = info.values.Length - 1; i >= 0; i--) {
864 enumValue = (int) info.values.GetValue (i);
868 if ((flags & enumValue) == enumValue) {
869 retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
873 if (flags != 0) return asString;
876 case TypeCode.UInt16: {
877 ushort flags = (ushort) value;
879 for (int i = info.values.Length - 1; i >= 0; i--) {
880 enumValue = (ushort) info.values.GetValue (i);
884 if ((flags & enumValue) == enumValue) {
885 retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
889 if (flags != 0) return asString;
892 case TypeCode.UInt32: {
893 uint flags = (uint) value;
895 for (int i = info.values.Length - 1; i >= 0; i--) {
896 enumValue = (uint) info.values.GetValue (i);
900 if ((flags & enumValue) == enumValue) {
901 retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
905 if (flags != 0) return asString;
908 case TypeCode.Int64: {
909 long flags = (long) value;
911 for (int i = info.values.Length - 1; i >= 0; i--) {
912 enumValue = (long) info.values.GetValue (i);
916 if ((flags & enumValue) == enumValue) {
917 retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
921 if (flags != 0) return asString;
924 case TypeCode.UInt64: {
925 ulong flags = (ulong) value;
927 for (int i = info.values.Length - 1; i >= 0; i--) {
928 enumValue = (ulong) info.values.GetValue (i);
932 if ((flags & enumValue) == enumValue) {
933 retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
937 if (flags != 0) return asString;
942 if (retVal == String.Empty)
949 public static string Format (Type enumType, object value, string format)
951 if (enumType == null)
952 throw new ArgumentNullException ("enumType");
954 throw new ArgumentNullException ("value");
956 throw new ArgumentNullException ("format");
958 if (!enumType.IsEnum)
959 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
961 Type vType = value.GetType();
962 Type underlyingType = Enum.GetUnderlyingType (enumType);
964 if (vType != enumType)
965 throw new ArgumentException (string.Format(CultureInfo.InvariantCulture,
966 "Object must be the same type as the enum. The type" +
967 " passed in was {0}; the enum type was {1}.",
968 vType.FullName, enumType.FullName));
969 } else if (vType != underlyingType) {
970 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
971 "Enum underlying type and the object must be the same type" +
972 " or object. Type passed in was {0}; the enum underlying" +
973 " type was {1}.", vType.FullName, underlyingType.FullName));
976 if (format.Length != 1)
977 throw new FormatException ("Format String can be only \"G\",\"g\",\"X\"," +
978 "\"x\",\"F\",\"f\",\"D\" or \"d\".");
980 char formatChar = format [0];
982 if ((formatChar == 'G' || formatChar == 'g')) {
983 if (!enumType.IsDefined (typeof(FlagsAttribute), false)) {
984 retVal = GetName (enumType, value);
986 retVal = value.ToString();
994 if ((formatChar == 'f' || formatChar == 'F'))
995 return FormatFlags (enumType, value);
997 retVal = String.Empty;
998 switch (formatChar) {
1000 retVal = FormatSpecifier_X (enumType, value, true);
1003 retVal = FormatSpecifier_X (enumType, value, false);
1007 if (underlyingType == typeof (ulong)) {
1008 ulong ulongValue = Convert.ToUInt64 (value);
1009 retVal = ulongValue.ToString ();
1011 long longValue = Convert.ToInt64 (value);
1012 retVal = longValue.ToString ();
1016 throw new FormatException ("Format String can be only \"G\",\"g\",\"X\"," +
1017 "\"x\",\"F\",\"f\",\"D\" or \"d\".");
1021 #if NET_4_0 || MOONLIGHT || MOBILE
1022 public bool HasFlag (Enum flag)
1024 var val = get_value ();
1025 ulong mvalue = GetValue (val, Type.GetTypeCode (val.GetType ()));
1026 ulong fvalue = GetValue (flag, Type.GetTypeCode (flag.GetType ()));
1028 return ((mvalue & fvalue) == fvalue);