fcd12f2b541d84822d13fb7b939c463248647f1f tdreszer Fri Apr 15 17:42:16 2011 -0700 Add simple support for reading lines with continuation characters as single lines. diff --git src/lib/linefile.c src/lib/linefile.c index 083ddb2..b8ea9a6 100644 --- src/lib/linefile.c +++ src/lib/linefile.c @@ -668,47 +668,125 @@ void lineFileExpectAtLeast(struct lineFile *lf, int expecting, int got) /* Check line has right number of words. */ { if (got < expecting) errAbort("Expecting at least %d words line %d of %s got %d", expecting, lf->lineIx, lf->fileName, got); } void lineFileShort(struct lineFile *lf) /* Complain that line is too short. */ { errAbort("Short line %d of %s", lf->lineIx, lf->fileName); } +void lineFileReuseFull(struct lineFile *lf) +// Reuse last full line read. Unlike lineFileReuse, +// lineFileReuseFull only works with previous lineFileNextFull call +{ +assert(lf->fullLine != NULL); +lf->fullLineResuse = TRUE; +} + + +boolean lineFileNextFull(struct lineFile *lf, char **retStart, int *retSize) +// Fetch next line from file joining up any that are continued by ending '\' +// NOTE: comment lines can't be continued! ("# comment \ \n more comment" is 2 lines.) +{ +// May have requested reusing the last full line. +if (lf->fullLineResuse) + { + assert(lf->fullLine != NULL); + lf->fullLineResuse = FALSE; + *retStart = dyStringContents(lf->fullLine); + if (retSize) + *retSize = dyStringLen(lf->fullLine); + return TRUE; + } + +*retStart = NULL; + +// Initialize memory if needed +if (lf->fullLine == NULL) + lf->fullLine = dyStringNew(1024); +dyStringClear(lf->fullLine); + +char *line; +while (lineFileNext(lf, &line, NULL)) + { + char *clippedText = skipLeadingSpaces(line); + + // Fill lf memory in case of continued lines + if (dyStringLen(lf->fullLine) == 0) + { + dyStringAppend(lf->fullLine,line); // includes first line's whitespace. + *retStart = dyStringContents(lf->fullLine); + } + else if (clippedText[0] != '\0') + dyStringAppend(lf->fullLine,clippedText); // don't include continued line's leading spaces + + // Will the next line continue this one? + if (clippedText[0] != '\0' && clippedText[0] != '#') // Comment lines can't be continued! + { + line = dyStringContents(lf->fullLine); + char *lastChar = lastNonWhitespaceChar(line); + if (lastChar != NULL && *lastChar == '\\') + { + if (lastChar > line && *(lastChar - 1) != '\\') // Not an escaped continuation char + { + dyStringResize(lf->fullLine,(lastChar - line)); // This clips off the last char and any trailing white-space in dyString + continue; + } + } + } + if (retSize) + *retSize = dyStringLen(lf->fullLine); + return TRUE; + } +return FALSE; +} + boolean lineFileNextReal(struct lineFile *lf, char **retStart) /* Fetch next line from file that is not blank and * does not start with a '#'. */ { char *s, c; while (lineFileNext(lf, retStart, NULL)) { s = skipLeadingSpaces(*retStart); c = s[0]; if (c != 0 && c != '#') - { return TRUE; } +return FALSE; +} + +boolean lineFileNextFullReal(struct lineFile *lf, char **retStart) +// Fetch next line from file that is not blank and does not start with a '#'. +// Continuation lines (ending in '\') are joined into a single line. +{ +while (lineFileNextFull(lf, retStart, NULL)) + { + char *clippedText = skipLeadingSpaces(*retStart); + if (clippedText[0] != '\0' && clippedText[0] != '#') + return TRUE; } return FALSE; } + int lineFileChopNext(struct lineFile *lf, char *words[], int maxWords) /* Return next non-blank line that doesn't start with '#' chopped into words. */ { int lineSize, wordCount; char *line; while (lineFileNext(lf, &line, &lineSize)) { if (line[0] == '#') continue; wordCount = chopByWhite(line, words, maxWords); if (wordCount != 0) return wordCount; } return 0;