static struct bed4 *parseRegionInput(char *db, char *inputString, int maxRegions, int maxErrs, struct dyString *dyWarn) /* scan the user region definition, turn into a bed list */ { int regionCount = 0; int errCount = 0; struct bed4 *bedList = NULL; struct lineFile *lf = lineFileOnString("userData", TRUE, inputString); char *line = NULL; while (lineFileNextReal(lf, &line)) { char *chromName = NULL; int chromStart = 0; int chromEnd = 0; char *regionName = NULL; // Chop a copy of line so we can display line if there's an error. char copy[strlen(line)+1]; safecpy(copy, sizeof(copy), line); char *words[5]; int wordCount = chopByWhite(copy, words, ArraySize(words)); boolean badFormat = FALSE; boolean gotError = FALSE; /* might be something of the form: chrom:start-end optionalRegionName */ if (((1 == wordCount) || (2 == wordCount)) && hgParseChromRange(NULL, words[0], &chromName, &chromStart, &chromEnd)) { if (2 == wordCount) regionName = cloneString(words[1]); } else if (!((3 == wordCount) || (4 == wordCount))) { dyStringPrintf(dyWarn, "line %d: '%s': " "unrecognized format. Please enter 3- or 4-column BED or " "a chr:start-end position range optionally followed by a name.\n", lf->lineIx, line); badFormat = TRUE; gotError = TRUE; } else { chromName = words[0]; // Make sure chromStart and chromEnd are numbers if (!isNumericString(words[1])) { dyStringPrintf(dyWarn, "line %d: '%s': chromStart must be a number but is '%s'\n", lf->lineIx, line, words[1]); gotError = TRUE; } if (!isNumericString(words[2])) { dyStringPrintf(dyWarn, "line %d: '%s': chromEnd must be a number but is '%s'\n", lf->lineIx, line, words[2]); gotError = TRUE; } if (! gotError) { chromStart = atoi(words[1]); chromEnd = atoi(words[2]); if (wordCount > 3) regionName = cloneString(words[3]); } } char *officialChromName = chromName ? hgOfficialChromName(db, chromName) : NULL; if (! badFormat) { if (NULL == officialChromName) { dyStringPrintf(dyWarn, "line %d: '%s': chrom name '%s' not recognized in this assembly\n", lf->lineIx, line, chromName ? chromName : words[0]); gotError = TRUE; } else if (illegalCoordinate(db, officialChromName, chromStart, chromEnd, line, lf->lineIx, dyWarn)) { gotError = TRUE; } } if (gotError) { errCount++; if (errCount > maxErrs && maxErrs > 0) { dyStringPrintf(dyWarn, "Exceeded maximum number of errors (%d), quitting\n", maxErrs); break; } else continue; } ++regionCount; if (regionCount > maxRegions && maxRegions > 0) { dyStringPrintf(dyWarn, "line %d: limit of %d region definitions exceeded, skipping the rest\n", lf->lineIx, maxRegions); break; } struct bed4 *bedEl = bed4New(officialChromName, chromStart, chromEnd, regionName); slAddHead(&bedList, bedEl); } lineFileClose(&lf); // Keep regions in same order as user entered them: slReverse(&bedList); return (bedList); }
static struct bed *parseRegionInput(char *inputString) /* scan the user region definition, turn into a bed list */ { int itemCount = 0; struct bed *bedList = NULL; struct bed *bedEl; int wordCount; char *words[5]; struct lineFile *lf; lf = lineFileOnString("userData", TRUE, inputString); while (0 != (wordCount = lineFileChopNext(lf, words, ArraySize(words)))) { char *chromName = NULL; int chromStart = 0; int chromEnd = 0; char *regionName = NULL; /* might be something of the form: chrom:start-end optionalRegionName */ if (((1 == wordCount) || (2 == wordCount)) && hgParseChromRange(NULL, words[0], &chromName, &chromStart, &chromEnd)) { if (2 == wordCount) regionName = cloneString(words[1]); } else if (!((3 == wordCount) || (4 == wordCount))) { int i; struct dyString *errMessage = dyStringNew(0); for (i = 0; i < wordCount; ++i) dyStringPrintf(errMessage, "%s ", words[i]); errAbort("line %d: '%s'<BR>\n" "illegal bed size, expected 3 or 4 fields, found %d\n", lf->lineIx, dyStringCannibalize(&errMessage), wordCount); } else { chromName = hgOfficialChromName(database, words[0]); chromStart = sqlSigned(words[1]); chromEnd = sqlSigned(words[2]); if (wordCount > 3) regionName = cloneString(words[3]); } ++itemCount; if (itemCount > 1000) { warn("limit 1000 region definitions reached at line %d<BR>\n", lf->lineIx); break; } AllocVar(bedEl); bedEl->chrom = chromName; if (NULL == bedEl->chrom) errAbort("at line %d, chrom name '%s' %s %s not recognized in this assembly %d", lf->lineIx, words[0], words[1], words[2], wordCount); bedEl->chromStart = chromStart; bedEl->chromEnd = chromEnd; if (illegalCoordinate(bedEl->chrom, bedEl->chromStart, bedEl->chromEnd)) errAbort("illegal input at line %d: %s %d %d", lf->lineIx, bedEl->chrom, bedEl->chromStart, bedEl->chromEnd); if (wordCount > 3) bedEl->name = regionName; else bedEl->name = NULL; /* if we wanted to give artifical names to each item */ #ifdef NOT { char name[128]; safef(name, ArraySize(name), "item_%04d", itemCount); bedEl->name = cloneString(name); } #endif slAddHead(&bedList, bedEl); } lineFileClose(&lf); // slSort(&bedList, bedCmp); /* this would do chrom,chromStart order */ slReverse(&bedList); /* with no sort, it is in order as user entered */ return (bedList); }