2012-02-29 2 views
1

파이썬 construct 라이브러리에서는 구문 분석중인 데이터에 플래그가 설정된 경우에만 의미가있는 필드가 있습니다.Python 구문 - 선택적 필드에 대한 데이터 사용

그러나 데이터 필드는 항상 존재합니다.

따라서 어떤 경우에도 데이터를 소비하지만 플래그 값에 따라 필드 값만 설정하고 싶습니다.

>>> struct.parse("010203".decode("hex")) 

결과이어야 : 데이터에 대한

struct = Struct("struct", 
    Flag("flag"), 
    UBInt8("optional_data"), 
    UBInt8("mandatory") 
) 

: 구조 인 경우, 예를 들어

(부정확하게)으로 정의

Container({'flag': True, 'mandatory': 3, 'optional_data': 2}) 

및 데이터 :

>>> struct.parse("000203".decode("hex")) 

원하는 결과는 다음

>>> struct.parse("000203".decode("hex")) 
Container({'flag': False, 'mandatory': 3, 'optional_data': '\x02'}) 
:

struct = Struct("struct", 
    Flag("flag"), 
    IfThenElse("optional_data", lambda ctx: ctx.flag, 
     UBInt8("dummy"), 
     Padding(1) 
    ), 
    UBInt8("mandatory") 
) 

그러나 패딩()과 같이, 필드의 원시 데이터를 둔다 :

Container({'flag': False, 'mandatory': 3, 'optional_data': None}) 

I는 다음 시도

감사합니다.

답변

0

아마 simi를 사용할 수 있습니다. 시퀀스

class LengthValueAdapter(Adapter): 
""" 
Adapter for length-value pairs. It extracts only the value from the 
pair, and calculates the length based on the value. 
See PrefixedArray and PascalString. 

Parameters: 
* subcon - the subcon returning a length-value pair 
""" 
__slots__ = [] 
def _encode(self, obj, context): 
    return (len(obj), obj) 
def _decode(self, obj, context): 
    return obj[1] 

class OptionalDataAdapter(Adapter): 
__slots__ = [] 
def _decode(self, obj, context): 
    if context.flag: 
    return obj 
    else 
    return None 

에 대한 LengthValueAdapter 고맙다는 그래서

struct = Struct("struct", 
    Flag("flag"), 
    OptionalDataAdapter(UBInt8("optional_data")), 
    UBInt8("mandatory") 
) 
1

내가 정확하게 문제를 이해한다면 확실하지 않다. 문제가 패딩이 int로 구문 분석되지 않는다면, IFThenElse가 필요 없다. 코드에서 구문 분석 된 컨테이너의 플래그를 확인하고 optional_data 필드를 무시하도록 선택할 수 있습니다.

struct = Struct("struct", 
    Flag("flag"), 
    UBInt8("optional_data"), 
    UBInt8("mandatory") 
) 

문제는 당신이 플래그가 설정되어 있지 않은 경우, 당신은이 왓를 정의 할 필요가 플래그가 설정되어있는 경우에만 이름 옵션 데이터를 사용할 수 있지만, 이름 더미가 사용하려는 경우

struct = Struct("struct", 
    Flag("flag"), 
    If("optional_data", lambda ctx: ctx.flag, 
     UBInt8("useful_byte"), 
    ), 
    If("dummy", lambda ctx: !ctx.flag, 
     UBInt8("ignore_byte"), 
    ), 
    UBInt8("mandatory") 
)