From: Dan Fandrich Date: Thu, 15 Oct 2009 06:15:17 +0000 (-0700) Subject: Changed the various functions searching for tags in ExifTagTable[] X-Git-Tag: libexif-0_6_21-release~90 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fec975a7da6284a562b885b4908681661f3c17e4;p=platform%2Fupstream%2Flibexif.git Changed the various functions searching for tags in ExifTagTable[] to use a binary search. This single change increases the speed of a run through the libexif-testsuite by 7% --- diff --git a/ChangeLog b/ChangeLog index d99700f..82a3d15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-14 Dan Fandrich + + * Changed the various functions searching for tags in ExifTagTable[] + to use a binary search. This single change increases the speed of + a run through the libexif-testsuite by 7% + 2009-10-13 Dan Fandrich * po/sv.po: Updated Swedish translation by Daniel Nylander diff --git a/NEWS b/NEWS index 573b8ce..113659d 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,5 @@ libexif-0.6.x: + * Now using a binary search to make searching through the tag table faster libexif-0.6.18 (2009-10-09): diff --git a/libexif/exif-tag.c b/libexif/exif-tag.c index 3f113aa..a78bbf9 100644 --- a/libexif/exif-tag.c +++ b/libexif/exif-tag.c @@ -47,7 +47,7 @@ * The entries MUST be sorted in tag order. * The name and title are mandatory, but the description may be NULL. */ -static const struct { +static const struct TagEntry { /*! Tag ID. There may be duplicate tags when the same number is used for * different meanings in different IFDs. */ ExifTag tag; @@ -877,12 +877,57 @@ exif_tag_table_get_name (unsigned int n) return (n < exif_tag_table_count ()) ? ExifTagTable[n].name : NULL; } +/*! + * Return the number of entries in the EXIF tag table, including the + * terminating NULL entry. + */ unsigned int exif_tag_table_count (void) { return sizeof (ExifTagTable) / sizeof (ExifTagTable[0]); } + +/*! + * Compares the tag with that in entry. + * \param[in] tag pointer to integer tag value + * \param[in] entry pointer to a struct TagEntry + * \return 0 if tags are equal, <0 if tag < entry, >0 if tag > entry + */ +static int +match_tag(const void *tag, const void *entry) +{ + return *(int*)tag - ((struct TagEntry *)entry)->tag; +} + + +/*! + * Finds the first entry in the EXIF tag table with the given tag number + * using a binary search. + * \param[in] tag to find + * \return index into table, or -1 if not found + */ +static int +exif_tag_table_first(ExifTag tag) +{ + int i; + struct TagEntry *entry = bsearch(&tag, ExifTagTable, + exif_tag_table_count()-1, sizeof(struct TagEntry), match_tag); + if (!entry) + return -1; /* Not found */ + + /* Calculate index of found entry */ + i = entry - ExifTagTable; + + /* There may be other entries with the same tag number, so search + * backwards to find the first + */ + while ((i > 0) && (ExifTagTable[i-1].tag == tag)) { + --i; + } + return i; +} + #define RECORDED \ ((ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_CHUNKY] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \ (ExifTagTable[i].esl[ifd][EXIF_DATA_TYPE_UNCOMPRESSED_PLANAR] != EXIF_SUPPORT_LEVEL_NOT_RECORDED) || \ @@ -893,9 +938,14 @@ const char * exif_tag_get_name_in_ifd (ExifTag tag, ExifIfd ifd) { unsigned int i; + int first; - if (ifd >= EXIF_IFD_COUNT) return NULL; - for (i = 0; ExifTagTable[i].name; i++) + if (ifd >= EXIF_IFD_COUNT) + return NULL; + first = exif_tag_table_first(tag); + if (first < 0) + return NULL; + for (i = first; ExifTagTable[i].name; i++) if ((ExifTagTable[i].tag == tag) && RECORDED) break; return ExifTagTable[i].name; } @@ -904,6 +954,7 @@ const char * exif_tag_get_title_in_ifd (ExifTag tag, ExifIfd ifd) { unsigned int i; + int first; /* FIXME: This belongs to somewhere else. */ /* libexif should use the default system locale. @@ -913,8 +964,12 @@ exif_tag_get_title_in_ifd (ExifTag tag, ExifIfd ifd) * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); */ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - if (ifd >= EXIF_IFD_COUNT) return NULL; - for (i = 0; ExifTagTable[i].title; i++) + if (ifd >= EXIF_IFD_COUNT) + return NULL; + first = exif_tag_table_first(tag); + if (first < 0) + return NULL; + for (i = first; ExifTagTable[i].title; i++) if ((ExifTagTable[i].tag == tag) && RECORDED) break; return _(ExifTagTable[i].title); } @@ -923,6 +978,7 @@ const char * exif_tag_get_description_in_ifd (ExifTag tag, ExifIfd ifd) { unsigned int i; + int first; /* libexif should use the default system locale. * If an application specifically requires UTF-8, then we @@ -932,7 +988,11 @@ exif_tag_get_description_in_ifd (ExifTag tag, ExifIfd ifd) */ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - if (ifd >= EXIF_IFD_COUNT) return NULL; + if (ifd >= EXIF_IFD_COUNT) + return NULL; + first = exif_tag_table_first(tag); + if (first < 0) + return NULL; for (i = 0; ExifTagTable[i].description; i++) if ((ExifTagTable[i].tag == tag) && RECORDED) { /* GNU gettext acts strangely when given an empty string */ @@ -987,7 +1047,7 @@ exif_tag_get_title (ExifTag tag) const char * exif_tag_get_description (ExifTag tag) { - return exif_tag_get_stuff (tag, exif_tag_get_description_in_ifd); + return exif_tag_get_stuff(tag, exif_tag_get_description_in_ifd); } @@ -1021,12 +1081,17 @@ static inline ExifSupportLevel get_support_level_in_ifd (ExifTag tag, ExifIfd ifd, ExifDataType t) { unsigned int i; - for (i = 0; ExifTagTable[i].description; i++) { + int first = exif_tag_table_first(tag); + if (first < 0) + return EXIF_SUPPORT_LEVEL_NOT_RECORDED; + for (i = first; ExifTagTable[i].name; i++) { if (ExifTagTable[i].tag == tag) { const ExifSupportLevel supp = ExifTagTable[i].esl[ifd][t]; if (supp != EXIF_SUPPORT_LEVEL_NOT_RECORDED) return supp; /* Try looking for another entry */ + } else { + break; /* We've reached the end of the matching tags */ } } return EXIF_SUPPORT_LEVEL_NOT_RECORDED; @@ -1045,7 +1110,11 @@ static inline ExifSupportLevel get_support_level_any_type (ExifTag tag, ExifIfd ifd) { unsigned int i; - for (i = 0; ExifTagTable[i].description; i++) { + int first = exif_tag_table_first(tag); + if (first < 0) + return EXIF_SUPPORT_LEVEL_UNKNOWN; + + for (i = first; ExifTagTable[i].name; i++) { if (ExifTagTable[i].tag == tag) { /* * Check whether the support level is the same for all possible @@ -1064,6 +1133,8 @@ get_support_level_any_type (ExifTag tag, ExifIfd ifd) return supp; } /* Keep searching the table for another tag for our IFD */ + } else { + break; /* We've reached the end of the matching tags */ } } return EXIF_SUPPORT_LEVEL_UNKNOWN;