#Copyright (c) 2006-2007 SunMedia technology (Chengdu) co. Ltd. 
#All right reserved
#Author:jlxia
#date:2007/01/25

import re
import parserfile
import string

typeBitwidth = {'unsigned char': 1, 'unsigned int':4,'UINT8':1,'UINT16':2,'UINT32':4,'int':4,'DB_PID_INFO':8,
    'char':1,'INT8': 1,'OSD_INFO_t':8,'TV_INFO_t':8,'TIME_INFO_t':5,'TIMER_INFO_t':13,'AC3_INFO_t':11,
    'SCAN_PARA_t':4,'SYSSET_USALS':20,'CASYSTEM_id_t':12,'SERVICE_UPDATE_t':2,'SYSSET_SSU_OTA':9
}

_DVB_NETWORK_Alias = {'ucInUsed':'LNB TYPE', 'ucFlag':'ucFlag','ucDiseqcType':'DiSEqC Mode','ucDiseqcPort':'DiSEqC Port',
    'uiLNBFreq':'uiLNBFreq', 'szNetName':'Satellite', 'iLongitude':'Longtitude', 'ucPosition':'Position'}
_DVB_MULTIPLEX_Alias = {'szTpName':'Transponder','usFreqM':'Frequency','usSymRateK':'Symbol Rate','usSatIndex':'Satellite Index',
'usTpIndex':None, 'ucSkew':'Polarization','ucVCRate':'FEC','ucFlag':None, 'ucInUsed':None}
_DVB_SERVICE_Alias = {'szProgName':'Service Name','usProgNo':None,'ucInUsed':None, 'usTpIndex':'Tp Index','usServiceId':'Service ID',
'usTsId':'TS ID', 'usOrigNetId':'Original Net ID','stVideoPid':'Video PID', 'stAudioPid1':'Audio PID 1','stAudioPid2':'Audio PID 2',
'usPcrPid':'PCR PID', 'uiProgAttrib':'Program Attribute','usPMTPid':'PMT ID','usDataPID':'usDataPID','usCodec':'Codec','usCASystemID':'CA System ID'}

aliasNameDict = {'DVB_NETWORK:_DVB_NETWORK':_DVB_NETWORK_Alias, 
'DVB_MULTIPLEX:_DVB_MULTIPLEX':_DVB_MULTIPLEX_Alias, 
'DVB_SERVICE:_DVB_SERVICE':_DVB_SERVICE_Alias,}

_DVB_NETWORK_Child = {'ucFlag':['22KHz','12V','USALS East/West'],'uiLNBFreq':['LNBFreq Vertical','LNBFreq Horizontal']}
_DVB_SERVICE_Child = {'stAudioPid':['Audio PID 1','Audio PID 2']}
childNameDict = {'DVB_NETWORK:_DVB_NETWORK':_DVB_NETWORK_Child, 'DVB_SERVICE:_DVB_SERVICE':_DVB_SERVICE_Child,}

#structure's member type, group 1 is keyword ,group 2 is member's type, group 3 is pointer sign, group 4 is group's name
_STVariable = re.compile(r"""
    (struct\s+?)?    #keyword, may be have
    \s*?
    (\w+)            #member's type
    \s*?
    ([*])?            #member may be pointer type
    \s*?
    (\w+)            #member's name
""", re.VERBOSE).search

#structure's member is callback function, group 1 is return value, group 2 is function name, group 3 is parameter
_STFunc = re.compile(r"""
    (\w+?)            #return value
    \s*?
    [(]
    (.*?)            #function name
    [)]
    \s*?
    [(]
    (.*?)            #paramters
    [)]
""", re.VERBOSE | re.DOTALL).search


