# Path: dissect/common.py
# class KeyCache(collections.defaultdict):
#     '''
#     A dictionary based key/val cache.
# 
#     Example:
# 
#         cache = KeyCache( getFooThing )
# 
#         if cache['woot']:
#             dostuff()
# 
#     '''
#     def __init__(self, lookmeth):
#         collections.defaultdict.__init__(self)
#         self.lookmeth = lookmeth
# 
#     def __missing__(self, key):
#         valu = self.lookmeth(key)
#         self[key] = valu
#         return valu
# 
# Path: dissect/filelab.py
# class FileLab(OnDemand):
#     '''
#     Base class for file format parsers.
# 
#     The FileLab class provides routines to help file parsers
#     with concepts like API caching and on-demand parsing.
# 
#     Example:
# 
#         class FooLab(FileLab):
# 
#             def __init__(self, fd, off=0):
#                 FileLab.__init__(self, fd, off=off)
# 
#                 self.add('foo', self._getFoo )
#                 self.add('bars', self._getFooBars )
# 
#             def _getFoo(self):
#                 return 'foo'
# 
#             def _getFooBars(self):
#                 return ['bar','bar','bar']
# 
#         foo = FooLab()
# 
#         for bar in foo.get('bars'):
#             dostuff()
# 
#     '''
#     def __init__(self, fd, off=0):
#         OnDemand.__init__(self)
#         self.fd = fd
#         self.off = off
# 
#     def getStruct(self, off, cls, *args, **kwargs):
#         '''
#         Construct a VStruct and load from the file offset.
# 
#         Example:
# 
#             class Foo(VStruct):
#                 # ...
# 
#             foo = lab.getStruct(0, Foo)
# 
#         Notes:
# 
#             * if off is unspecified, the current file offset is used
# 
#         '''
#         if off == None:
#             off = self.fd.tell()
# 
#         obj = cls(*args,**kwargs)
#         obj.vsLoad( self.fd, offset=off )
#         return obj
# 
#     def readAtOff(self, off, size, shortok=False):
#         self.fd.seek(off)
#         byts = self.fd.read(size)
#         if len(byts) != size and not shortok:
#             raise Exception('readAtOff(%d,%d) short: %d' % (off,size,len(byts)))
#         return byts
# 
#     def strAtOff(self, off, codec='utf8'):
#         '''
#         Incrementally decode and return a null terminated string.
#         '''
#         self.fd.seek(off)
#         def fdbytes():
#             while True:
#                 b = self.fd.read(1)
#                 if not b:
#                     break
#                 yield b
# 
#         ret = []
#         for c in codecs.iterdecode(fdbytes(),codec):
#             if ord(c) == 0:
#                 break
# 
#             ret.append(c)
# 
#         return ''.join(ret)


from dissect.common import KeyCache
from dissect.filelab import FileLab
'''
A special FileLab extension to facilitate parsing and
normalization of binary executable constructs.
'''



class BexLab(FileLab):
    '''
    bex:arch = <name>       - A unified standard for arch names
    bex:ptr:size = <size>   - Pointer width in bytes
    bex:ptr:base = <addr>   - Base/Load address for the image

    - Memory maps
    bex:mem:maps = [ (rva,info), ... ]

    #bex:relocs = [ (rva,info), ... ]
    #bex:imports = [ (rva,info), ... ]
    #bex:exports = [ (rva,info), ... ]
    '''
    def __init__(self, fd, off=0):
        FileLab.__init__(self, fd, off=off)

# Path: dissect/common.py
# class KeyCache(collections.defaultdict):
#     '''
#     A dictionary based key/val cache.
# 
#     Example:
# 
#         cache = KeyCache( getFooThing )
# 
#         if cache['woot']:
#             dostuff()
# 
#     '''
#     def __init__(self, lookmeth):
#         collections.defaultdict.__init__(self)
#         self.lookmeth = lookmeth
# 
#     def __missing__(self, key):
#         valu = self.lookmeth(key)
#         self[key] = valu
#         return valu
# 
# Path: dissect/filelab.py
# class FileLab(OnDemand):
#     '''
#     Base class for file format parsers.
# 
#     The FileLab class provides routines to help file parsers
#     with concepts like API caching and on-demand parsing.
# 
#     Example:
# 
#         class FooLab(FileLab):
# 
#             def __init__(self, fd, off=0):
#                 FileLab.__init__(self, fd, off=off)
# 
#                 self.add('foo', self._getFoo )
#                 self.add('bars', self._getFooBars )
# 
#             def _getFoo(self):
#                 return 'foo'
# 
#             def _getFooBars(self):
#                 return ['bar','bar','bar']
# 
#         foo = FooLab()
# 
#         for bar in foo.get('bars'):
#             dostuff()
# 
#     '''
#     def __init__(self, fd, off=0):
#         OnDemand.__init__(self)
#         self.fd = fd
#         self.off = off
# 
#     def getStruct(self, off, cls, *args, **kwargs):
#         '''
#         Construct a VStruct and load from the file offset.
# 
#         Example:
# 
#             class Foo(VStruct):
#                 # ...
# 
#             foo = lab.getStruct(0, Foo)
# 
#         Notes:
# 
#             * if off is unspecified, the current file offset is used
# 
#         '''
#         if off == None:
#             off = self.fd.tell()
# 
#         obj = cls(*args,**kwargs)
#         obj.vsLoad( self.fd, offset=off )
#         return obj
# 
#     def readAtOff(self, off, size, shortok=False):
#         self.fd.seek(off)
#         byts = self.fd.read(size)
#         if len(byts) != size and not shortok:
#             raise Exception('readAtOff(%d,%d) short: %d' % (off,size,len(byts)))
#         return byts
# 
#     def strAtOff(self, off, codec='utf8'):
#         '''
#         Incrementally decode and return a null terminated string.
#         '''
#         self.fd.seek(off)
#         def fdbytes():
#             while True:
#                 b = self.fd.read(1)
#                 if not b:
#                     break
#                 yield b
# 
#         ret = []
#         for c in codecs.iterdecode(fdbytes(),codec):
#             if ord(c) == 0:
#                 break
# 
#             ret.append(c)
# 
#         return ''.join(ret)


# Path: dissect/bexlab.py
from dissect.common import KeyCache
from dissect.filelab import FileLab

'''
A special FileLab extension to facilitate parsing and
normalization of binary executable constructs.
'''



class BexLab(FileLab):
    '''
    bex:arch = <name>       - A unified standard for arch names
    bex:ptr:size = <size>   - Pointer width in bytes
    bex:ptr:base = <addr>   - Base/Load address for the image

    - Memory maps
    bex:mem:maps = [ (rva,info), ... ]

    #bex:relocs = [ (rva,info), ... ]
    #bex:imports = [ (rva,info), ... ]
    #bex:exports = [ (rva,info), ... ]
    '''
    def __init__(self, fd, off=0):
        FileLab.__init__(self, fd, off=off)

        self._bex_rva2off = KeyCache( self._rvaToOff )