Return a list of entries in the given IFD.

def dump_ifd(self, ifd, ifd_name, tag_dict=EXIF_TAGS, relative=0, stop_tag=DEFAULT_STOP_TAG):
        """
        Return a list of entries in the given IFD.
        """
        # make sure we can process the entries
        try:
            entries = self.s2n(ifd, 2)
        except TypeError:
            logger.warning("Possibly corrupted IFD: %s" % ifd)
            return

        for i in range(entries):
            # entry is index of start of this IFD in the file
            entry = ifd + 2 + 12 * i
            tag = self.s2n(entry, 2)

            # get tag name early to avoid errors, help debug
            tag_entry = tag_dict.get(tag)
            if tag_entry:
                tag_name = tag_entry[0]
            else:
                tag_name = 'Tag 0x%04X' % tag

            # ignore certain tags for faster processing
            if not (not self.detailed and tag in IGNORE_TAGS):
                field_type = self.s2n(entry + 2, 2)

                # unknown field type
                if not 0 < field_type < len(FIELD_TYPES):
                    if not self.strict:
                        continue
                    else:
                        raise ValueError('Unknown type %d in tag 0x%04X' % (field_type, tag))

                type_length = FIELD_TYPES[field_type][0]
                count = self.s2n(entry + 4, 4)
                # Adjust for tag id/type/count (2+2+4 bytes)
                # Now we point at either the data or the 2nd level offset
                offset = entry + 8

                # If the value fits in 4 bytes, it is inlined, else we
                # need to jump ahead again.
                if count * type_length > 4:
                    # offset is not the value; it's a pointer to the value
                    # if relative we set things up so s2n will seek to the right
                    # place when it adds self.offset.  Note that this 'relative'
                    # is for the Nikon type 3 makernote.  Other cameras may use
                    # other relative offsets, which would have to be computed here
                    # slightly differently.
                    if relative:
                        tmp_offset = self.s2n(offset, 4)
                        offset = tmp_offset + ifd - 8
                        if self.fake_exif:
                            offset += 18
                    else:
                        offset = self.s2n(offset, 4)

                field_offset = offset
                values = None
                if field_type == 2:
                    # special case: null-terminated ASCII string
                    # XXX investigate
                    # sometimes gets too big to fit in int value
                    if count != 0:  # and count < (2**31):  # 2E31 is hardware dependant. --gd
                        file_position = self.offset + offset
                        try:
                            self.file.seek(file_position)
                            values = self.file.read(count)
                            #print(values)
                            # Drop any garbage after a null.
                            values = values.split(b'\x00', 1)[0]
                            if isinstance(values, bytes):
                                try:
                                    values = values.decode("utf-8")
                                except UnicodeDecodeError:
                                    logger.warning("Possibly corrupted field %s in %s IFD", tag_name, ifd_name)
                        except OverflowError:
                            logger.warn('OverflowError at position: %s, length: %s', file_position, count)
                            values = ''
                        except MemoryError:
                            logger.warn('MemoryError at position: %s, length: %s', file_position, count)
                            values = ''
                else:
                    values = []
                    signed = (field_type in [6, 8, 9, 10])

                    # XXX investigate
                    # some entries get too big to handle could be malformed
                    # file or problem with self.s2n
                    if count < 1000:
                        for dummy in range(count):
                            if field_type in (5, 10):
                                # a ratio
                                value = Ratio(self.s2n(offset, 4, signed),
                                              self.s2n(offset + 4, 4, signed))
                            else:
                                value = self.s2n(offset, type_length, signed)
                            values.append(value)
                            offset = offset + type_length
                    # The test above causes problems with tags that are
                    # supposed to have long values! Fix up one important case.
                    elif tag_name in ('MakerNote', makernote.canon.CAMERA_INFO_TAG_NAME):
                        for dummy in range(count):
                            value = self.s2n(offset, type_length, signed)
                            values.append(value)
                            offset = offset + type_length

                # now 'values' is either a string or an array
                if count == 1 and field_type != 2:
                    printable = str(values[0])
                elif count > 50 and len(values) > 20:
                    printable = str(values[0:20])[0:-1] + ", ... ]"
                else:
                    try:
                        printable = str(values)
                    # fix for python2's handling of unicode values
                    except UnicodeEncodeError:
                        printable = unicode(values)

                # compute printable version of values
                if tag_entry:
                    # optional 2nd tag element is present
                    if len(tag_entry) != 1:
                        if callable(tag_entry[1]):
                            # call mapping function
                            printable = tag_entry[1](values)
                        elif type(tag_entry[1]) is tuple:
                            ifd_info = tag_entry[1]
                            try:
                                logger.debug('%s SubIFD at offset %d:', ifd_info[0], values[0])
                                self.dump_ifd(values[0], ifd_info[0], tag_dict=ifd_info[1], stop_tag=stop_tag)
                            except IndexError:
                                logger.warn('No values found for %s SubIFD', ifd_info[0])
                        else:
                            printable = ''
                            for i in values:
                                # use lookup table for this tag
                                printable += tag_entry[1].get(i, repr(i))

                self.tags[ifd_name + ' ' + tag_name] = IfdTag(printable, tag,
                                                              field_type,
                                                              values, field_offset,
                                                              count * type_length)
                try:
                    tag_value = repr(self.tags[ifd_name + ' ' + tag_name])
                # fix for python2's handling of unicode values
                except UnicodeEncodeError:
                    tag_value = unicode(self.tags[ifd_name + ' ' + tag_name])
                logger.debug(' %s: %s', tag_name, tag_value)

            if tag_name == stop_tag:
                break