void writeGap(struct dyString *aRes, int aGap, char *aSeq, struct dyString *bRes, int bGap, char *bSeq) /* Write double - gap. Something like: * ....123.... or --c * ...4123.... ag- */ { char abbrev[16]; int minToAbbreviate = 16; if (doShort && (aGap >= minToAbbreviate || bGap >= minToAbbreviate)) { fillShortGapString(abbrev, aGap, '.', 13); dyStringAppend(aRes, abbrev); fillShortGapString(abbrev, bGap, '.', 13); dyStringAppend(bRes, abbrev); } else { #ifdef OLD dyStringAppendMultiC(aRes, '-', aGap); dyStringAppendN(bRes, bSeq, aGap); dyStringAppendN(aRes, aSeq, bGap); dyStringAppendMultiC(bRes, '-', bGap); #endif /* OLD */ dyStringAppendMultiC(aRes, '-', bGap); dyStringAppendN(bRes, bSeq, bGap); dyStringAppendN(aRes, aSeq, aGap); dyStringAppendMultiC(bRes, '-', aGap); } }
struct dyString * dyStringSub(char *orig, char *in, char *out) /* Make up a duplicate of orig with all occurences of in substituted * with out. */ { int inLen = strlen(in), outLen = strlen(out), origLen = strlen(orig); struct dyString *dy = newDyString(origLen + 2*outLen); char *s, *e; if (orig == NULL) return NULL; for (s = orig; ;) { e = stringIn(in, s); if (e == NULL) { e = orig + origLen; dyStringAppendN(dy, s, e - s); break; } else { dyStringAppendN(dy, s, e - s); dyStringAppendN(dy, out, outLen); s = e + inLen; } } return dy; }
struct dyString *unrepFileName(char *fileName, boolean isSingle) /* Return string with Rep# in fileName replaced with "Merged" */ { char *s = strstr(fileName, "Rep"); struct dyString *dy = dyStringNew(0); if (s == NULL) { if (isSingle) dyStringAppend(dy, fileName); else errAbort("No 'Rep' in fileName %s", fileName); } else { char *pastRep = s + strlen("Rep"); int digitCount = countLeadingDigits(pastRep); if (digitCount < 1) errAbort("No digits after 'Rep' in filename %s", fileName); pastRep += digitCount; dyStringAppendN(dy, fileName, s-fileName); dyStringAppend(dy, "Merged"); int len = strlen(pastRep); if (!isSingle && endsWith(pastRep, ".gz")) len -= strlen(".gz"); dyStringAppendN(dy, pastRep, len); } return dy; }
void correctOne(struct dnaSeq *est, struct psl *psl, char *nibDir, struct hash *nibHash, FILE *f) /* Write one corrected EST to file. */ { struct dnaSeq *geno = readCachedNib(nibHash, nibDir, psl->tName, psl->tStart, psl->tEnd - psl->tStart); struct dyString *t = newDyString(est->size+20); int qSize = psl->qSize; int tSize = psl->tSize; int qLastEnd = 0; int blockIx; struct mrnaBlock *mbList, *mb; int genoOffset = psl->tStart; boolean isRc = FALSE; /* Load sequence and alignment blocks, coping with reverse * strand as necessary. */ toUpperN(geno->dna, geno->size); /* This helps debug... */ mbList = mrnaBlockFromPsl(psl); if (psl->strand[0] == '-') { reverseComplement(geno->dna, geno->size); genoOffset = tSize - psl->tEnd; for (mb = mbList; mb != NULL; mb = mb->next) { reverseIntRange(&mb->tStart, &mb->tEnd, tSize); reverseIntRange(&mb->qStart, &mb->qEnd, qSize); } slReverse(&mbList); isRc = TRUE; } /* Make t have corrected sequence. */ for (mb = mbList; mb != NULL; mb = mb->next) { int qStart = mb->qStart; int qEnd = mb->qEnd; int uncovSize = qStart - qLastEnd; if (uncovSize > 0) dyStringAppendN(t, est->dna + qLastEnd, uncovSize); dyStringAppendN(t, geno->dna + mb->tStart - genoOffset, mb->tEnd - mb->tStart); qLastEnd = qEnd; } if (qLastEnd != qSize) { int uncovSize = qSize - qLastEnd; dyStringAppendN(t, est->dna + qLastEnd, uncovSize); } /* Output */ faWriteNext(f, est->name, t->string, t->stringSize); /* Clean up time. */ slFreeList(&mbList); freeDyString(&t); freeDnaSeq(&geno); }
boolean raNextTagVal(struct lineFile *lf, char **retTag, char **retVal, struct dyString *dyRecord) // Read next line. Return FALSE at end of file or blank line. Otherwise fill in // *retTag and *retVal and return TRUE. If dy parameter is non-null, then the text parsed // gets appended to dy. Continuation lines in RA file will be joined to produce tag and val, // but dy will be filled with the unedited multiple lines containing the continuation chars. // NOTE: retTag & retVal, if returned, point to static mem which will be overwritten on next call! { *retTag = NULL; *retVal = NULL; char *line, *raw = NULL; int lineLen,rawLen; // Don't bother with raw if it isn't used. char **pRaw = NULL; int *pRawLen = NULL; if (dyRecord != NULL) { pRaw = &raw; pRawLen = &rawLen; } while (lineFileNextFull(lf, &line, &lineLen, pRaw, pRawLen)) // Joins continuation lines { char *clippedText = skipLeadingSpaces(line); if (*clippedText == 0) { if (dyRecord) lineFileReuse(lf); // Just so don't loose leading space in dy. return FALSE; } // Append whatever line was read from file. if (dyRecord) { if (raw != NULL) dyStringAppendN(dyRecord, raw, rawLen); else dyStringAppendN(dyRecord, line, lineLen); dyStringAppendC(dyRecord,'\n'); } // Skip comments if (*clippedText == '#') { if (startsWith("#EOF", clippedText)) return FALSE; else continue; } *retTag = nextWord(&line); *retVal = trimSpaces(line); return TRUE; } return FALSE; }
void writeGap(struct dyString *aRes, int aGap, char *aSeq, struct dyString *bRes, int bGap, char *bSeq) /* Write double - gap. Something like: * --c * ag- */ { dyStringAppendMultiC(aRes, '-', bGap); dyStringAppendN(bRes, bSeq, bGap); dyStringAppendN(aRes, aSeq, aGap); dyStringAppendMultiC(bRes, '-', aGap); }
char *vcfGetSlashSepAllelesFromWords(char **words, struct dyString *dy, boolean *retSkippedFirstBase) /* Overwrite dy with a /-separated allele string from VCF words, * skipping the extra initial base that VCF requires for indel alleles if necessary. * Return dy->string for convenience. */ { dyStringClear(dy); // VCF reference allele gets its own column: char *refAllele = words[3]; char *altAlleles = words[4]; // First determine whether there is an extra initial base that we need to skip: boolean allStartSame = TRUE; char *p; while ((p = strchr(altAlleles, ',')) != NULL) { if (altAlleles[0] != refAllele[0]) allStartSame = FALSE; altAlleles = p+1; } if (altAlleles[0] != refAllele[0]) allStartSame = FALSE; int offset = allStartSame ? 1 : 0; if (refAllele[offset] == '\0') dyStringAppendC(dy, '-'); else dyStringAppend(dy, refAllele+offset); // VCF alternate alleles are comma-separated, make them /-separated: altAlleles = words[4]; if (isNotEmpty(altAlleles) && differentString(altAlleles, ".")) { // Now construct the string: while ((p = strchr(altAlleles, ',')) != NULL) { dyStringAppendC(dy, '/'); int len = p - altAlleles - offset; if (len == 0) dyStringAppendC(dy, '-'); else dyStringAppendN(dy, altAlleles+offset, len); altAlleles = p+1; } dyStringAppendC(dy, '/'); int len = strlen(altAlleles) - offset; if (len == 0) dyStringAppendC(dy, '-'); else dyStringAppendN(dy, altAlleles+offset, len); } if (retSkippedFirstBase) *retSkippedFirstBase = offset; return dy->string; }
void xpTextUntil(struct xp *xp, char *endPattern) /* Stuff xp->text with everything up to endPattern. */ { int endSize = strlen(endPattern); int endPos = 0; char c; struct dyString *dy = xp->stack->text; for (;;) { if ((c = xpGetChar(xp)) == 0) xpUnexpectedEof(xp); if (c == endPattern[endPos]) { endPos += 1; if (endPos == endSize) return; } else { if (endPos > 0) dyStringAppendN(dy, endPattern, endPos); dyStringAppendC(dy, c); endPos = 0; } } }
char *replaceRegEx(char *str, char *replace, char *regEx, int flags) { /* Replace text matching regEx in str with replace string. flags is passed through to regcomp as the cflags argument. Returned string should be free'ed after use. */ regex_t re; regmatch_t match[1]; int err = regcomp(&re, regEx, flags); if(err) errAbort("regcomp failed; err: %d", err); struct dyString *dy = newDyString(0); size_t len = strlen(str); size_t offset = 0; while(offset < len && !regexec(&re, str + offset, 1, match, 0)) { dyStringAppendN(dy, str + offset, match[0].rm_so); if(replace != NULL) dyStringAppend(dy, replace); offset += match[0].rm_eo; } if(offset < len) { dyStringAppend(dy, str + offset); } regfree(&re); return dyStringCannibalize(&dy); }
char *menuBarAddUiVars(char *oldString, char *cgiPrefix, char *uiVars) /* Look for CGI program calls in oldString, and add session vars hgsid to them */ { int len = strlen(oldString); char buf[4096]; /* Create a regular expression and compile it */ regex_t re; regmatch_t match[2]; safef(buf, sizeof(buf), "%s[A-Za-z]+(%c%c?)", cgiPrefix, '\\', '?'); int err = regcomp(&re, buf, REG_EXTENDED); if(err) errAbort("regcomp failed; err: %d", err); /* Search through oldString with regex, and build up new string in dy */ struct dyString *dy = newDyString(0); int offset; for(offset = 0; offset < len && !regexec(&re, oldString + offset, ArraySize(match), match, 0); offset += match[0].rm_eo) { dyStringAppendN(dy, oldString + offset, match[0].rm_eo); if(match[1].rm_so == match[1].rm_eo) dyStringAppend(dy, "?"); dyStringAppend(dy, uiVars); if(match[1].rm_so != match[1].rm_eo) dyStringAppend(dy, "&"); } if(offset < len) dyStringAppend(dy, oldString + offset); return dyStringCannibalize(&dy); }
static void appendFirstWord(struct dyString *buf, char *str) /* append the first white-spaced word from str */ { char *end = skipToSpaces(str); if (end == NULL) end = str + strlen(str); dyStringAppendN(buf, str, (end - str)); }
void dyStringAppendEscapedForTabFile(struct dyString *dy, char *string) /* Append string to dy, escaping if need be */ { char c, *s; boolean needsEscape = FALSE; s = string; while ((c = *s++) != 0) { switch (c) { case '\\': case '\t': case '\n': needsEscape = TRUE; } } if (needsEscape) { s = string; while ((c = *s++) != 0) { switch (c) { case '\\': dyStringAppendN(dy, "\\\\", 2); break; case '\t': dyStringAppendN(dy, "\\t", 2); break; case '\n': dyStringAppendN(dy, "\\n", 2); break; default: dyStringAppendC(dy, c); break; } } } else dyStringAppend(dy, string); }
char *lineFileReadAll(struct lineFile *lf) /* Read remainder of lineFile and return it as a string. */ { struct dyString *dy = dyStringNew(1024*4); lf->zTerm = 0; int size; char *line; while (lineFileNext(lf, &line, &size)) dyStringAppendN(dy, line, size); return dyStringCannibalize(&dy); }
void pf_lineIn(_pf_Stack *stack) /* Get next line of input from stdin. In general * you do not want to mix calls to keyIn and lineIn, * since keyIn is unbuffered and lineIn is buffered. * Returns nil at EOF. */ { char buf[256]; int i, c; FILE *f = stdin; for (i=0; i<sizeof(buf)-1; ++i) { c = fgetc(f); if (c < 0) { if (i == 0) stack[0].String = NULL; else { buf[i] = 0; stack[0].String = _pf_string_from_const(buf); } return; } buf[i] = c; if (c == '\n') { buf[i] = 0; stack[0].String = _pf_string_dupe(buf, i); return; } } /* Well, looks like it's a pretty long string! * Let's convert to dyString based capture rather * than using the fixed size buffer on stack. */ { struct dyString *dy = dyStringNew(512); struct _pf_string *string; dyStringAppendN(dy, buf, i); for (;;) { c = fgetc(f); if (c < 0) break; dyStringAppendC(dy, c); if (c == '\n') break; } string = _pf_string_new(dy->string, dy->bufSize); string->size = dy->stringSize; dyStringCannibalize(&dy); stack[0].String = string; } }
char *phyloFindPath(struct phyloTree *tree, char *ref, char *cross) /* find the shortest path from ref to cross (returns a list * of the node names separated by spaces) */ { struct phyloTree *treeRef, *treeCross, *parent; struct dyString *ds = newDyString(0); if ((treeRef = phyloFindName(tree,ref)) == NULL) return NULL; if ((treeCross = phyloFindName(tree,cross)) == NULL) return NULL; phyloClearTreeMarks(tree); phyloMarkUpTree(treeCross); if ((parent = phyloFindMarkUpTree(treeRef)) == NULL) return NULL; /* walk up the tree till we hit the common parent */ while(treeRef != parent) { treeRef = treeRef->parent; if (ds->stringSize) dyStringAppendC(ds, ' '); if (treeRef->ident->name) dyStringAppendN(ds, treeRef->ident->name, strlen(treeRef->ident->name)); } /* now walk down the tree till we come to the target species */ while (parent != treeCross) { parent = parent->mark; dyStringAppendC(ds, ' '); if (parent->ident->name) dyStringAppendN(ds, parent->ident->name, strlen(parent->ident->name)); } return ds->string; }
static boolean matchAndExtractIndexes(char *dottedName, struct tagSchema *schema, struct dyString *scratch, char **retIndexes, boolean *retMatchEnd) /* Dotted name is something like this.that.12.more.2.ok * The objArrayPieces is something like "this.that." ".more." ".notOk" * Crucially it holds at least two elements, some of which may be "" * This function will return TRUE if all but maybe the last of the objArrayPieces is * found in the dottedName. If this is the case it will put something like .12.2 in * scratch and *retIndexes. If the last one matches it will set *retMatchEnd. * Sort of a complex routine but it plays a key piece in checking required array * elements */ { struct slName *objArrayPieces = schema->objArrayPieces; dyStringClear(scratch); struct slName *piece = objArrayPieces; char *pos = dottedName; boolean gotNum = FALSE; for (;;) { /* Check to see if we match next piece, and return FALSE if not */ char *pieceString = piece->name; int pieceLen = strlen(pieceString); if (pieceLen != 0 && memcmp(pieceString, pos, pieceLen) != 0) return FALSE; pos += pieceLen; /* Put the number into scratch with a leading dot separator. */ int digits = tagSchemaDigitsUpToDot(pos); if (digits == 0) return FALSE; dyStringAppendC(scratch, '.'); dyStringAppendN(scratch, pos, digits); pos += digits; gotNum = TRUE; /* Go to next piece,saving last piece for outside of the loop. */ piece = piece->next; if (piece->next == NULL) break; } /* One more special case, where last piece needs to agree on emptiness at least in * terms of matching */ if (isEmpty(piece->name) != isEmpty(pos)) return FALSE; /* Otherwise both have something. We return true/false depending on whether it matches */ *retMatchEnd = (strcmp(piece->name, pos) == 0); *retIndexes = scratch->string; return gotNum; }
static void nodeNames(struct phyloTree *tree, struct dyString *ds) /* recursive workhorse to add all the node names to a string */ { int ii; if (tree->ident->name) { dyStringAppendN(ds, tree->ident->name, strlen(tree->ident->name)); dyStringAppendC(ds, ' '); } for (ii=0; ii < tree->numEdges; ii++) nodeNames(tree->edges[ii],ds); }
boolean getWormGeneExonDna(char *name, DNA **retDna) /* Get the DNA associated with a gene, without introns. */ { struct gdfGene *g; struct slName *syn = NULL; long lstart, lend; int start, end; int dnaSize; DNA *dna; int i; struct gdfDataPoint *pt = NULL; struct wormGdfCache *gdfCache; struct dyString *dy = newDyString(1000); /* Translate biologist type name to cosmid.N name */ if (wormIsGeneName(name)) { syn = wormGeneToOrfNames(name); if (syn != NULL) name = syn->name; } if (strncmp(name, "g-", 2) == 0) gdfCache = &wormGenieGdfCache; else gdfCache = &wormSangerGdfCache; if ((g = wormGetSomeGdfGene(name, gdfCache)) == NULL) return FALSE; gdfGeneExtents(g, &lstart, &lend); start = lstart; end = lend; /*wormClipRangeToChrom(chromIds[g->chromIx], &start, &end);*/ dnaSize = end-start; dna = wormChromPart(chromIds[g->chromIx], start, dnaSize); gdfOffsetGene(g, -start); if (g->strand == '-') { reverseComplement(dna, dnaSize); gdfRcGene(g, dnaSize); } pt = g->dataPoints; for (i=0; i<g->dataCount; i += 2) { dyStringAppendN(dy, (dna+pt[i].start), (pt[i+1].start - pt[i].start)); } *retDna = cloneString(dy->string); dyStringFree(&dy); gdfFreeGene(g); return TRUE; }
void ultraPcrRegions(char *database, char *bedFile, char *outFa) /* ultraPcrRegions - Get regions to PCR up and some surrounding sequence. */ { int extraSize = 1000; FILE *f = mustOpen(outFa, "w"); struct bed *bed, *bedList = bedLoadNAll(bedFile, 4); hSetDb(database); for (bed = bedList; bed != NULL; bed = bed->next) { int bedSize = bed->chromEnd - bed->chromStart; int chromSize = hChromSize(bed->chrom); int seqSize; int seqStart = bed->chromStart - extraSize; int seqEnd = bed->chromEnd + extraSize; int firstParenPos, secondParenPos; struct dyString *dy; char fileName[512]; struct dnaSeq *seq; if (seqStart < 0) seqStart = 0; if (seqEnd > chromSize) seqEnd = chromSize; seqSize = seqEnd - seqStart; firstParenPos = bed->chromStart - seqStart; secondParenPos = firstParenPos + bedSize; seq = hChromSeqMixed(bed->chrom, seqStart, seqEnd); dy = dyStringNew(seqSize+2); dyStringAppendN(dy, seq->dna, firstParenPos); dyStringAppendC(dy, '('); dyStringAppendN(dy, seq->dna+firstParenPos, secondParenPos-firstParenPos); dyStringAppendC(dy, ')'); dyStringAppendN(dy, seq->dna+secondParenPos, seqSize - secondParenPos); faWriteNext(f, bed->name, dy->string, dy->stringSize); } carefulClose(&f); }
static void fillInMissing(struct oneOrg *nativeOrg, struct oneOrg *orgList, struct dnaSeq *native, int seqStart, int curPos, int aliStart) /* Fill in alignment strings in orgList with native sequence * for first organism, and dots for rest. */ { int fillSize = aliStart - curPos; int offset = curPos - seqStart; struct oneOrg *org; if (nativeOrg == NULL) return; dyStringAppendN(nativeOrg->dy, native->dna + offset, fillSize); for (org = orgList; org != NULL; org = org->next) { if (org != nativeOrg) dyStringAppendMultiC(org->dy, '.', fillSize); } }
static void appendMimeVar(struct dyString *dy, char *name, char *value, char *varType, char *boundary) /* Append cgiVar with cgi-encoded value to dy. */ { char *fileName = NULL; if (value == NULL) value = ""; dyStringAppend(dy, "\r\n--"); dyStringAppend(dy, boundary); dyStringAppend(dy, "\r\n"); dyStringAppend(dy, "content-disposition: form-data; name=\""); dyStringAppend(dy, name); dyStringAppend(dy, "\""); if (varType && sameWord(varType, "FILE")) { fileName = strrchr(value,'/'); if (fileName) ++fileName; else fileName = value; dyStringAppend(dy, "; filename=\""); dyStringAppend(dy, fileName); dyStringAppend(dy, "\""); } dyStringAppend(dy, "\r\n"); dyStringAppend(dy, "\r\n"); if (varType && sameWord(varType, "FILE") && !sameWord(value,"")) { FILE *f = mustOpen(value, "r"); char buf[MIMEBUFSIZE]; int bytesRead = 0; do { bytesRead = fread(buf,1,MIMEBUFSIZE,f); if (bytesRead < 0) errnoAbort("error reading file to upload %s",value); dyStringAppendN(dy, buf, bytesRead); } while(bytesRead > 0); carefulClose(&f); } else dyStringAppend(dy, value); }
void writeInsert(struct dyString *aRes, struct dyString *bRes, char *aSeq, int gapSize) /* Write out gap, possibly shortened, to aRes, bRes. */ { int minToAbbreviate = 16; if (doShort && gapSize >= minToAbbreviate) { char abbrevGap[16]; char abbrevSeq[16]; fillSpliceSites(abbrevSeq, gapSize, aSeq, 15); dyStringAppend(aRes, abbrevSeq); fillShortGapString(abbrevGap, gapSize, '-', 15); dyStringAppend(bRes, abbrevGap); } else { dyStringAppendN(aRes, aSeq, gapSize); dyStringAppendMultiC(bRes, '-', gapSize); } }
static char *getQName(char *qName) /* get query name, optionally dropping trailing unique identifier. * WARNING: static return */ { static struct dyString *buf = NULL; if (ignoreQUniq) { if (buf == NULL) buf = dyStringNew(2*strlen(qName)); dyStringClear(buf); char *dash = strrchr(qName, '-'); if (dash == NULL) return qName; dyStringAppendN(buf, qName, (dash-qName)); return buf->string; } else return qName; }
static char *subThroughHash(struct lineFile *lf, struct hash *hash, struct dyString *dy, char *s) /* Return string that has any variables in string-valued hash looked up. * The result is put in the passed in dyString, and also returned. */ { char *tok; int size; dyStringClear(dy); while (nextSubTok(lf, &s, &tok, &size)) { if (tok[0] == '$') { char tokBuf[256], *val; /* Extract 'var' out of '$var' or '${var}' into tokBuf*/ tok += 1; size -= 1; if (tok[0] == '{') { tok += 1; size -= 2; } if (size >= sizeof(tokBuf)) errAbort("Variable name too long line %d of %s", lf->lineIx, lf->fileName); memcpy(tokBuf, tok, size); tokBuf[size] = 0; /* Do substitution. */ val = hashFindVal(hash, tokBuf); if (val == NULL) errAbort("$%s not defined line %d of %s", tokBuf, lf->lineIx, lf->fileName); dyStringAppend(dy, val); } else { dyStringAppendN(dy, tok, size); } } return dy->string; }
static char *readHtmlRecursive(char *fileName, char *database) /* Slurp in an html file. Wherever it contains insertHtmlRegex, recursively slurp that in * and replace insertHtmlRegex with the contents. */ { char *html; readInGulp(fileName, &html, NULL); if (isEmpty(html)) return html; regmatch_t substrs[4]; while (regexMatchSubstr(html, insertHtmlRegex, substrs, ArraySize(substrs))) { struct dyString *dy = dyStringNew(0); // All text before the regex match: dyStringAppendN(dy, html, substrs[0].rm_so); // Is there an #if before the #insert ? boolean doInsert = TRUE; if (substrs[1].rm_so != -1 && (! sameStringN(database, html+substrs[2].rm_so, (substrs[2].rm_eo - substrs[2].rm_so)))) doInsert = FALSE; if (doInsert) { // Recursively pull in inserted file contents from relative path, replacing regex match: char dir[PATH_LEN]; splitPath(fileName, dir, NULL, NULL); char insertFileName[PATH_LEN+FILENAME_LEN]; safecpy(insertFileName, sizeof(insertFileName), dir); safencat(insertFileName, sizeof(insertFileName), html+substrs[3].rm_so, (substrs[3].rm_eo - substrs[3].rm_so)); if (!fileExists(insertFileName)) errAbort("readHtmlRecursive: relative path '%s' (#insert'ed in %s) not found", insertFileName, fileName); char *insertedText = readHtmlRecursive(insertFileName, database); dyStringAppend(dy, insertedText); freez(&insertedText); } // All text after the regex match: dyStringAppend(dy, html+substrs[0].rm_eo); freez(&html); html = dyStringCannibalize(&dy); } return html; }
static void abbreviateLongSeq(char *seqIn, int endLength, boolean showLength, struct dyString *dy) /* If seqIn is longer than 2*endLength plus abbreviation fudge, abbreviate it * to its first endLength bases, ellipsis that says how many bases are skipped, * and its last endLength bases; add result to dy. */ { int threshold = 2*endLength + 30; int seqInLen = strlen(seqIn); if (seqInLen > threshold) { dyStringAppendN(dy, seqIn, endLength); dyStringAppend(dy, "..."); if (showLength) { int skippedLen = seqInLen-2*endLength; dyStringPrintf(dy, "<%d bases>...", skippedLen); } dyStringAppend(dy, seqIn+seqInLen-endLength); } else dyStringAppend(dy, seqIn); }
static char *limitText(char *text) /* read text string and limit to 1000 actual data lines */ { struct dyString *limitedText = dyStringNew(0); /* yes, opening with FALSE so as not to destroy the original string */ struct lineFile *lf = lineFileOnString("limitText", FALSE, text); char *lineStart = NULL; int lineLength = 0; int legitimateLineCount = 0; while (legitimateLineCount < 1000 && lineFileNext(lf, &lineStart, &lineLength)) { char *s, c; s = skipLeadingSpaces(lineStart); c = s[0]; if (c != 0 && c != '#') ++legitimateLineCount; dyStringAppendN(limitedText, lineStart, lineLength); } if ((legitimateLineCount == 1000) && lineFileNext(lf, &lineStart, &lineLength)) warn("WARNING: defined regions limit of 1000 definitions reached at line %d<BR>\n", lf->lineIx-1); lineFileClose(&lf); return (dyStringCannibalize(&limitedText)); }
static void joinerExpand(struct joiner *joiner) /* Expand joiners that have [] in them. */ { struct joinerSet *js, *nextJs, *newJs, *newList = NULL; for (js=joiner->jsList; js != NULL; js = nextJs) { char *startBracket, *endBracket; nextJs = js->next; if ((startBracket = strchr(js->name, '[')) != NULL) { char *dbStart,*dbEnd; char *dbCommaList; struct joinerField *jf, *newJf; struct dyString *dy = dyStringNew(0); endBracket = strchr(startBracket, ']'); if (endBracket == NULL) errAbort("[ without ] line %d of %s", js->lineIx, joiner->fileName); dbCommaList = cloneStringZ(startBracket+1, endBracket - startBracket - 1); dbStart = dbCommaList; while (dbStart != NULL) { /* Parse out comma-separated list. */ dbEnd = strchr(dbStart, ','); if (dbEnd != NULL) { *dbEnd++ = 0; if (dbEnd[0] == 0) dbEnd = NULL; } if (dbStart[0] == 0) errAbort("Empty element in comma separated list line %d of %s", js->lineIx, joiner->fileName); /* Make up name for new joiner. */ dyStringClear(dy); dyStringAppendN(dy, js->name, startBracket-js->name); dyStringAppend(dy, dbStart); dyStringAppend(dy, endBracket+1); /* Allocate new joiner and fill in most data elements. */ AllocVar(newJs); newJs->name = cloneString(dy->string); newJs->typeOf = cloneString(js->typeOf); newJs->external = cloneString(js->external); newJs->description = cloneString(js->description); newJs->isFuzzy = js->isFuzzy; newJs->lineIx = js->lineIx; newJs->isDependency = js->isDependency; /* Fill in new joiner fieldList */ for (jf = js->fieldList; jf != NULL; jf = jf->next) { char *bs = NULL, *be = NULL; /* Allocate vars and do basic fields. */ AllocVar(newJf); newJf->dbList = slNameCloneList(jf->dbList); newJf->field = cloneString(jf->field); newJf->chopBefore = slNameCloneList(jf->chopBefore); newJf->chopAfter = slNameCloneList(jf->chopBefore); newJf->separator = cloneString(jf->separator); newJf->indexOf = jf->indexOf; newJf->isPrimary = jf->isPrimary; newJf->unique = jf->unique; newJf->full = jf->full; newJf->minCheck = jf->minCheck; newJf->splitPrefix = cloneString(jf->splitPrefix); newJf->exclude = slNameCloneList(jf->exclude); /* Do substituted table field. */ if ((bs = strchr(jf->table, '[')) != NULL) be = strchr(bs, ']'); if (bs == NULL || be == NULL) errAbort("Missing [] in field '%s' line %d of %s", jf->table, jf->lineIx, joiner->fileName); dyStringClear(dy); dyStringAppendN(dy, jf->table, bs - jf->table); dyStringAppend(dy, dbStart); dyStringAppend(dy, be+1); newJf->table = cloneString(dy->string); slAddHead(&newJs->fieldList, newJf); } newJs->expanded = TRUE; slReverse(&newJs->fieldList); slAddHead(&newList, newJs); dbStart = dbEnd; } dyStringFree(&dy); freez(&dbCommaList); joinerSetFree(&js); } else { slAddHead(&newList, js); } } slReverse(&newList); joiner->jsList = newList; }
void testDbFilters(struct htmlPage *dbPage, char *org, char *db, char *accColumn, struct slName *geneList) /* Test filter that returns just geneList. */ { struct slName *gene; int rowCount; char accFilter[256]; /* Start out with filter page. */ struct htmlPage *page = quickSubmit(dbPage, NULL, org, db, accColumn, NULL, "accOneFilterPage", advFilterVarName, "on"); verbose(1, "testFilters %s %s\n", org, db); if (page == NULL) return; /* Set up to filter exactly one gene. */ safef(accFilter, sizeof(accFilter), "near.as.%s.wild", accColumn); { htmlPageSetVar(page, NULL, accFilter, geneList->name); htmlPageSetVar(page, NULL, searchVarName, geneList->name); serialSubmit(&page, NULL, org, db, accColumn, geneList->name, "accOneFilterSubmit", "Submit", "on"); if (page == NULL) return; /* Make sure really got one gene. */ rowCount = nearCountUniqAccRows(page); if (rowCount != 1) { qaStatusSoftError(nearTestList->status, "Acc exact filter returned %d items", rowCount); } } /* Set up filter for all genes in list. */ { struct dyString *dy = newDyString(0); int geneCount = slCount(geneList); for (gene = geneList; gene != NULL; gene = gene->next) dyStringPrintf(dy, "%s ", gene->name); htmlPageSetVar(page, NULL, accFilter, dy->string); htmlPageSetVar(page, NULL, countVarName, "all"); /* despite 3 genes requested, must see all if many dupes */ serialSubmit(&page, NULL, org, db, accColumn, dy->string, "accMultiFilterSubmit", "Submit", "on"); dyStringFree(&dy); if (page == NULL) return; rowCount = nearCountUniqAccRows(page); if (rowCount != geneCount) { qaStatusSoftError(nearTestList->status, "Acc multi filter expecting %d, got %d items", geneCount, rowCount); } } /* Set up filter for wildcard in list. */ { struct dyString *dy = newDyString(0); char len = strlen(geneList->name); dyStringAppendN(dy, geneList->name, len-1); dyStringAppendC(dy, '*'); htmlPageSetVar(page, NULL, accFilter, dy->string); serialSubmit(&page, NULL, org, db, accColumn, dy->string, "accWildFilterSubmit", "Submit", "on"); dyStringFree(&dy); if (page == NULL) return; rowCount = nearCountRows(page); if (rowCount < 1) { qaStatusSoftError(nearTestList->status, "Acc wild filter no match"); } } /* Clear out advanced filters. */ { htmlPageFree(&page); page = quickSubmit(dbPage, NULL, org, db, NULL, NULL, "advFilterClear", advFilterClearVarName, "on"); } htmlPageFree(&page); }
void dyStringAppend(struct dyString *ds, char *string) /* Append zero terminated string to end of dyString. */ { dyStringAppendN(ds, string, strlen(string)); }