/******************************************************************************
 * public メソッド
 *****************************************************************************/
TemplateVariableCreator::TemplateVariableCreator(apr_pool_t *pool,
                                                 const char **ids)
  : pool_(pool),
    ids_(ids),
    var_scr_pool_(NULL),
    var_scr_pool_end_(NULL)
{
    // ダミー用に 1 つ分多く確保
    APR_PALLOC(variables_, variable_t **, pool_,
               sizeof(variable_t *) * (get_entry_count(ids) + 1));

    memset(variables_, 0, sizeof(variable_t *) * (get_entry_count(ids) + 1));
}
예제 #2
0
/**
 * Throws exif_failure_exception if the exif data state is determined to be invalid
 * such that further entry parsing would be invalid.
 * @Throws exif_failure_exception_t
 */
static string get_exif_long(tiff_handle_t &tiff_handle, uint32_t ifd_entry_offset) {

    // print each long separated by a space
    uint32_t count = get_entry_count(tiff_handle, ifd_entry_offset);
    uint32_t offset = get_data_offset(tiff_handle, ifd_entry_offset);

    // Abort on count overflow
    tiff_handle.bytes_read += count * 4; // exif standard: 1 exif long is 4 bytes long
    if (count >= 0x4000 || tiff_handle.bytes_read >= 0x10000) throw exif_failure_exception_t();

    if (count == 1) {
        // count is 1 so print the long directly
        stringstream ss;
        try {
	    ss << (uint32_t)tiff_handle.sbuf->get32u(offset);
        } catch (sbuf_t::range_exception_t &e) {
            // add nothing to ss
        }
        return ss.str();

    } else {
        // count is not 1 so print the uint32_t bytes as utf8
        std::string s = get_possible_utf32(*(tiff_handle.sbuf)+offset, count, tiff_handle.byte_order);
#ifdef DEBUG
        cout << "exif_entry.get_exif_short (escaped): '" << validateOrEscapeUTF8(s, true, true) << "'\n";
#endif
        return s;
    }
}
예제 #3
0
/**
 * Throws exif_failure_exception if the exif data state is determined to be invalid
 * such that further entry parsing would be invalid.
 * @Throws exif_failure_exception_t
 */
static string get_exif_srational(tiff_handle_t &tiff_handle, uint32_t ifd_entry_offset) {
    // print each rational as 1'st uint32, "/", 2'nd uint32, separated by a space
    uint32_t count = get_entry_count(tiff_handle, ifd_entry_offset);
    uint32_t offset = get_data_offset(tiff_handle, ifd_entry_offset);

    // Abort on count overflow
    tiff_handle.bytes_read += count * 8; // exif standard: 1 exif srational is 8 bytes long
    if (count >= 0x2000 || tiff_handle.bytes_read >= 0x10000) throw exif_failure_exception_t();

    stringstream ss;
    for (uint32_t i=0; i<count; i++) {
        try {
	    // return 1'st int32, "/", 2'nd int32
            ss << tiff_handle.sbuf->get32i(offset + i * 8, tiff_handle.byte_order) << "/"
               << tiff_handle.sbuf->get32i(offset + i * 8 + 4, tiff_handle.byte_order);
	    if (i + 1 < count) {
	        ss << " ";
	    }
        } catch (sbuf_t::range_exception_t &e) {
            break;
        }
    }
    return ss.str();
}
예제 #4
0
/**
 * Throws exif_failure_exception if the exif data state is determined to be invalid
 * such that further entry parsing would be invalid.
 * @Throws exif_failure_exception_t
 */
