summaryrefslogtreecommitdiff
path: root/ext/exif
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-10-09 15:39:03 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-10-18 16:54:56 +0200
commit56e3e6f13562609f854fe8ddcd0cf65514456f4b (patch)
tree6a9e08bb2e89009db2e6de7ef966930c4e7b1cbd /ext/exif
parente5324a2484ec0782a76daca7dd5e1a5ac232b3d8 (diff)
downloadphp-git-56e3e6f13562609f854fe8ddcd0cf65514456f4b.tar.gz
Implement a cache for exif tag name lookups
Diffstat (limited to 'ext/exif')
-rw-r--r--ext/exif/exif.c67
1 files changed, 54 insertions, 13 deletions
diff --git a/ext/exif/exif.c b/ext/exif/exif.c
index 8152b69830..02c1524dec 100644
--- a/ext/exif/exif.c
+++ b/ext/exif/exif.c
@@ -132,6 +132,7 @@ ZEND_BEGIN_MODULE_GLOBALS(exif)
char * encode_jis;
char * decode_jis_be;
char * decode_jis_le;
+ HashTable *tag_table_cache;
ZEND_END_MODULE_GLOBALS(exif)
ZEND_DECLARE_MODULE_GLOBALS(exif)
@@ -197,6 +198,7 @@ static PHP_GINIT_FUNCTION(exif)
exif_globals->encode_jis = NULL;
exif_globals->decode_jis_be = NULL;
exif_globals->decode_jis_le = NULL;
+ exif_globals->tag_table_cache = NULL;
}
/* }}} */
@@ -219,6 +221,10 @@ PHP_MINIT_FUNCTION(exif)
PHP_MSHUTDOWN_FUNCTION(exif)
{
UNREGISTER_INI_ENTRIES();
+ if (EXIF_G(tag_table_cache)) {
+ zend_hash_destroy(EXIF_G(tag_table_cache));
+ free(EXIF_G(tag_table_cache));
+ }
return SUCCESS;
}
/* }}} */
@@ -721,7 +727,6 @@ static tag_info_array tag_table_IFD = {
{ 0x8773, "ICC_Profile"},
{ 0x8822, "ExposureProgram"},
{ 0x8824, "SpectralSensity"},
- { 0x8828, "OECF"},
{ 0x8825, "GPS_IFD_Pointer"},
{ 0x8827, "ISOSpeedRatings"},
{ 0x8828, "OECF"},
@@ -1350,25 +1355,61 @@ static const maker_note_type maker_note_array[] = {
};
/* }}} */
+static HashTable *exif_make_tag_ht(tag_info_type *tag_table)
+{
+ HashTable *ht = malloc(sizeof(HashTable));
+ zend_hash_init(ht, 0, NULL, NULL, 1);
+ while (tag_table->Tag != TAG_END_OF_LIST) {
+ if (!zend_hash_index_add_ptr(ht, tag_table->Tag, tag_table->Desc)) {
+ zend_error(E_CORE_ERROR, "Duplicate tag %x", tag_table->Tag);
+ }
+ tag_table++;
+ }
+ return ht;
+}
+
+static void exif_tag_ht_dtor(zval *zv)
+{
+ HashTable *ht = Z_PTR_P(zv);
+ zend_hash_destroy(ht);
+ free(ht);
+}
+
+static HashTable *exif_get_tag_ht(tag_info_type *tag_table)
+{
+ HashTable *ht;
+
+ if (!EXIF_G(tag_table_cache)) {
+ EXIF_G(tag_table_cache) = malloc(sizeof(HashTable));
+ zend_hash_init(EXIF_G(tag_table_cache), 0, NULL, exif_tag_ht_dtor, 1);
+ }
+
+ ht = zend_hash_index_find_ptr(EXIF_G(tag_table_cache), (uintptr_t) tag_table);
+ if (ht) {
+ return ht;
+ }
+
+ ht = exif_make_tag_ht(tag_table);
+ zend_hash_index_add_new_ptr(EXIF_G(tag_table_cache), (uintptr_t) tag_table, ht);
+ return ht;
+}
+
/* {{{ exif_get_tagname
Get headername for tag_num or NULL if not defined */
static char * exif_get_tagname(int tag_num, char *ret, int len, tag_table_type tag_table)
{
- int i, t;
char tmp[32];
-
- for (i = 0; (t = tag_table[i].Tag) != TAG_END_OF_LIST; i++) {
- if (t == tag_num) {
- if (ret && len) {
- strlcpy(ret, tag_table[i].Desc, abs(len));
- if (len < 0) {
- memset(ret + strlen(ret), ' ', -len - strlen(ret) - 1);
- ret[-len - 1] = '\0';
- }
- return ret;
+ char *desc = zend_hash_index_find_ptr(exif_get_tag_ht(tag_table), tag_num);
+ if (desc) {
+ if (ret && len) {
+ strlcpy(ret, desc, abs(len));
+ if (len < 0) {
+ memset(ret + strlen(ret), ' ', -len - strlen(ret) - 1);
+ ret[-len - 1] = '\0';
}
- return tag_table[i].Desc;
+ return ret;
}
+ return desc;
}
if (ret && len) {