05563be2e445f57aaadc21dd3a843db0ff8faee6
kent
  Tue Mar 26 21:52:43 2013 -0700
Adding several new functions to meta library.
diff --git src/hg/lib/meta.c src/hg/lib/meta.c
index a30fb9b..70e4c18 100644
--- src/hg/lib/meta.c
+++ src/hg/lib/meta.c
@@ -7,30 +7,55 @@
  *         target H3K4Me3
  *         antibody abCamAntiH3k4me3
  *       
  *            meta lowLevel
  *            fileName hg19/chipSeq/helaH3k4me3.narrowPeak.bigBed
  * The file is interpreted so that lower level stanzas inherit tags from higher level ones.
  */
 
 #include "common.h"
 #include "linefile.h"
 #include "hash.h"
 #include "errabort.h"
 #include "meta.h"
 #include "ra.h"
 
+struct metaTagVal *metaTagValNew(char *tag, char *val)
+/* Create new meta tag/val */
+{
+struct metaTagVal *mtv;
+AllocVar(mtv);
+mtv->tag = cloneString(tag);
+mtv->val = cloneString(val);
+return mtv;
+}
+
+int metaTagValCmp(const void *va, const void *vb)
+/* Compare to sort based on tag name . */
+{
+const struct metaTagVal *a = *((struct metaTagVal **)va);
+const struct metaTagVal *b = *((struct metaTagVal **)vb);
+return strcmp(a->tag, b->tag);
+}
+
+void metaSortTags(struct meta *meta)
+/* Do canonical sort so that the first tag stays first but the
+ * rest are alphabetical. */
+{
+slSort(&meta->tagList->next, metaTagValCmp);
+}
+
 int countLeadingSpacesDetabbing(char *s, int tabStop)
 /* Count up leading chars including those implied by tab. Set tabStop to 8
  * for usual UNIX results. */
 {
 int count = 0;
 char c;
 while ((c = *s++) != 0)
     {
     if (c == ' ')
         ++count;
     else if (c == '\t')
         {
 	int tabBefore = (count % tabStop) * tabStop;
 	count = (tabBefore+1)*tabStop;
 	}
@@ -262,30 +287,49 @@
 
 char *metaTagVal(struct meta *meta, char *name)
 /* Return value of tag found in this node or if its not there in parents.
  * Returns NULL if tag not found. */
 {
 struct meta *m;
 for (m = meta; m != NULL; m = m->parent)
     {
     char *val = metaLocalTagVal(m, name);
     if (val != NULL)
        return val;
     }
 return NULL;
 }
 
+void metaAddTag(struct meta *meta, char *tag, char *val)
+/* Add tag to meta, replacing existing tag if any */
+{
+/* First loop through to replace an existing tag. */
+struct metaTagVal *mtv;
+for (mtv = meta->tagList; mtv != NULL; mtv = mtv->next)
+    {
+    if (sameString(mtv->tag, tag))
+       {
+       freeMem(mtv->val);
+       mtv->val = cloneString(val);
+       return;
+       }
+    }
+/* If didn't make it then add new tag (at end) */
+mtv = metaTagValNew(tag, val);
+slAddTail(&meta->tagList, mtv);
+}
+
 static void rHashMetaList(struct hash *hash, struct meta *list)
 /* Add list, and any children of list to hash */
 {
 struct meta *meta;
 for (meta = list; meta != NULL; meta = meta->next)
     {
     hashAddUnique(hash, meta->name, meta);
     if (meta->children)
         rHashMetaList(hash, meta->children);
     }
 }
 
 struct hash *metaHash(struct meta *forest)
 /* Return hash of meta at all levels of heirarchy keyed by forest. */
 {