static  string get_exif_slong(tiff_handle_t &tiff_handle, uint32_t ifd_entry_offset) {
    // print each signed long
    uint32_t count = get_entry_count(tiff_handle, ifd_entry_offset);
    uint32_t offset = get_data_offset(tiff_handle, ifd_entry_offset);

    // Abort on count overflow
    tiff_handle.bytes_read += count * 4; // exif standard: 1 exif slong is 4 bytes long
    if (count >= 0x4000 || tiff_handle.bytes_read >= 0x10000) throw exif_failure_exception_t();

    stringstream ss;
    for (uint32_t i=0; i<count; i++) {
        try {
	    ss << tiff_handle.sbuf->get32i(offset + i * 4, tiff_handle.byte_order);
        } catch (sbuf_t::range_exception_t &e) {
            // at end
            break;
        }
	if (i + 1 < count) {
	    ss << " ";
	}
    }

    return ss.str();
}
예제 #5
0
/**
 * Throws exif_failure_exception if the exif data state is determined to be invalid
 * such that further entry parsing would be invalid.
 * @Throws exif_failure_exception_t
 */
static string get_exif_ascii(tiff_handle_t &tiff_handle, uint32_t ifd_entry_offset) {
    // print each byte as a character in a string
    uint32_t count = get_entry_count(tiff_handle, ifd_entry_offset);
    uint32_t offset = get_data_offset(tiff_handle, ifd_entry_offset);

    // Abort on count overflow
    tiff_handle.bytes_read += count; // exif standard: 1 exif ascii value is 1 byte long
    if (count >= 0x10000 || tiff_handle.bytes_read >= 0x10000) throw exif_failure_exception_t();

    // strip off "\0" allowing up to 2 \0 markers because tiff terminates with \0 using byte pairs
    try {
        if (count > 0 && tiff_handle.sbuf->get8u(offset + count - 1) == 0) {
	    count--;
        }
        if (count > 0 && tiff_handle.sbuf->get8u(offset + count - 1) == 0) {
	    count--;
        }
    } catch (sbuf_t::range_exception_t &e) {
        // at end so there is nothing to strip
    }

    // although 7-bit ascii is expected, parse using UTF-8
    return get_possible_utf8(*(tiff_handle.sbuf)+offset, count);
}
예제 #6
0
/**
 * Throws exif_failure_exception if the exif data state is determined to be invalid
 * such that further entry parsing would be invalid.
 * @Throws exif_failure_exception_t
 */
static string get_exif_byte(tiff_handle_t &tiff_handle, uint32_t ifd_entry_offset) {
 
    uint32_t count = get_entry_count(tiff_handle, ifd_entry_offset);
    uint32_t offset = get_data_offset(tiff_handle, ifd_entry_offset);

    // Abort on count overflow
    tiff_handle.bytes_read += count; // exif standard: 1 exif byte is 1 byte long
    if (count >= 0x10000 || tiff_handle.bytes_read >= 0x10000) throw exif_failure_exception_t();

    if (count == 1) {
        // count is 1 so print the byte as an integer
        stringstream ss;
        try {
	    ss << (int)tiff_handle.sbuf->get8u(offset);
        } catch (sbuf_t::range_exception_t &e) {
            // add nothing to ss
        }
        return ss.str();

    } else {
        // count is not 1 so return the bytes as utf8
        return get_possible_utf8(*(tiff_handle.sbuf)+offset, count);
    }
}
예제 #7
0
/*!
 * This function is used by the proc file system to read the DPTC log buffer.
 * Each time the DPTC proc file system file is read this function is called
 * and returns the data written in the log buffer.
 *
 * @param    buf	pointer to the buffer the data should be written to.
 * @param    start	pointer to the pointer where the new data is
 *                      written to.
 *			procedure should update the start pointer to point to
 *			where in the buffer the data was written.
 * @param    offset	current offset in the DPTC proc file.
 * @param    count	number of bytes to read.
 * @param    eof	pointer to eof flag. should be set to 1 when
 *                      reaching eof.
 * @param    data	driver specific data pointer.
 *
 * @return   number byte read from the log buffer.
 *
 */
