def _parsetemplate(self, template): if isinstance(template, str): template = [template] # remove spaces from template tmplstr = re.sub('\s+', '', template[0]) # if template is shorter than data, don't match data = self.data.rstrip('\0') if len(data) > len(tmplstr)/2: return False # pad data with zeroes to match with template data = self.data + '\0'*max(0, len(tmplstr)/2-len(self.data)) # create template data with variables set to zero to be able to use getdata() tmpldatastr = re.sub('[^0-9a-f]', '0', tmplstr) tmpldata = ''.join([chr(int(tmpldatastr[i:i+2], 16)) for i in range(0, len(tmpldatastr), 2)]) # determine fields and their nibble-offsets from template fields = [] # field names (or '0' for literal) tmploffsets = [] # offsets of fields from template lastchar = None for i in range(len(tmplstr)): curchar = tmplstr[i] if curchar in '0123456789abcdef': curchar = '0' if curchar != lastchar: fields.append(curchar) tmploffsets.append(i*4) lastchar = curchar tmploffsets.append(len(tmplstr)*4) # determine field boundaries, in the following order: # 1. specified start-offsets, if any # 1b. apply fixed-width fields with known start-offsets # 2. boundaries of template characters # 2b. apply fixed-width fields with known start-offsets # 3. boundaries of template literals offsets = [None] * (len(fields)+1) if len(template) > 1 and template[1]: for fchar,bitoffs in template[1].iteritems(): offsets[fields.index(fchar)] = tmplstr.find(fchar)*4 + bitoffs self._apply_fixedwidth(fields, offsets) # boundaries of template characters for i in range(len(tmploffsets)-1): if offsets[i] is not None: continue if fields[i] == '0': continue offsets[i] = tmploffsets[i] self._apply_fixedwidth(fields, offsets) # boundaries of template literals for i in range(len(tmploffsets)): if offsets[i] is not None: continue offsets[i] = tmploffsets[i] self._apply_fixedwidth(fields, offsets) # now parse all fields fieldvalues={} for i in range(len(fields)): value = getbits(data, offsets[i], offsets[i+1]) curchar = fields[i] if curchar == '0': # literal: check with template tmplvalue = getbits(tmpldata, offsets[i], offsets[i+1]) if tmplvalue != value: return False else: # template variable: store fname, fchar, flen, ftype = self._field_by_char(curchar) try: fieldvalues[fname] = ftype(value, obj=self, width=(offsets[i+1]-offsets[i]+3)/4) except TypeError: fieldvalues[fname] = ftype(value) # everything is ok, incorporate fields self.__dict__.update(fieldvalues) return True
def getbits(self, start, end): # return number at bit positions of data (0 is beginning) return getbits(self.data, start, end)