diff options
| author | comex <comexk@gmail.com> | 2009-01-28 12:34:10 -0500 |
|---|---|---|
| committer | comex <comexk@gmail.com> | 2009-01-28 12:34:10 -0500 |
| commit | 50d3baa2cdcdfb8ad20bd5cd59cbdcb07db731bc (patch) | |
| tree | 007da64a2f08737aa9f1561f16b181d46d0ffd33 /ethyl.py | |
| parent | 2a0c75e9811b0d66282765a996b7ebebb1ce5c83 (diff) | |
refactoring
Diffstat (limited to 'ethyl.py')
| -rw-r--r-- | ethyl.py | 143 |
1 files changed, 142 insertions, 1 deletions
@@ -1,3 +1,4 @@ +import sys, struct, re formats = { 'pane': ''' u8 flags_1 // 8 @@ -61,4 +62,144 @@ formats = { u32 c ''', -}
\ No newline at end of file +} + +for (dname, definition) in formats.items(): + definition = re.sub(re.compile('//.*$', re.M), '', definition) + definition = definition.strip() + definition = re.sub('\n[\n ]+', '\n', definition) + df = [[j.strip() for j in i.strip().split()] for i in definition.split('\n')] + df = [] + etc = etcn = False + for i in definition.split('\n'): + i = i.strip() + if i[:3] == 'etc': + etc = True + if i == 'etc!': + etcn = True + continue + typ, name = [j.strip() for j in i.split()] + m = re.match('^([^\[]+)\[([a-zA-Z0-9]+)\]$', name) + if m: + name = m.group(1) + size = eval(m.group(2)) + df.append((typ, (name, size))) + else: + df.append((typ, name)) + formats[dname] = df, etc, etcn + + + +def pr_dict(data, start=''): + for a in sorted(data.keys()): + b = data[a] + print '%s%s: %s' % (start, str(a), hex(b) if type(b) in (int, long) else repr(b)) +types = { + 'u8': 'B', + 'u16': 'H', + 'u32': 'I', + 'u64': 'Q', + 's8': 'b', + 's16': 'h', + 's32': 'i', + 's64': 'q', + 'float': 'f', + 'f32': 'f', + 'double': 'd', + 'f64': 'd', + 'bool': 'c', + 'char': 'c', +} +def parse_var(pos, typ, chunk): + if not types.has_key(typ): + raise Exception('What\'s a %s?' % typ) + fmt = '>' + types[typ] + size = struct.calcsize(fmt) + + return (pos + size), struct.unpack(fmt, chunk[pos:pos + size])[0] +def nullterm(str_plus): + z = str_plus.find('\0') + if z != -1: + return str_plus[:z] + else: + return str_plus +def parse_data(chunk, definition, prefix=None, start=0): + df, etc, etcn = formats[definition] + #print df, repr(definition) + #print df + + pos = start + ret = {} + for typ, name in df: + try: + name, size = name + except: + pos, var = parse_var(pos, typ, chunk) + else: + if typ == 'char': + var = chunk[pos:pos+size].rstrip(chr(0)) + pos += size + else: + var = [] + for n in xrange(size): + pos, varn = parse_var(pos, typ, chunk) + var.append(varn) + if ret.has_key(name): + try: + ret[name].append(var) + except AttributeError: + ret[name] = [ret[name], var] + else: + ret[name] = var + #print hex(pos) + if pos > len(chunk): + raise Exception('too much!') + if pos < len(chunk): + if etc and not etcn: + ret['etc'] = repr(chunk[pos:]) + elif not etc: + raise Exception('Incomplete handling...') + if prefix is not None: + ret2 = {} + for (k, v) in ret.items(): + ret2[prefix + '.' + k] = v + ret = ret2 + return (ret, pos) if etcn else ret +def unparse_var(typ, var): + if not types.has_key(typ): + raise Exception('What\'s a %s?' % typ) + return struct.pack('>' + types[typ], var) +def unparse_data(vars, definition, prefix=None): + df, etc, etcn = formats[definition] + ret = '' + for typ, name in df: + size = None + try: + name, size = name + except: + pass + if prefix is not None: + name = re.sub('^' + re.quote(prefix) + '\.', '', name) + var = vars[name] + if size is None: + ret += unparse_var(typ, var) + else: + if typ == 'char': + ret += var.ljust(size, '\0') + else: + assert len(var) == size + for v in var: + ret += unparse_var(typ, v) + return ret +def iff_to_chunks(z): + pos = 0 + chunks = [] + while pos < len(z): + cc = z[pos:pos+4] + length, = struct.unpack('>I', z[pos+4:pos+8]) + #print cc + #print hex(length) + data = z[pos+8:pos+length] + pos += length + chunks.append((cc, data)) + return chunks
\ No newline at end of file |