static int read_log(char *buf, char **start, off_t offset, int count,
		    int *eof, void *data)
{
	int entries_to_read;
	int num_of_entries;
	int entries_to_end_of_buffer, entries_left;
	void *entry_ptr;
	char *buf_ptr;
	dvfs_dptc_params_s *params;

	params = (dvfs_dptc_params_s *) data;

	/* Calculate number of log entries to read */
	entries_to_read = count / sizeof(dptc_log_entry_s);
	/* Get the number of current log buffer entries */
	num_of_entries = get_entry_count(&params->dptc_log_buffer);

	/*
	 * If number of entries to read is larger that the number of entries
	 * in the log buffer set number of entries to read to number of
	 * entries in the log buffer and set eof flag to 1
	 */
	if (num_of_entries < entries_to_read) {
		entries_to_read = num_of_entries;
		*eof = 1;
	}

	/*
	 * Down the log buffer mutex to exclude others from reading and
	 * writing to the log buffer.
	 */
	if (down_interruptible(&params->dptc_log_buffer.mutex)) {
		return -EAGAIN;
	}

	if (num_of_entries == 0 && offset == 0) {
		inc_log_index(&params->dptc_log_buffer.tail, -1);
		num_of_entries++;
		entries_to_read++;
	}

	/* get the pointer of the last (oldest) entry in the log buffer */
	entry_ptr = (void *)&params->dptc_log_buffer.
	    entries[params->dptc_log_buffer.tail];

	/* Check if tail index wraps during current read */
	if ((params->dptc_log_buffer.tail + entries_to_read) < LOG_ENTRIES) {
		/* No tail wrap around copy data from log buffer to buf */
		memcpy(buf, entry_ptr,
		       (entries_to_read * sizeof(dptc_log_entry_s)));
	} else {
		/*
		 * Tail wrap around.
		 * First copy data from current position until end of buffer,
		 * after that copy the rest from start of the log buffer.
		 */
		entries_to_end_of_buffer = LOG_ENTRIES -
		    params->dptc_log_buffer.tail;
		memcpy(buf, entry_ptr,
		       (entries_to_end_of_buffer * sizeof(dptc_log_entry_s)));

		entry_ptr = (void *)&params->dptc_log_buffer.entries[0];
		buf_ptr = buf +
		    (entries_to_end_of_buffer * sizeof(dptc_log_entry_s));
		entries_left = entries_to_read - entries_to_end_of_buffer;
		memcpy(buf_ptr, entry_ptr,
		       (entries_left * sizeof(dptc_log_entry_s)));
	}

	/* Increment the tail index by the number of entries read */
	inc_log_index(&params->dptc_log_buffer.tail, entries_to_read);

	/* Up the log buffer mutex to allow access to the log buffer */
	up(&params->dptc_log_buffer.mutex);

	/* set start of data to point to buf */
	*start = buf;

	return (entries_to_read * sizeof(dptc_log_entry_s));
}
예제 #8
0
void entry_reader::parse_entry(ifd_type_t ifd_type, tiff_handle_t &tiff_handle,
			       size_t ifd_entry_offset, entry_list_t &entries) {
/** 
 * parse_ifd_entry() parses one entry and places it into entries.
 * Throws exif_failure_exception if the exif data state is determined to be invalid
 * such that further entry parsing would be invalid.
 * @Throws exif_failure_exception_t
 */

    // check now that the 12 entry bytes are available
    if (ifd_entry_offset + 12 > tiff_handle.sbuf->bufsize) {
	// no space for entry record
	return;
    }

    // entry tag
    const uint16_t entry_tag = get_entry_tag(tiff_handle, ifd_entry_offset);
#ifdef DEBUG
    const uint16_t zentry_type = get_entry_type(tiff_handle, ifd_entry_offset);
    uint32_t zcount = get_entry_count(tiff_handle, ifd_entry_offset);
    uint32_t zoffset = get_data_offset(tiff_handle, ifd_entry_offset);
    cout << "exif_entry.parse_entry entry tag: " << entry_tag << ", entry type: " << zentry_type << " entry count: " << zcount << ", entry offset: " << zoffset;
#endif

    // add entry or parse entry's nested IFD, based on entry_tag
#ifdef DEBUG
    cout << "exif_entry.parse_entry IFD type: " << (int)ifd_type << "\n";
#endif
    switch (ifd_type) {
    case IFD0_TIFF:	// see table Tag Support Levels(1) for 0th IFD TIFF Tags
    case IFD1_TIFF:	// see table Tag Support Levels(1) for 0th IFD TIFF Tags
        uint32_t forwarded_ifd_offset;
        switch (entry_tag) {
	case 0x0100: add_entry(ifd_type, "ImageWidth", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0101: add_entry(ifd_type, "ImageLength", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0102: add_entry(ifd_type, "BitsPerSample", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0103: add_entry(ifd_type, "Compression", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0106: add_entry(ifd_type, "PhotometricInterpreation", tiff_handle, ifd_entry_offset, entries); break;
	case 0x010e: add_entry(ifd_type, "ImageDescription", tiff_handle, ifd_entry_offset, entries); break;
	case 0x010f: add_entry(ifd_type, "Make", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0110: add_entry(ifd_type, "Model", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0111: add_entry(ifd_type, "StripOffsets", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0112: add_entry(ifd_type, "Orientation", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0115: add_entry(ifd_type, "SamplesPerPixel", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0116: add_entry(ifd_type, "RowsPerStrip", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0117: add_entry(ifd_type, "StripByteCounts", tiff_handle, ifd_entry_offset, entries); break;
	case 0x011a: add_entry(ifd_type, "XResolution", tiff_handle, ifd_entry_offset, entries); break;
	case 0x011b: add_entry(ifd_type, "YResolution", tiff_handle, ifd_entry_offset, entries); break;
	case 0x011c: add_entry(ifd_type, "PlanarConfiguration", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0128: add_entry(ifd_type, "ResolutionUnit", tiff_handle, ifd_entry_offset, entries); break;
	case 0x012d: add_entry(ifd_type, "TransferFunction", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0131: add_entry(ifd_type, "Software", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0132: add_entry(ifd_type, "DateTime", tiff_handle, ifd_entry_offset, entries); break;
	case 0x013b: add_entry(ifd_type, "Artist", tiff_handle, ifd_entry_offset, entries); break;
	case 0x013e: add_entry(ifd_type, "WhitePoint", tiff_handle, ifd_entry_offset, entries); break;
	case 0x013f: add_entry(ifd_type, "PrimaryChromaticities", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0201: add_entry(ifd_type, "JPEGInterchangeFormat", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0202: add_entry(ifd_type, "JPEGInterchangeFormatLength", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0211: add_entry(ifd_type, "YCbCrCoefficients", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0212: add_entry(ifd_type, "YCbCrSubSampling", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0213: add_entry(ifd_type, "YCbCrPositioning", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0214: add_entry(ifd_type, "ReferenceBlackWhite", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8298: add_entry(ifd_type, "Copyright", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8769: // EXIF tag
            forwarded_ifd_offset = get_ifd_offset(tiff_handle, ifd_entry_offset);
            if (ifd_type == IFD0_TIFF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries case8769 IFD0_tiff to IFD0_EXIF: ifd_entry_offset: " << ifd_entry_offset << " forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD0_EXIF, tiff_handle, forwarded_ifd_offset, entries);
            } else if (ifd_type == IFD1_TIFF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries case8769 IFD1_tiff to IFD1_EXIF: ifd_entry_offset:" << ifd_entry_offset << " forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD1_EXIF, tiff_handle, forwarded_ifd_offset, entries);
            } else {
		assert(0);
            }
            break;
	case 0x8825: // GPS tag
            forwarded_ifd_offset = get_ifd_offset(tiff_handle, ifd_entry_offset);
            if (ifd_type == IFD0_TIFF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries case8825 IFD0_tiff to IFD0_GPS: forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD0_GPS, tiff_handle, forwarded_ifd_offset, entries);
            } else if (ifd_type == IFD1_TIFF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries case8825 IFD1_tiff to IFD1_GPS: forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD1_GPS, tiff_handle, forwarded_ifd_offset, entries);
            } else {
		assert(0);
            }
            break;
	default:
            add_generic_entry(ifd_type, tiff_handle, ifd_entry_offset, entries);
            break;
        }
        break;
    case IFD0_EXIF:	// see table Tag Support Levels(1) for 0th IFD TIFF Tags
    case IFD1_EXIF:	// see table Tag Support Levels(1) for 0th IFD TIFF Tags
        switch (entry_tag) {
	case 0x829a: add_entry(ifd_type, "ExposureTime", tiff_handle, ifd_entry_offset, entries); break;
	case 0x829d: add_entry(ifd_type, "FNumber", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8822: add_entry(ifd_type, "ExposureProgram", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8824: add_entry(ifd_type, "SpectralSensitivity", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8827: add_entry(ifd_type, "PhotographicSensitivity", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8828: add_entry(ifd_type, "OECF", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8830: add_entry(ifd_type, "SensitivityType", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8831: add_entry(ifd_type, "StandardOutputSensitivity", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8832: add_entry(ifd_type, "RecommendedExposureIndex", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8833: add_entry(ifd_type, "ISOSpeed", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8834: add_entry(ifd_type, "ISOSpeedLatitudeyyy", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8835: add_entry(ifd_type, "IOSpeedLatitudezzz", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9000: add_entry(ifd_type, "ExifVersion", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9003: add_entry(ifd_type, "DateTimeOriginal", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9004: add_entry(ifd_type, "DateTimeDigitized", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9101: add_entry(ifd_type, "ComponentsConfiguration", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9102: add_entry(ifd_type, "CompressedBitsPerPixel", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9201: add_entry(ifd_type, "ShutterSpeedValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9202: add_entry(ifd_type, "ApertureValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9203: add_entry(ifd_type, "BrightnessValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9204: add_entry(ifd_type, "ExposureBiasValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9205: add_entry(ifd_type, "MaxApertureValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9206: add_entry(ifd_type, "SubjectDistance", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9207: add_entry(ifd_type, "MeteringMode", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9208: add_entry(ifd_type, "LightSource", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9209: add_entry(ifd_type, "Flash", tiff_handle, ifd_entry_offset, entries); break;
	case 0x920a: add_entry(ifd_type, "FocalLength", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9214: add_entry(ifd_type, "SubjectArea", tiff_handle, ifd_entry_offset, entries); break;
	case 0x927c: add_maker_note_entry(ifd_type, "MakerNote", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9286: add_entry(ifd_type, "UserComment", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9290: add_entry(ifd_type, "SubSecTime", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9291: add_entry(ifd_type, "SubSecTimeOriginal", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9292: add_entry(ifd_type, "SubSecTimeDigitized", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa000: add_entry(ifd_type, "FlashpixVersion", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa001: add_entry(ifd_type, "ColorSpace", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa002: add_entry(ifd_type, "PixelXDimension", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa003: add_entry(ifd_type, "PixelYDimension", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa004: add_entry(ifd_type, "RelatedSoundFile", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa005: // Interoperability tag
            forwarded_ifd_offset = get_ifd_offset(tiff_handle, ifd_entry_offset);
            if (ifd_type == IFD0_EXIF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries casea005 IFD0_EXIF to IFD0_INTEROP: ifd_entry_offset: " << ifd_entry_offset << ", forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD0_INTEROPERABILITY, tiff_handle, forwarded_ifd_offset, entries);
            } else if (ifd_type == IFD1_EXIF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries casea005 IFD1_EXIF to IFD1_INTEROP: forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD1_INTEROPERABILITY, tiff_handle, forwarded_ifd_offset, entries);
            } else {
		assert(0);
            }
            break;
	case 0xa20b: add_entry(ifd_type, "FlashEnergy", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa20c: add_entry(ifd_type, "SpatialFrequencyResponse", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa20e: add_entry(ifd_type, "FocalPlaneXResolution", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa20f: add_entry(ifd_type, "FocalPlaneYResolution", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa210: add_entry(ifd_type, "FocalPlaneResolutionUnit", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa214: add_entry(ifd_type, "SubjectLocation", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa215: add_entry(ifd_type, "ExposureIndex", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa217: add_entry(ifd_type, "SensingMethod", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa300: add_entry(ifd_type, "FileSource", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa301: add_entry(ifd_type, "SceneType", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa302: add_entry(ifd_type, "CFAPattern", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa401: add_entry(ifd_type, "CustomRendered", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa402: add_entry(ifd_type, "ExposureMode", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa403: add_entry(ifd_type, "WhiteBalance", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa404: add_entry(ifd_type, "DigitalZoomRatio", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa405: add_entry(ifd_type, "FocalLengthIn35mmFilm", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa406: add_entry(ifd_type, "SceneCaptureType", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa407: add_entry(ifd_type, "GainControl", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa408: add_entry(ifd_type, "Contrast", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa409: add_entry(ifd_type, "Saturation", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa40a: add_entry(ifd_type, "Sharpness", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa40b: add_entry(ifd_type, "DeviceSettingDescription", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa40c: add_entry(ifd_type, "SubjectDistanceRange", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa420: add_entry(ifd_type, "ImageUniqueID", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa430: add_entry(ifd_type, "CameraOwnerName", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa431: add_entry(ifd_type, "BodySerialNumber", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa432: add_entry(ifd_type, "LensSpecification", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa433: add_entry(ifd_type, "LensMake", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa434: add_entry(ifd_type, "LensModel", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa435: add_entry(ifd_type, "LensSerialNumber", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa500: add_entry(ifd_type, "Gamma", tiff_handle, ifd_entry_offset, entries); break;
	default:
            add_generic_entry(ifd_type, tiff_handle, ifd_entry_offset, entries);
            break;
        }
        break;
    case IFD0_GPS:
    case IFD1_GPS:
        switch (entry_tag) {
	case 0x0000: add_entry(ifd_type, "GPSVersionID", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0001: add_entry(ifd_type, "GPSLatitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0002: add_entry(ifd_type, "GPSLatitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0003: add_entry(ifd_type, "GPSLongitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0004: add_entry(ifd_type, "GPSLongitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0005: add_entry(ifd_type, "GPSAltitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0006: add_entry(ifd_type, "GPSAltitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0007: add_entry(ifd_type, "GPSTimeStamp", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0008: add_entry(ifd_type, "GPSSatellites", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0009: add_entry(ifd_type, "GPSStatus", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000a: add_entry(ifd_type, "GPSMeasureMode", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000b: add_entry(ifd_type, "GPSDOP", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000c: add_entry(ifd_type, "GPSSpeedRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000d: add_entry(ifd_type, "GPSSpeed", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000e: add_entry(ifd_type, "GPSTrackRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000f: add_entry(ifd_type, "GPSTrack", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0010: add_entry(ifd_type, "GPSImgDirectionRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0011: add_entry(ifd_type, "GPSImgDirection", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0012: add_entry(ifd_type, "GPSMapDatum", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0013: add_entry(ifd_type, "GPSDestLatitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0014: add_entry(ifd_type, "GPSDestLatitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0015: add_entry(ifd_type, "GPSDestLongitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0016: add_entry(ifd_type, "GPSDestLongitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0017: add_entry(ifd_type, "GPSDestBearingRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0018: add_entry(ifd_type, "GPSDestBearing", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0019: add_entry(ifd_type, "GPSDestDistanceRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001a: add_entry(ifd_type, "GPSDestDistance", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001b: add_entry(ifd_type, "GPSProcessingMethod", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001c: add_entry(ifd_type, "GPSAreaInformation", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001d: add_entry(ifd_type, "GPSDateStamp", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001e: add_entry(ifd_type, "GPSDifferential", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001f: add_entry(ifd_type, "GPSHPositioningError", tiff_handle, ifd_entry_offset, entries); break;
	default:
            add_generic_entry(ifd_type, tiff_handle, ifd_entry_offset, entries);
            break;
        }
        break;
    case IFD0_INTEROPERABILITY:
    case IFD1_INTEROPERABILITY:
        switch (entry_tag) {
	case 0x0001: add_entry(ifd_type, "InteroperabilityIndex", tiff_handle, ifd_entry_offset, entries); break;
	default:
            // do nothing by default; the following catch-all was recording huge amounts of redundant data
            //add_generic_entry(ifd_type, tiff_handle, ifd_entry_offset, entries);
            break;
        }
        break;

    default:
        // not a valid type
        cout << "exif_entry.parse_entry invalid entry tag: " << entry_tag << "\n";
        assert(0);
    }
}