be4311c07e14feb728abc6425ee606ffaa611a58 markd Fri Jan 22 06:46:58 2021 -0800 merge with master diff --git src/lib/obscure.c src/lib/obscure.c index f6bea35..5bb41cd 100644 --- src/lib/obscure.c +++ src/lib/obscure.c @@ -156,30 +156,71 @@ struct lineFile *lf = lineFileOpen(fileName, TRUE); struct hash *hash = hashNew(16); char *row[3]; int fields = 0; while ((fields = lineFileChop(lf, row)) != 0) { lineFileExpectWords(lf, 2, fields); char *name = row[0]; char *value = lmCloneString(hash->lm, row[1]); hashAdd(hash, name, value); } lineFileClose(&lf); return hash; } +struct hash *hashTsvBy(char *in, int keyColIx, int *retColCount) +/* Return a hash of rows keyed by the given column */ +{ +struct lineFile *lf = lineFileOpen(in, TRUE); +struct hash *hash = hashNew(0); +char *line = NULL, **row = NULL; +int colCount = 0, colAlloc=0; /* Columns as counted and as allocated */ +while (lineFileNextReal(lf, &line)) + { + if (colCount == 0) + { + *retColCount = colCount = chopByChar(line, '\t', NULL, 0); + verbose(2, "Got %d columns in first real line\n", colCount); + colAlloc = colCount + 1; // +1 so we can detect unexpected input and complain + lmAllocArray(hash->lm, row, colAlloc); + } + int count = chopByChar(line, '\t', row, colAlloc); + if (count != colCount) + { + errAbort("Expecting %d words, got more than that line %d of %s", + colCount, lf->lineIx, lf->fileName); + } + hashAdd(hash, row[keyColIx], lmCloneRow(hash->lm, row, colCount) ); + } +lineFileClose(&lf); +return hash; +} + +void writeTsvRow(FILE *f, int rowSize, char **row) +/* Write out row of strings to a line in tab-sep file */ +{ +if (rowSize > 0) + { + fprintf(f, "%s", row[0]); + int i; + for (i=1; i<rowSize; ++i) + fprintf(f, "\t%s", row[i]); + } +fprintf(f, "\n"); +} + struct slPair *slPairTwoColumnFile(char *fileName) /* Read in a two column file into an slPair list */ { char *row[2]; struct slPair *list = NULL; struct lineFile *lf = lineFileOpen(fileName, TRUE); while (lineFileRow(lf, row)) slPairAdd(&list, row[0], cloneString(row[1])); lineFileClose(&lf); slReverse(&list); return list; } struct slName *readAllLines(char *fileName) /* Read all lines of file into a list. (Removes trailing carriage return.) */