2013-06-20 5 views
3

나는 홈 오토메이션 모듈에서 얻은 바이너리 데이터를 파싱하는 dll을 만들고있다.바이트 열거 형을 파싱

하지만 일부 코드에 대한 조언이 필요합니다.
그래서 몇 바이트의 메시지가 표시되고 각 비트는이 경우 특정 조건을 나타냅니다. I는 각각의 상태가 열거되는 순간에서이 코드에

enter image description here

는 I 배열에 열거두고 대응하는 비트가 설정되어 있는지 확인한다.
private void ParseZoneConditionFlag1(int Flag1) // Flag1 = Hex represenation of byte 
{ 
    Zone_Status_ZoneConditionFlagEnum[] FlagArray = new Zone_Status_ZoneConditionFlagEnum[8]; 
    FlagArray[0] = Zone_Status_ZoneConditionFlagEnum.Faulted; 
    FlagArray[1] = Zone_Status_ZoneConditionFlagEnum.Tampered; 
    FlagArray[2] = Zone_Status_ZoneConditionFlagEnum.Trouble; 
    FlagArray[3] = Zone_Status_ZoneConditionFlagEnum.Bypassed; 
    FlagArray[4] = Zone_Status_ZoneConditionFlagEnum.Inhibited; 
    FlagArray[5] = Zone_Status_ZoneConditionFlagEnum.Low_Battery; 
    FlagArray[6] = Zone_Status_ZoneConditionFlagEnum.Loss_Supervision; 
    FlagArray[7] = Zone_Status_ZoneConditionFlagEnum.Reserved; 

    base.CheckBitsSet(FlagArray, Flag1, ZoneConditionFlags_List); 
} 

private void ParseZoneConditionFlag2(int Flag2) 
{ 
    Zone_Status_ZoneConditionFlagEnum[] FlagArray = new Zone_Status_ZoneConditionFlagEnum[8]; 
    FlagArray[0] = Zone_Status_ZoneConditionFlagEnum.Alarm_Memory; 
    FlagArray[1] = Zone_Status_ZoneConditionFlagEnum.Bypass_Memory; 
    FlagArray[2] = Zone_Status_ZoneConditionFlagEnum.Reserved; 
    FlagArray[3] = Zone_Status_ZoneConditionFlagEnum.Reserved; 
    FlagArray[4] = Zone_Status_ZoneConditionFlagEnum.Reserved; 
    FlagArray[5] = Zone_Status_ZoneConditionFlagEnum.Reserved; 
    FlagArray[6] = Zone_Status_ZoneConditionFlagEnum.Reserved; 
    FlagArray[7] = Zone_Status_ZoneConditionFlagEnum.Reserved; 

    base.CheckBitsSet(FlagArray, Flag2, ZoneConditionFlags_List); 
} 

그리고 그 방법은 내가이 작품의 실제 비트

protected void CheckBitsSet<T>(T[] ConstantArray, int HexValue, List<T> DestinationList) 
{ 
    byte b = (byte) HexValue; 

    for (int i = 0; i < Mask.Length; i++) 
    { 
     if(IsBitSet(b, i)) 
     { 
      DestinationList.Add(ConstantArray[i]); 
     } 
    } 
} 

public bool IsBitSet(byte b, int pos) 
{ 
    return (b & (1 << pos)) != 0; 
} 

을 확인하지만,이 작업을 수행 할 수있는 청소기 방법이 있는지 궁금했다.
클리너를 사용하면 매번 올바른 enum을 배열에 추가하지 않아도됩니다.

+2

왜 열거 그냥 바로 비트와'[플래그]'열거되지 않습니다 : 읽기

return ((value & flag) == flag); // means "are all set" return ((value & flag) != 0); // means "is any set" 

? –

답변

10

어떻게 막 : 다음

[Flags] 
enum MyFlags : short 
{ 
    None = 0, 
    Faulted = 1 << 0, 
    Tampered = 1 << 1, 
    Trouble = 1 << 2, 
    Bypassed = 1 << 3, 
    Inhibited = 1 << 4, 
    LowBattery = 1 << 5, 
    LossOfSupervision = 1 << 6, 
    AlarmMemory = 1 << 8, 
    BypassMemory = 1 << 9 
} 
static bool IsSet(MyFlags value, MyFlags flag) 
{ 
    return ((value & flag) == flag); 
} 

및 2 바이트 값으로 값 (short, 엔디 언에 대한 조심)를 읽고,이 MyFlags에 캐스팅.

은 어떤 플래그를 확인하려면 : 당신이 무슨 뜻인지 알아낼 필요로

MyFlags value = ... 
bool isAlarmMemory = IsSet(value, MyFlags.AlarmMemory); 

그것은 잔재주가

bool memoryProblem = IsSet(value, MyFlags.AlarmMemory | MyFlags.BypassMemory); 

즉, 당신이에 대한 복합 플래그를 이야기 할 때 얻을 "입니다 이러한 플래그 중 하나라도 설정되어 있습니까? " vs "이 모든 플래그가 설정되어 있습니까?"

테스트가 시작됩니다.

// this is just some garbage that I'm pretending is a message from 
// your module; I'm assuming the byte numbers in the image are 
// zero-based, so the two that we want are: \/\/\/ (the 6,3) 
byte[] data = { 12, 63, 113, 0, 13, 123, 14, 6, 3, 14, 15 }; 

// and I'm assuming "byte 7" and "byte 8" (image) are zero-based; 
// MyFlags uses byte 7 *first*, so it is little-endian; we can get that 
// via: 
short flagsRaw = (short)(data[7] | (data[8] << 8)); 
MyFlags flags = (MyFlags)flagsRaw; 
// flags has value Tampered | Trouble | AlarmMemory | BypassMemory, 
// which is what we expect for {6,3} 
+0

열거 형 정의에서 이중 화살표는 무엇입니까? 결코 문법을 보지 못했습니다 – Ian

+0

방금 ​​400k에 도달했습니다, 축하합니다! 나는이 주제가 여러 차례 논의되었다고 생각한다. –

+0

@Ian left-shift; '1 << 4는 (2 진수)'10000' === (10 진수) 16; 그러나이 컨텍스트에서는 "비트 5"가 "0"에서부터 계산되는 한 "1"과 동일하기 때문에 "비트 5"(이 스펙에서)를 매핑하는 것이 편리합니다. " –

1

사용이 :

[Flags] 
public enum MyEnum 
{ 
    Value1 = 1, 
    Value2 = 2, 
    Value3 = 4, 
    Value5 = 8 
} 

(...) 

void Func(int flag) 
{ 
    MyEnum @enum = (MyEnum)flag; 

    // Testing, whether a flag is set 

    if ((@enum & MyEnum.Value1) != 0) // sth 
}