1f36dac15fb404318112d4c3271d4b14eba70223
kent
  Mon May 24 17:35:05 2021 -0700
Making library tolerate extra lines that start with % in matrix market.

diff --git src/lib/matrixMarket.c src/lib/matrixMarket.c
index cced410..9f6ba3a 100644
--- src/lib/matrixMarket.c
+++ src/lib/matrixMarket.c
@@ -1,130 +1,141 @@
 #include "common.h"
 #include "linefile.h"
 #include "obscure.h"
 #include "sqlNum.h"
 #include "matrixMarket.h"
 
 void matrixMarketJustNumberCoordinates(struct matrixMarket *mm, char *fileName)
 /* Make sure that the matrix is of the type we can handle */
 {
 if (differentWord(mm->format, "coordinate"))
     errAbort("%s is not a MatrixMarket matrix in coordinate format", fileName);
 if (differentWord(mm->type, "integer") && differentWord(mm->type, "real"))
     errAbort("%s has numbers in %s format, can only handle real and integer",
 	fileName, mm->type);
 if (differentWord(mm->symmetries, "general"))
     errAbort("%s has %s symmetries, can only handle general symmetries", 
         fileName, mm->symmetries);
 }
 
 struct matrixMarket *matrixMarketOpen(char *fileName)
 /* Open a matrixMarket file and read header, return a handle for use in more routines. */
 {
 struct lineFile *lf = lineFileOpen(fileName, TRUE);
 char *row[6];	// Big enough for header
 int rowSize;
 
 /* Get header line, check for errors */
 rowSize = lineFileChopNext(lf, row, ArraySize(row));
 lineFileExpectWords(lf, 5, rowSize);
 if (differentString(row[0], "%%MatrixMarket"))
    errAbort("%s is not a MatrixMarket file", fileName);
 if (differentWord(row[1], "matrix"))
     errAbort("%s is not a MatrixMarket matrix", fileName);
 
+/* Skip over other lines that start with % */
+char *line;
+while (lineFileNext(lf, &line, NULL))
+    {
+    if (line[0] != '%')
+        {
+	lineFileReuse(lf);
+	break;
+	}
+    }
+
 /* Allocate our return object and fill in what we can from the header line */
 struct matrixMarket *mm;
 AllocVar(mm);
 mm->lf = lf;
 mm->format = cloneString(row[2]);
 mm->type = cloneString(row[3]);
 mm->symmetries = cloneString(row[4]);
 
 /* Precalculate a shortcut or two */
 mm->isInt = sameWord(mm->type, "integer");
 
 /* Get the dimensions line and save it in our data structure */
 rowSize = lineFileChopNext(lf, row, ArraySize(row));
 lineFileExpectWords(lf, 3, rowSize);
 mm->colCount = lineFileNeedNum(lf, row, 0);
 mm->rowCount = lineFileNeedNum(lf, row, 1);
 mm->valCount = lineFileNeedNum(lf, row, 2);
 if (mm->colCount <= 0 || mm->rowCount <= 0)
     errAbort("%d x %d matrix in %s, dimensions must be positive)", mm->colCount, mm->rowCount, fileName);
 
 return mm;
 }
 
 void matrixMarketClose(struct matrixMarket **pMm)
 /* Close down matrix market and free up associated resources */
 {
 struct matrixMarket *mm = *pMm;
 if (mm != NULL)
     {
     lineFileClose(&mm->lf);
     freeMem(mm->format);
     freeMem(mm->type);
     freeMem(mm->symmetries);
     freeMem(mm->row);
     freez(pMm);
     }
 }
 
 
 boolean matrixMarketNext(struct matrixMarket *mm)
 /* Fetch next value from matrix market, returning FALSE if at end of file */
 {
 char *row[4];
 struct lineFile *lf = mm->lf;
 int rowSize = lineFileChopNext(lf, row, ArraySize(row));
 if (rowSize <= 0)
     return FALSE;
 lineFileExpectWords(lf, 3, rowSize);
 mm->x = sqlUnsigned(row[0]) - 1;
 if (mm->x >= mm->colCount)
     errAbort("X coordinate %d too big, %d max, line %d of %s", mm->x+1, mm->colCount, 
 	lf->lineIx, lf->fileName);
 mm->y = sqlUnsigned(row[1]) - 1;
 if (mm->y >= mm->rowCount)
     errAbort("Y coordinate %d too big, %d max, line %d of %s", mm->y+1, mm->rowCount, 
 	lf->lineIx, lf->fileName);
 char *val = row[2];
 mm->val = (mm->isInt ? sqlSigned(val) : sqlDouble(val));
 return TRUE;
 }
 
 boolean matrixMarketNextRow(struct matrixMarket *mm)
 /* Fetch next row into mm->row, return FALSE at eof.  Beware this may skip rows
  * so look at mm->rowIx as well */
 {
 if (mm->lastRow)
     return FALSE;
 if (mm->row == NULL)
     {
     if (!matrixMarketNext(mm))   /* We always start one into the row - this catches empty matrix*/
         return FALSE;
     mm->rowIx = mm->y;
     AllocArray(mm->row, mm->colCount);
     }
 zeroBytes(mm->row, mm->colCount * sizeof(mm->row[0]));
 mm->rowIx = mm->y;
 mm->row[mm->x] = mm->val;
 for (;;)
     {
     if (!matrixMarketNext(mm))
         {
 	mm->lastRow = TRUE;
 	break;
 	}
     if (mm->y != mm->rowIx)
         {
 	if (mm->y < mm->rowIx)
 	    errAbort("%s is not a sorted-by-y matrix-market on line %d", mm->lf->fileName, 
 		mm->lf->lineIx);
 	break;
 	}
     mm->row[mm->x] = mm->val;
     }
 return TRUE;
 }