shithub: opusfile

Download patch

ref: 046b089dfd1995bd97825c11d12a9755a039f931
parent: 0e4b81e15f2ccb8cf437f055e50d1a989237d3ec
author: Timothy B. Terriberry <tterribe@xiph.org>
date: Sat Aug 24 08:05:38 EDT 2013

Expose tag comparison functions.

It seems somewhat silly to have to write your own strcasecmp to
 satisfy the usage pattern found in opusfile_example: scanning the
 whole tags list and handling certain tags specially (as opposed to
 searching for specific tags, as opus_tags_query() does).
Given that we were already using an equivalent function internally
 to implement opus_tags_query, just expose it directly.

--- a/examples/opusfile_example.c
+++ b/examples/opusfile_example.c
@@ -93,24 +93,6 @@
   else fprintf(_fp,"%li%s%c",(long)val,_spacer,SUFFIXES[shift]);
 }
 
-/*A version of strncasecmp() that is guaranteed to only ignore the case of
-   ASCII characters.*/
-static int local_strncasecmp(const char *_a,const char *_b,int _n){
-  int i;
-  for(i=0;i<_n;i++){
-    int a;
-    int b;
-    int d;
-    a=_a[i];
-    b=_b[i];
-    if(a>='a'&&a<='z')a-='a'-'A';
-    if(b>='a'&&b<='z')b-='a'-'A';
-    d=a-b;
-    if(d)return d;
-  }
-  return 0;
-}
-
 static void put_le32(unsigned char *_dst,opus_uint32 _x){
   _dst[0]=(unsigned char)(_x&0xFF);
   _dst[1]=(unsigned char)(_x>>8&0xFF);
@@ -304,7 +286,7 @@
         for(ci=0;ci<tags->comments;ci++){
           const char *comment;
           comment=tags->user_comments[ci];
-          if(local_strncasecmp(comment,"METADATA_BLOCK_PICTURE=",23)==0){
+          if(opus_tagncompare("METADATA_BLOCK_PICTURE",22,comment)==0){
             OpusPictureTag pic;
             int            err;
             err=opus_picture_tag_parse(&pic,comment);
--- a/include/opusfile.h
+++ b/include/opusfile.h
@@ -547,6 +547,32 @@
    \param _tags The #OpusTags structure to clear.*/
 void opus_tags_clear(OpusTags *_tags) OP_ARG_NONNULL(1);
 
+/**Check if \a _comment is an instance of a \a _tag_name tag.
+   \see opus_tagncompare
+   \param _tag_name A NUL-terminated, case-insensitive, ASCII string containing
+                     the name of the tag to check for (without the terminating
+                     '=' character).
+   \param _comment  The comment string to check.
+   \return An integer less than, equal to, or greater than zero if \a _comment
+            is found respectively, to be less than, to match, or be greater
+            than a "tag=value" string whose tag matches \a _tag_name.*/
+int opus_tagcompare(const char *_tag_name,const char *_comment);
+
+/**Check if \a _comment is an instance of a \a _tag_name tag.
+   This version is slightly more efficient than opus_tagcompare() if the length
+    of the tag name is already known (e.g., because it is a constant).
+   \see opus_tagcompare
+   \param _tag_name A case-insensitive ASCII string containing the name of the
+                     tag to check for (without the terminating '=' character).
+   \param _tag_len  The number of characters in the tag name.
+                    This must be non-negative.
+   \param _comment  The comment string to check.
+   \return An integer less than, equal to, or greater than zero if \a _comment
+            is found respectively, to be less than, to match, or be greater
+            than a "tag=value" string whose tag matches the first \a _tag_len
+            characters of \a _tag_name.*/
+int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment);
+
 /**Parse a single METADATA_BLOCK_PICTURE tag.
    This decodes the BASE64-encoded content of the tag and returns a structure
     with the MIME type, description, image parameters (if known), and the
--- a/src/info.c
+++ b/src/info.c
@@ -251,12 +251,17 @@
   return 0;
 }
 
-/*Is _a a "tag=value" comment whose tag matches _b?
-  0 if it is, a non-zero value otherwise.*/
-static int op_tagcompare(const char *_a,const char *_b,int _n){
-  return op_strncasecmp(_a,_b,_n)||_a[_n]!='=';
+int opus_tagcompare(const char *_tag_name,const char *_comment){
+  return opus_tagncompare(_tag_name,strlen(_tag_name),_comment);
 }
 
+int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){
+  int ret;
+  OP_ASSERT(_tag_len>=0);
+  ret=op_strncasecmp(_tag_name,_comment,_tag_len);
+  return ret?ret:'='-_comment[_tag_len];
+}
+
 const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){
   char **user_comments;
   int    tag_len;
@@ -268,7 +273,7 @@
   user_comments=_tags->user_comments;
   found=0;
   for(ci=0;ci<ncomments;ci++){
-    if(!op_tagcompare(user_comments[ci],_tag,tag_len)){
+    if(!opus_tagncompare(_tag,tag_len,user_comments[ci])){
       /*We return a pointer to the data, not a copy.*/
       if(_count==found++)return user_comments[ci]+tag_len+1;
     }
@@ -288,7 +293,7 @@
   user_comments=_tags->user_comments;
   found=0;
   for(ci=0;ci<ncomments;ci++){
-    if(!op_tagcompare(user_comments[ci],_tag,tag_len))found++;
+    if(!opus_tagncompare(_tag,tag_len,user_comments[ci]))found++;
   }
   return found;
 }