class ParserAPI:
    def __init__(self, DataDict):
        self.DataDict = DataDict

        #record index in browsing map or list
        self.idx = 0
        self.member = []
        self.mIdx = 0

        #record Data's name
        self.m_DataName = ''

        #record member's name
        self.m_name = ''
        
    def GetFirstData(self):
        '''return data's name, if dict is empty, return None'''
        if not self.DataDict:
            return None
        self.idx = 1
        self.m_DataName = self.DataDict.keys()[0]
        return self.m_DataName

    def GetNextData(self):
        if self.idx >= len(self.DataDict):
            return None
        self.idx += 1
        self.m_DataName = self.DataDict.keys()[self.idx-1]
        return self.m_DataName
    
    def getData(self, dataName):
        dataName = dataName.replace('\n','')
        dataName = dataName.replace(' ','')
        dataName = dataName.replace('\t','')
        for itemName in self.DataDict.keys():
            if itemName.find(dataName) != -1:
                self.m_DataName = itemName
                return itemName
        return None
    def setData(self, dataName):
        self.m_DataName = dataName
        self.member = self.DataDict[self.m_DataName].split(';')

    def GetFirstMember(self, sep):
        '''get data's member, it used by structure and enum'''
        if self.m_DataName not in self.DataDict:
            print 'Dict has no the %s key' % self.m_DataName
            return None
        
        if self.DataDict[self.m_DataName].isspace():
            return None
        
        if not self.DataDict[self.m_DataName]:
            #print "the %s key of Dict's value is empty" % self.m_DataName
            return None
        
        self.mIdx = 1
        self.member = self.DataDict[self.m_DataName].split(sep)
        
        #self.formatStruct()

        #remove comment, blank, newline
        for i in range(len(self.member)):
            if self.member[i].isspace():
                del self.member[i]
                continue
            self.member[i] = self.member[i].strip()
        return self.member[0]

    def GetNextMember(self):
        if self.mIdx >= len(self.member):
            return None
        
        self.mIdx += 1
        return self.member[self.mIdx-1]
    
    def GetIndexMember(self, index):
        if index >= len(self.member):
            return None
        return self.member[index]
    
    def getMemberInformation(self, strItem):
        if strItem == ' ' or len(strItem) == 1 or strItem == '  ' or strItem == '':
            return None
        memberInfor = []
        memberType = self.GetTypeOfMember(strItem)
        memberInfor.append(memberType)
        memberInfor.append(self.m_name)
        memberByteWidth = self.getBitWidth(self.m_name, memberType)
        memberInfor.append(memberByteWidth)
        return memberInfor
    
    def getAliasName(self, memberName):
        if memberName.find('[') != -1:
            memberName = memberName[:memberName.find('[')]
        aliasName = memberName
        if aliasNameDict.has_key(self.m_DataName):
            aliasDict = aliasNameDict[self.m_DataName]
            if aliasDict.has_key(memberName):
                aliasName = aliasDict[memberName]
        return aliasName
    
    def getChildName(self, memberName):
        #return None
        if memberName.find('[') != -1:
            memberName = memberName[:memberName.find('[')]
        if childNameDict.has_key(self.m_DataName):
            childDict = childNameDict[self.m_DataName]
            if childDict.has_key(memberName):
                return childDict[memberName]
            else:
                return None
        else:
            return None
    
    def GetTypeOfMember(self, strItem):
        '''used by structure's member, or by function's parameters'''
        global _STFunc, _STVariable
        MOFunc = _STFunc(strItem)
        MOVar = _STVariable(strItem)
        self.m_name = ''
        if MOFunc:
            return strItem
        elif MOVar:
            nIndex = 0
            nIndex1 = strItem.rfind(' ')
            nIndex2 = strItem.rfind('	')    
            if nIndex1 == -1 and nIndex2 == -1:
                return ''
            elif nIndex1 == -1 and nIndex2 != -1:
                nIndex = nIndex2
            elif nIndex1 != -1 and nIndex2 == -1:
                nIndex = nIndex1
            elif nIndex1 != -1 and nIndex2 != -1:
                if nIndex1>nIndex2:
                    nIndex = nIndex1
                else:
                    nIndex = nIndex2
            else:
                return ''
            self.m_name = strItem[nIndex+1:]
            self.m_name = self.m_name.replace(' ','')
            strType = strItem[0:nIndex]

            return strType
        else:
            return None

    def GetNameOfMember(self, strItem):
        '''only used by structure's member, or by function's parameters'''
        return self.m_name
    
    def formatMemberName(self, memberName):
        if memberName.find('[') != -1:
            memberName = memberName[:memberName.find('[')]
        return memberName

    def formatStruct(self):
        #change member name
        if self.m_DataName.find('_DVB_SERVICE') != -1:
            defaultIndex = -1
            for member in self.member:
                if member.find('DB_PID_INFO	stAudioPid[2]') != -1:
                    defaultIndex = self.member.index(member)
            if defaultIndex != -1:
                self.member.pop(defaultIndex)
                self.member.insert(defaultIndex, 'DB_PID_INFO	stAudioPid1')
                self.member.insert(defaultIndex+1, 'DB_PID_INFO	stAudioPid2')
    
    def getBitWidth(self, strValue, strType):
        strValue = strValue.replace('\n','')
        strValue = strValue.replace(' ','')
        strValue = strValue.replace('\t','')
        strType = strType.replace('\n','')
        strType = strType.replace(' ','')
        strType = strType.replace('\t','')
        if strValue.find('[') != -1:
            indexFirst = strValue.find('[')
            indexEnd = strValue.find(']')
            if typeBitwidth.has_key(strType):
                bitWidth = int(strValue[indexFirst+1:indexEnd])*typeBitwidth[strType]
            else:
                bitWidth = int(strValue[indexFirst+1:indexEnd])
            return bitWidth
        else:
            if typeBitwidth.has_key(strType):
                return typeBitwidth[strType]
            else:
                if strType.find('short') != -1:
                    return 2
                elif strType.find('char') != -1:
                    return 1
                elif strType.find('int') != -1:
                    return 4
                elif strType.find('UINT8') != -1:
                    return 1
                elif strType.find('UINT16') != -1:
                    return 2
                elif strType.find('UINT32') != -1:
                    return 4
                return 4


    
def test():
    pass
if __name__ == '__main__':
    test()
