qq jcesstruct構造python解析


jcesstructはprotobuffのようなシーケンス化構造で、qqは主にこのシーケンス化構造を使用しています.ネット上の資料は少なく、Javaですから、pythonの解析を書きましょう.
フォーマットの内容:
ttlv構造、すなわちtag,type,length,valueの3つの内容.
jcestructの構造はすべてheadで、次の内容です.
head構造
通常headは1バイトで、typeも含まれ、tagはシーケンス番号を表す.
1つのheadの下位4ビットはtypeタイプであり、上位4ビットはtagであり、tagが0 xfに等しい場合、headは2バイトを含み、2番目のバイトはtag値である.
headを取得するコードは次のとおりです.
def readHead():
    head = jcestruct.read(1)
    headdata = struct.unpack('b',head)
    for i in headdata:
        #print(i)
        print("headData:",end='')
        print(hex(i))
        headtag = ((i)& 0xF0)>>4
        headtype = i&0xF
        if 0xF == headtag:
            headtag = jcestruct.read(1)
        print("headtap:",end='')
        print(headtag)
        print("headtype:",end='')
        print(headtype)
    return headtag,headtype

typeのフォーマットリストは次のとおりです.

を選択します.
0
byteまたはbool
1
Short
2
Int
3
Long
4
Float
5
Double
6,7
String   6文字列が短い、1バイトが長さ、7文字列が長い、1 intが長さ
8
Map  後の最初のintは長さを表す
9
List
10
STRUCT_BEGINはJceStructクラスの開始を継承しています
11
STRUCT_ENDはJceStructクラスの終わりを受け継いだ
12
ZERO_TAG
13
TYPE_SIMPLE_LISTが後に加えた構造はbytes配列で、なぜこの構造があるのか分からないが、まずbyteが長さタイプを表し、
 
# -*- coding: utf-8 -*-
"""
Created on Fri Feb  7 16:49:39 2020

@author: lth
"""
import struct

TYPE_BYTE = 0;
TYPE_SHORT = 1
TYPE_INT = 2
TYPE_LONG = 3
TYPE_FLOAT = 4
TYPE_DOUBLE = 5
TYPE_STRING1 = 6
TYPE_STRING4 = 7
TYPE_MAP = 8
TYPE_LIST = 9
#     0A*******0B
TYPE_STRUCT_BEGIN = 10
TYPE_STRUCT_END = 11
TYPE_ZERO_TAG = 12
TYPE_SIMPLE_LIST = 13





def readHead():
    head = jcestruct.read(1)
    if b'' == head:
        print('complete!')
        return 0,12
    print(head)
    headdata = struct.unpack('b',head)
    for i in headdata:
        headtag = ((i)& 0xF0)>>4
        headtype = i&0xF
        if 0xF == headtag:
            headtag = jcestruct.read(1)
        '''
        print("headData:",end='')
        print(hex(i))
        print("headtap:",end='')
        print(headtag)
        print("headtype:",end='')
        print(headtype)
        '''
    return headtag,headtype
    


    
def switchType(typ):
    if TYPE_BYTE == typ:
        print("tag:byte")
        jceData = jcestruct.read(1)
        print(int.from_bytes(jceData,'little'))
        return int.from_bytes(jceData,'little')
        
    elif TYPE_SHORT == typ:   ##short
        print("tag:short")
        jceData = jcestruct.read(2)
        print(jceData)
    elif TYPE_INT == typ:  ##int
        print("tag:int")
        jceData = jcestruct.read(4)
        print(jceData)
    elif TYPE_LONG == typ:  ##long
        print("tag:long")
        jceData = jcestruct.read(8)
        print(jceData)
    elif TYPE_FLOAT == typ:    ##float
        print("tag:float")
        jceData = jcestruct.read(8)
        print(jceData)
    elif TYPE_DOUBLE == typ:   ###double
        print("tag:double")
        jceData = jcestruct.read(8)
        print(jceData)
    elif TYPE_STRING1 == typ:  ##sting
        print("tag:string")
        jceDatalen = jcestruct.read(1)
        
        jceDatalen = int().from_bytes(jceDatalen,byteorder='big', signed=False)
        #print(int().from_bytes(jceDatalen,byteorder='little', signed=False))
        
        jceData = jcestruct.read(jceDatalen)
        print(jceData)
    elif TYPE_STRING4 == typ:  ##long string
        print("tag:long")
        jceDatalen = jcestruct.read(4)
        
        jceData = jcestruct.read(int(jceDatalen))
        print(jceData)
    elif TYPE_MAP == typ:  ##map
        print("tag:map",end='')
        jceDatalen = jcestruct.read(2)    ## map    
        jceDatalen = int.from_bytes(jceDatalen,'big')
        print(jceDatalen)
        print('[')
        for i in range(0,jceDatalen):
            a,b = readHead()
            print("key is:",end='')
            switchType(b)
            a,b = readHead()
            print("value is:",end='')
            switchType(b)
        
    elif TYPE_LIST == typ:   ##list
        print("tag:list")
        jceDatalen = jcestruct.read(2)    ## map    
        jceDatalen = int.from_bytes(jceDatalen,'big')
        print(jceDatalen)
        for i in range(0,jceDatalen):
            tag,typ = readHead()
            switchType(typ)
        jceData = jcestruct.read(jceDatalen)
        print(jceData)
    elif TYPE_STRUCT_BEGIN == typ:   ##0a  begin 0b end
        print("tag:begin")
        tag,typ = readHead()
        #print(typ)
        switchType(typ)
#        print(jceData)
    elif TYPE_STRUCT_END == typ:
        print("tag:end")
        jceData = jcestruct.read(1)
        print(jceData)
    elif TYPE_ZERO_TAG == typ:   ##zero
        print("tag:deadline")
        return
    elif TYPE_SIMPLE_LIST == typ: ##simple list
        jcestruct.read(1)
        tag,typ = readHead()
        if typ == TYPE_SHORT:
            jceDatalen = jcestruct.read(2)
            jceDatalen = int().from_bytes(jceDatalen,byteorder='big', signed=False)
            jceData = jcestruct.read(jceDatalen)
            print(jceData)
        elif typ == TYPE_BYTE:
            jceDatalen = jcestruct.read(1)
            jceDatalen = int().from_bytes(jceDatalen,byteorder='big', signed=False)
            jceData = jcestruct.read(jceDatalen)
            print(jceData)
            
    
#print(headtag)
if __name__ == '__main__':
    jcestruct = open('test.bin','rb') #output
    tag1,type1 = readHead()
    while(TYPE_ZERO_TAG != type1):    
        switchType(type1)
        tag1,type1 = readHead()
    jcestruct.close()