src/hg/overlapSelect/coordCols.c 1.4

1.4 2010/01/30 01:14:00 markd
allow specifying location of name when specifying column indices so that -statsOutput is useful
Index: src/hg/overlapSelect/coordCols.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/overlapSelect/coordCols.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -b -B -U 1000000 -r1.3 -r1.4
--- src/hg/overlapSelect/coordCols.c	31 Jul 2009 18:09:23 -0000	1.3
+++ src/hg/overlapSelect/coordCols.c	30 Jan 2010 01:14:00 -0000	1.4
@@ -1,75 +1,86 @@
 /* coordCols - parsing of file by specifying coordinate columns */
 #include "common.h"
 #include "coordCols.h"
 #include "rowReader.h"
 #include "sqlNum.h"
 
 static char const rcsid[] = "$Id$";
 
 static void invalidSpec(char *optName, char* spec)
 /* generate an error, msg can be null */
 {
 errAbort("invalid coord column spec for %s: %s", optName, spec);
 }
 
+static int colIdxOrOmitted(char **words, int numWords, int iWord)
+/* return the column index or -1 if omitted by empty or the end */
+{
+if ((iWord >= numWords) || (strlen(words[iWord]) == 0))
+    return -1;
+else
+    return sqlUnsigned(words[iWord]);
+}
+
 struct coordCols coordColsParseSpec(char *optName, char* spec)
 /* parse coordinate specified in an option. Can be in the form
  *   - chromCol - chrom in this column followed by start and end.
- *   - chromCol,startCol,endCol - chrom, start, and end in specified
- *     columns.
- *   - chromCol,startCol,endCol,strandCol - chrom, start, end, and
- *     strand in specified columns.
+ *   - chromCol,startCol,endCol,strandCol,name - chrom, start, end, and
+ *     strand in specified columns.  With unneeded columns empty or dropped
+ *     from the end.
  */
 {
 char buf[128];
 int numWords;
-char *words[4];
+char *words[6];
 struct coordCols cols;
 ZeroVar(&cols);
 cols.strandCol = -1;
 
 if (strlen(spec) > sizeof(buf)-1)
     invalidSpec(optName, spec);
-strcpy(buf, spec);
-numWords = chopString(buf, ",", words, ArraySize(words));
-switch (numWords) {
-case 1:
+safecpy(buf, sizeof(buf), spec);
+numWords = chopByChar(buf, ',', words, ArraySize(words));
+if (numWords == 1)
+    {
     cols.chromCol = sqlUnsigned(words[0]);
     cols.startCol = cols.chromCol + 1;
     cols.endCol = cols.chromCol + 2;
-    break;
-case 4:
-    cols.strandCol = sqlUnsigned(words[3]);
-case 3:
+    }
+else if (numWords <= 5)
+    {
     cols.chromCol = sqlUnsigned(words[0]);
     cols.startCol = sqlUnsigned(words[1]);
     cols.endCol = sqlUnsigned(words[2]);
-    break;
-default:
+    cols.strandCol = colIdxOrOmitted(words, numWords, 3);
+    cols.nameCol = colIdxOrOmitted(words, numWords, 4);
+    }
+else
     invalidSpec(optName, spec);
-}
-cols.minNumCols = cols.chromCol;
-cols.minNumCols = max(cols.minNumCols, cols.startCol);
-cols.minNumCols = max(cols.minNumCols, cols.endCol);
+// find minimum number of columns
+cols.minNumCols = cols.chromCol+1;
+cols.minNumCols = max(cols.minNumCols, cols.startCol+1);
+cols.minNumCols = max(cols.minNumCols, cols.endCol+1);
 if (cols.strandCol >= 0)
-    cols.minNumCols = max(cols.minNumCols, cols.strandCol);
-cols.minNumCols++;
-
+    cols.minNumCols = max(cols.minNumCols, cols.strandCol+1);
+if (cols.nameCol >= 0)
+    cols.minNumCols = max(cols.minNumCols, cols.nameCol+1);
 return cols;
 }
 
 struct coordColVals coordColParseRow(struct coordCols* cols,
                                      struct rowReader *rr)
-/* parse coords from a row */
+/* parse coords from a row, call coordColsRelease when done with result */
 {
 struct coordColVals colVals;
 ZeroVar(&colVals);
 rowReaderExpectAtLeast(rr, cols->minNumCols);
 colVals.chrom = rr->row[cols->chromCol];
 colVals.start = sqlUnsigned(rr->row[cols->startCol]);
 colVals.end = sqlUnsigned(rr->row[cols->endCol]);
 if (cols->strandCol >= 0)
     colVals.strand = rr->row[cols->strandCol][0];
+if (cols->nameCol >= 0)
+    colVals.name = cloneString(rr->row[cols->nameCol]);
 return colVals;
 }