# Path: pyfive/core.py
# def _padded_size(size, padding_multipe=8):
#     """ Return the size of a field padded to be a multiple a give value. """
#     return int(ceil(size / padding_multipe) * padding_multipe)
# 
# def _structure_size(structure):
#     """ Return the size of a structure in bytes. """
#     fmt = '<' + ''.join(structure.values())
#     return struct.calcsize(fmt)
# 
# Path: pyfive/core.py
# def _unpack_struct_from(structure, buf, offset=0):
#     """ Unpack a structure into an OrderedDict from a buffer of bytes. """
#     fmt = '<' + ''.join(structure.values())
#     values = struct.unpack_from(fmt, buf, offset=offset)
#     return OrderedDict(zip(structure.keys(), values))
# 
# def _unpack_struct_from_file(structure, fh):
#     """ Unpack a structure into an OrderedDict from an open file. """
#     size = _structure_size(structure)
#     buf = fh.read(size)
#     return _unpack_struct_from(structure, buf)
# 
# Path: pyfive/core.py
# class InvalidHDF5File(Exception):
#     """ Exception raised when an invalid HDF5 file is detected. """
#     pass


import struct
from collections import OrderedDict
from .core import _padded_size, _structure_size
from .core import _unpack_struct_from, _unpack_struct_from_file
from .core import InvalidHDF5File

    def __init__(self, fh, offset):

        fh.seek(offset)
        header = _unpack_struct_from_file(GLOBAL_HEAP_HEADER, fh)
        assert header['signature'] == b'GCOL'
        assert header['version'] == 1
        heap_data_size = header['collection_size'] - GLOBAL_HEAP_HEADER_SIZE
        heap_data = fh.read(heap_data_size)
        assert len(heap_data) == heap_data_size  # check for early end of file

        self.heap_data = heap_data
        self._header = header
        self._objects = None

    @property
    def objects(self):
        """ Dictionary of objects in the heap. """
        if self._objects is None:
            self._objects = OrderedDict()
            offset = 0
            while offset < len(self.heap_data):
                info = _unpack_struct_from(
                    GLOBAL_HEAP_OBJECT, self.heap_data, offset)
                if info['object_index'] == 0:
                    break
                offset += GLOBAL_HEAP_OBJECT_SIZE
                fmt = '<' + str(info['object_size']) + 's'
                obj_data = struct.unpack_from(fmt, self.heap_data, offset)[0]
                self._objects[info['object_index']] = obj_data

# Path: pyfive/core.py
# def _padded_size(size, padding_multipe=8):
#     """ Return the size of a field padded to be a multiple a give value. """
#     return int(ceil(size / padding_multipe) * padding_multipe)
# 
# def _structure_size(structure):
#     """ Return the size of a structure in bytes. """
#     fmt = '<' + ''.join(structure.values())
#     return struct.calcsize(fmt)
# 
# Path: pyfive/core.py
# def _unpack_struct_from(structure, buf, offset=0):
#     """ Unpack a structure into an OrderedDict from a buffer of bytes. """
#     fmt = '<' + ''.join(structure.values())
#     values = struct.unpack_from(fmt, buf, offset=offset)
#     return OrderedDict(zip(structure.keys(), values))
# 
# def _unpack_struct_from_file(structure, fh):
#     """ Unpack a structure into an OrderedDict from an open file. """
#     size = _structure_size(structure)
#     buf = fh.read(size)
#     return _unpack_struct_from(structure, buf)
# 
# Path: pyfive/core.py
# class InvalidHDF5File(Exception):
#     """ Exception raised when an invalid HDF5 file is detected. """
#     pass


# Path: pyfive/misc_low_level.py
import struct
from collections import OrderedDict
from .core import _padded_size, _structure_size
from .core import _unpack_struct_from, _unpack_struct_from_file
from .core import InvalidHDF5File


    def __init__(self, fh, offset):

        fh.seek(offset)
        header = _unpack_struct_from_file(GLOBAL_HEAP_HEADER, fh)
        assert header['signature'] == b'GCOL'
        assert header['version'] == 1
        heap_data_size = header['collection_size'] - GLOBAL_HEAP_HEADER_SIZE
        heap_data = fh.read(heap_data_size)
        assert len(heap_data) == heap_data_size  # check for early end of file

        self.heap_data = heap_data
        self._header = header
        self._objects = None

    @property
    def objects(self):
        """ Dictionary of objects in the heap. """
        if self._objects is None:
            self._objects = OrderedDict()
            offset = 0
            while offset < len(self.heap_data):
                info = _unpack_struct_from(
                    GLOBAL_HEAP_OBJECT, self.heap_data, offset)
                if info['object_index'] == 0:
                    break
                offset += GLOBAL_HEAP_OBJECT_SIZE
                fmt = '<' + str(info['object_size']) + 's'
                obj_data = struct.unpack_from(fmt, self.heap_data, offset)[0]
                self._objects[info['object_index']] = obj_data

                offset += _padded_size(info['object_size'])