struct hash *loadModuleToMotif(struct sqlConnection *conn, char *fileName, char *table) /* Load up file which has a line per module. The first word is the module * number, the rest of the tab-separated fields are motif names. * Return hash keyed by module&motif. */ { struct lineFile *lf = lineFileOpen(fileName, TRUE); char *line, *module, *motif; FILE *f = hgCreateTabFile(tmpDir, table); struct dyString *dy = dyStringNew(512); int motifCount = 0, moduleCount = 0; struct hash *hash = newHash(18); while (lineFileNextReal(lf, &line)) { ++moduleCount; subChar(line, ' ', '_'); module = nextWord(&line); while ((motif = nextWord(&line)) != NULL) { ++motifCount; fprintf(f, "%s\t%s\n", module, motif); hashAdd2(hash, module, motif, NULL); } } sqlDyStringPrintf(dy, "CREATE TABLE %s (\n" " module int not null,\n" " motif varchar(255) not null,\n" " #Indices\n" " INDEX(module),\n" " INDEX(motif(16))\n" ")\n", table); sqlRemakeTable(conn, table, dy->string); verbose(1, "%d modules, %d motifs in modules\n", moduleCount, motifCount); hgLoadTabFile(conn, tmpDir, table, &f); hgRemoveTabFile(tmpDir, table); verbose(1, "Loaded %s table\n", table); lineFileClose(&lf); return hash; }
struct hash *readBed(char *fileName) /* Read bed and return it as a hash keyed by chromName * with binKeeper values. */ { char *row[5]; struct lineFile *lf = lineFileOpen(fileName, TRUE); struct hash *hash = newHash(0); int expectedCols = bScore ? 5 : 3; while (lineFileNextRow(lf, row, expectedCols)) { struct binKeeper *bk; struct bed5 *bed; struct hashEl *hel = hashLookup(hash, row[0]); if (hel == NULL) { bk = binKeeperNew(0, 1024*1024*1024); hel = hashAdd(hash, row[0], bk); } bk = hel->val; AllocVar(bed); bed->chrom = hel->name; bed->start = lineFileNeedNum(lf, row, 1); bed->end = lineFileNeedNum(lf, row, 2); if (bScore) bed->score = lineFileNeedNum(lf, row, 4); if (bed->start > bed->end) errAbort("start after end line %d of %s", lf->lineIx, lf->fileName); if (bed->start == bed->end) { if (allowStartEqualEnd) // Note we are tweaking binKeeper coords here, so use bed->start and bed->end. binKeeperAdd(bk, max(0, bed->start-1), bed->end+1, bed); else lineFileAbort(lf, "start==end (if this is legit, use -allowStartEqualEnd)"); } else binKeeperAdd(bk, bed->start, bed->end, bed); } lineFileClose(&lf); return hash; }
struct liftSpec *readLifts(char *fileName) /* Read in lift file. */ { struct lineFile *lf = lineFileOpen(fileName, TRUE); int wordCount; char *words[16]; struct liftSpec *list = NULL, *el; while ((wordCount = lineFileChop(lf, words)) != 0) { char *offs; if (wordCount < 5) errAbort("Need at least 5 words line %d of %s", lf->lineIx, lf->fileName); offs = words[0]; if (!isdigit(offs[0]) && !(offs[0] == '-' && isdigit(offs[1]))) errAbort("Expecting number in first field line %d of %s", lf->lineIx, lf->fileName); if (!isdigit(words[4][0])) errAbort("Expecting number in fifth field line %d of %s", lf->lineIx, lf->fileName); AllocVar(el); el->offset = atol(offs); el->oldName = cloneString(words[1]); el->oldSize = atoi(words[2]); el->newName = cloneString(words[3]); el->newSize = atoi(words[4]); if (wordCount >= 6) { char c = words[5][0]; if (c == '+' || c == '-') el->strand = c; else errAbort("Expecting + or - field 6, line %d of %s", lf->lineIx, lf->fileName); } else el->strand = '+'; slAddHead(&list, el); } slReverse(&list); lineFileClose(&lf); if (list == NULL) errAbort("Empty liftSpec file %s", fileName); return list; }
struct tomRough *loadAllRough(char *fileName) /* Load up all bands from database. */ { struct tomRough *list = NULL, *el; struct lineFile *lf = lineFileOpen(fileName, TRUE); char *words[16], *line; int wordCount, lineSize; while (lineFileNext(lf, &line, &lineSize)) { wordCount = chopCommas(line, words); lineFileExpectWords(lf, 5, wordCount); el = tomRoughLoad(words); slAddHead(&list, el); } slReverse(&list); lineFileClose(&lf); printf("Loaded %d rough lines\n", slCount(list)); return list; }
struct hash *hashNmerFile(char *file) { struct lineFile *lf = lineFileOpen(file, TRUE); struct hash *nmerHash = newHash(15); struct nmerAlign *nmerList = NULL, *nmer; char key[256]; char *words[6]; while(lineFileNextRowTab(lf, words, 6)) { nmer = parseNmerAlignRow(words); snprintf(key, sizeof(key), "%s-%s", nmer->seq, nmer->name); nmerList = hashFindVal(nmerHash, key); if(nmerList == NULL) hashAddUnique(nmerHash, key, nmer); else slAddTail(&nmerList, nmer); } lineFileClose(&lf); return nmerHash; }
static struct visiMatch *readMatchFile(char *fileName) /* Read in match file */ { struct visiMatch *matchList = NULL, *match; struct lineFile *lf = lineFileMayOpen(fileName, TRUE); if (lf != NULL) { char *row[2]; while (lineFileRow(lf, row)) { AllocVar(match); match->imageId = lineFileNeedNum(lf, row, 0); match->weight = lineFileNeedDouble(lf, row, 1); slAddHead(&matchList, match); } lineFileClose(&lf); slReverse(&matchList); } return matchList; }
struct hash *makeStageHash(char *fileName) /* Return hash with keys that are stage names (st12 and the like) * and values are ascii strings describing age in days. * The input is two columns - stage name, and age in hours. */ { struct lineFile *lf = lineFileOpen(fileName, TRUE); char *row[2]; struct hash *hash = hashNew(0); while (lineFileRow(lf, row)) { char *stage = row[0]; double hours = atof(row[1]); char days[16]; safef(days, sizeof(days), "%f", hours/24); hashAdd(hash, stage, cloneString(days)); } lineFileClose(&lf); return hash; }
void addGlBin(char *in, char *out) /* Copy in to out, but adding bin field in first column. */ { char *row[4]; int i, start, end; struct lineFile *lf = lineFileOpen(in, TRUE); FILE *f = mustOpen(out, "w"); while (lineFileRow(lf, row)) { start = sqlUnsigned(row[1]); end = sqlUnsigned(row[2]); fprintf(f, "%u", hFindBin(start, end)); for (i=0; i<ArraySize(row); ++i) fprintf(f, "\t%s", row[i]); fprintf(f, "\n"); } carefulClose(&f); lineFileClose(&lf); }
struct hash *netToBkHash(char *netFile) /* Read net file into a hash full of binKeepers keyed by chromosome. * The binKeepers are full of nets. */ { struct hash *netHash = hashNew(0); struct lineFile *lf = lineFileOpen(netFile, TRUE); struct chainNet *net, *netList = chainNetRead(lf); for (net = netList; net != NULL; net = net->next) { if (hashLookup(netHash, net->name)) errAbort("%s has multiple %s records", netFile, net->name); struct binKeeper *bk = binKeeperNew(0, net->size); hashAdd(netHash, net->name, bk); struct cnFill *fill; for(fill=net->fillList; fill != NULL; fill = fill->next) binKeeperAdd(bk, fill->tStart, fill->tStart+fill->tSize, fill); } lineFileClose(&lf); return netHash; }
struct hash *getFreqHash(char *freqFile) /* Read the frequency file in, and store it in a hash and return that. */ { struct hash *freqHash = newHash(23); struct lineFile *lf = lineFileOpen(freqFile, TRUE); char *words[3]; /* Assume there's a header and skip it. */ lineFileSkip(lf, 1); while (lineFileRowTab(lf, words)) { int val; lineFileNeedFullNum(lf, words, 1); lineFileNeedFullNum(lf, words, 2); val = (int)sqlUnsigned(words[2]); addFreqToHash(freqHash, words[0], words[1], val); } lineFileClose(&lf); hashTraverseEls(freqHash, sortSlPairList); return freqHash; }
void catUncomment(int inCount, char *inNames[]) /* catUncomment - Concatenate input removing lines that start with '#'. */ { struct lineFile *lf; char *fileName; char *line; int i, lineSize; for (i=0; i<inCount; ++i) { fileName = inNames[i]; lf = lineFileOpen(fileName, FALSE); while (lineFileNext(lf, &line, &lineSize)) { if (line[0] != '#') mustWrite(stdout, line, lineSize); } lineFileClose(&lf); } }
struct replicate *readRaAsReplicates(char *fileName) /* Read RA file and return it as a list of replicates. */ { struct lineFile *lf = lineFileOpen(fileName, TRUE); struct replicate *rep, *repList = NULL; struct slPair *tagList; while ((tagList = raNextRecordAsSlPairList(lf)) != NULL) { AllocVar(rep); rep->fileName = mustFindInPairList(tagList, "fileName", lf); rep->replicate = mustFindInPairList(tagList, "replicate", lf); rep->tagList = tagList; slAddHead(&repList, rep); } slReverse(&repList); lineFileClose(&lf); return repList; }
struct binKeeper *readRepeats2(char *chrom, char *rmskFileName, struct hash *tSizeHash) /* read all repeats for a chromosome of size size, returns results in binKeeper structure for fast query*/ { boolean rmskRet; struct lineFile *rmskF = NULL; struct rmskOut2 *rmsk; struct binKeeper *bk; int size; size = hashIntVal(tSizeHash, chrom); bk = binKeeperNew(0, size); assert(size > 1); rmskOut2OpenVerify(rmskFileName ,&rmskF , &rmskRet); while ((rmsk = rmskOut2ReadNext(rmskF)) != NULL) { binKeeperAdd(bk, rmsk->genoStart, rmsk->genoEnd, rmsk); } lineFileClose(&rmskF); return bk; }
void fixEnsGtf(char *outName, int inCount, char *inFiles[]) /* fixEnsGtf - fix space vs. tab and start/stop codon problems in Ensemble .gtf file. */ { FILE *f = mustOpen(outName, "w"); struct lineFile *lf; int fileIx; int lineSize; char *line; for (fileIx = 0; fileIx < inCount; ++fileIx) { lf = lineFileOpen(inFiles[fileIx], TRUE); printf("Processing %s\n", lf->fileName); while (lineFileNext(lf, &line, &lineSize)) { fixLine(lf, line, f); } lineFileClose(&lf); } }
void addPhaseInfo(char *gsDir) /* Add in phase to clones from sequence.inf file. */ { char fileName[512]; struct lineFile *lf; char *words[8]; struct clone *clone; char *cloneName; sprintf(fileName, "%s/sequence.inf", gsDir); printf("Scanning %s for phase info\n", fileName); lf = lineFileOpen(fileName, TRUE); while (lineFileRow(lf, words)) { cloneName = words[0]; chopSuffix(cloneName); if ((clone = hashFindVal(cloneHash, cloneName)) == NULL) { if (!sameString(words[3], "0")) warn("%s is in %s but not .finf files", cloneName, fileName); continue; } clone->phase = atoi(words[3]); if (clone->phase <= 0 || clone->phase > 3) { warn("Bad phase %s line %d of %s", words[3], lf->lineIx, lf->fileName); continue; } if (clone->phase == 3) { if (!clone->isFin) warn("Clone %s is finished in sequence.inf but not in finished.finf", cloneName); } else { if (clone->isFin) warn("Clone %s is in finished.fin but is phase %s in sequence.inf", cloneName, words[3]); } } lineFileClose(&lf); }
void chainSplit(char *outDir, int inCount, char *inFiles[]) /* chainSplit - Split chains up by target or query sequence. */ { struct hash *hash = newHash(0); int inIx; char tpath[512]; FILE *meta ; bool metaOpen = TRUE; makeDir(outDir); safef(tpath, sizeof(tpath), "%s/meta.tmp", outDir); meta = mustOpen(tpath,"w"); for (inIx = 0; inIx < inCount; ++inIx) { struct lineFile *lf = lineFileOpen(inFiles[inIx], TRUE); struct chain *chain; FILE *f; lineFileSetMetaDataOutput(lf, meta); while ((chain = chainRead(lf)) != NULL) { char *name = (splitOnQ ? chain->qName : chain->tName); if (lump > 0) name = lumpName(name); if ((f = hashFindVal(hash, name)) == NULL) { char path[512], cmd[512]; safef(path, sizeof(path),"%s/%s.chain", outDir, name); if (metaOpen) fclose(meta); metaOpen = FALSE; safef(cmd,sizeof(cmd), "cat %s | sort -u > %s", tpath, path); mustSystem(cmd); f = mustOpen(path, "a"); hashAdd(hash, name, f); } chainWrite(chain, f); chainFree(&chain); } lineFileClose(&lf); } }
void tempLower(char *inName, char *insertsFile, char *outName) /* tempLower - Remove centromeres etc. from oo.18 cytobands. */ { struct lineFile *lf = lineFileOpen(inName, TRUE); FILE *f = mustOpen(outName, "w"); int wordCount, i; int start, end, offset; char *chrom; char *words[128]; int count = 0, liftCount = 0; struct chromGaps *cg; setupHugeGaps(insertsFile); while ((wordCount = lineFileChop(lf, words)) != 0) { chrom = words[0]; start = atoi(words[1]); end = atoi(words[2]); cg = hashFindVal(hugeHash, chrom); if (cg != NULL) { offset = gapOffset(cg, start); if (offset != 0) { start += offset; end += offset; liftCount += 1; } } fprintf(f, "%s\t%d\t%d", chrom, start, end); for (i=3; i<wordCount; ++i) fprintf(f, "\t%s", words[i]); fprintf(f, "\n"); ++count; } printf("Lifted %d of %d lines of %s to %s\n", liftCount, count, inName, outName); fclose(f); lineFileClose(&lf); }
void trackOverlap(char *database, char *chrom, char *homologyTrack, char *specFile) /* trackOverlap - Correlate a track with a series of tracks specified in specFile. */ { struct lineFile *lf = NULL; char *line = NULL; struct sqlConnection *conn; int chromSize; Bits *h**o = NULL; Bits *bits = NULL; Bits *once = NULL; lf = lineFileOpen(specFile, TRUE); conn = hAllocConn(database); chromSize = hChromSize(database, chrom); h**o = bitAlloc(chromSize); bits = bitAlloc(chromSize); once = bitAlloc(chromSize); /* Get homology bitmap and set once mask to be the same. */ fbOrTableBits(database, h**o, homologyTrack, chrom, chromSize, conn); bitOr(once, h**o, chromSize); /* printHeader */ printf("%-21s %8s %8s %5s %6s %6s %5s %5s \n", "Track Specification", "track", "overlap", "track", "cov", "track", "new", "cum"); printf("%-21s %8s %8s %5s %6s %6s %5s %5s \n", "", "size", "size", "geno", "track", "cov", "cov", "cov"); printf("-----------------------------------------------------------------------------\n"); /* Whittle awway at homology... */ explainSome(database, h**o, once, bits, chrom, chromSize, conn, NULL, homologyTrack); while(lineFileNextReal(lf, &line)) { explainSome(database, h**o, once, bits, chrom, chromSize, conn, line, NULL); } lineFileClose(&lf); hFreeConn(&conn); }
struct bed6* readBed6SoftAndSize(char* file, int* orig_size) /* read from a file. If it's missing fields, fill the bed */ { char* words[6]; if (!fileExists(file)) errAbort("Can't find file: %s", file); struct lineFile* lf = lineFileOpen(file, TRUE); struct bed6* list = NULL; int num_words = 0; int size = 0; while ((num_words = lineFileChopTab(lf, words)) > 0) { if (num_words < 3) errAbort("Expecting BED-3 formatted file (%s) but there are only %d columns on line %d", file, num_words, lf->lineIx); struct bed6* newb; AllocVar(newb); if (size < num_words) size = num_words; newb->chrom = cloneString(words[0]); newb->chromStart = sqlSigned(words[1]); newb->chromEnd = sqlSigned(words[2]); if (num_words < 4) newb->name = cloneString("."); else newb->name = cloneString(words[3]); if (num_words < 5) newb->score = 0; else newb->score = sqlSigned(words[4]); if (num_words < 6) newb->strand[0] = '+'; else newb->strand[0] = words[5][0]; newb->strand[1] = '\0'; slAddHead(&list, newb); } slReverse(&list); lineFileClose(&lf); if (orig_size) *orig_size = size; return list; }
void axtDropOverlap(char *inName, char *tSizeFile, char *qSizeFile, char *outName) /* used for cleaning up self alignments - deletes all overlapping self alignments */ { struct hash *qSizeHash = readSizes(qSizeFile); struct lineFile *lf = lineFileOpen(inName, TRUE); FILE *f = mustOpen(outName, "w"); struct axt *axt; int totMatch = 0; int totSkip = 0; int totLines = 0; while ((axt = axtRead(lf)) != NULL) { totLines++; totMatch += axt->score; if (sameString(axt->qName, axt->tName)) { int qs = axt->qStart; int qe = axt->qEnd; if (axt->qStrand == '-') reverseIntRange(&qs, &qe, findSize(qSizeHash, axt->qName)); if (axt->tStart == qs && axt->tEnd == qe) { /* printf( "skip %c\t%s\t%d\t%d\t%d\t%s\t%d\t%d\t%d\n", axt->qStrand, axt->qName, axt->symCount, axt->qStart, axt->qEnd, axt->tName, axt->symCount, axt->tStart, axt->tEnd ); */ totSkip++; continue; } } axtWrite(axt, f); axtFree(&axt); } fclose(f); lineFileClose(&lf); }
struct clone *readTrans(char *fileName) /* Read info in trans file. */ { char cloneName[128], lastCloneName[128]; struct clone *cloneList = NULL, *clone = NULL; struct frag *frag; struct lineFile *lf = lineFileOpen(fileName, TRUE); char *words[8], *parts[4], *subParts[3]; int wordCount, partCount, subCount; strcpy(lastCloneName, ""); while ((wordCount = lineFileChop(lf, words)) != 0) { lineFileExpectWords(lf, 3, wordCount); partCount = chopString(words[2], "(:)", parts, ArraySize(parts)); if (partCount != 2) errAbort("Badly formatted third field line %d of %s", lf->lineIx, lf->fileName); subCount = chopString(parts[1], ".", subParts, ArraySize(subParts)); if (subCount != 2) errAbort("Badly formatted third field line %d of %s (expecting start..end)", lf->lineIx, lf->fileName); fragToCloneName(words[0], cloneName); if (!sameString(cloneName, lastCloneName)) { AllocVar(clone); clone->name = cloneString(cloneName); slAddHead(&cloneList, clone); } AllocVar(frag); frag->name = cloneString(words[0]); frag->ffaName = cloneString(words[1]); frag->start = lineFileNeedNum(lf, subParts, 0) - 1; frag->end = lineFileNeedNum(lf, subParts, 1); slAddTail(&clone->fragList, frag); strcpy(lastCloneName, cloneName); } lineFileClose(&lf); slReverse(&cloneList); return cloneList; }
struct vcfFile *vcfFileMayOpen(char *fileOrUrl, int maxErr, int maxRecords, boolean parseAll) /* Open fileOrUrl and parse VCF header; return NULL if unable. * If parseAll, then read in all lines, parse and store in * vcff->records; if maxErr >= zero, then continue to parse until * there are maxErr+1 errors. A maxErr less than zero does not stop * and reports all errors. Set maxErr to VCF_IGNORE_ERRS for silence */ { struct lineFile *lf = NULL; if (startsWith("http://", fileOrUrl) || startsWith("ftp://", fileOrUrl) || startsWith("https://", fileOrUrl)) lf = netLineFileOpen(fileOrUrl); else lf = lineFileMayOpen(fileOrUrl, TRUE); struct vcfFile *vcff = vcfFileHeaderFromLineFile(lf, maxErr); if (parseAll) { vcff->records = vcfParseData(vcff, maxRecords); lineFileClose(&(vcff->lf)); // Not sure why it is closed. Angie? } return vcff; }
void addSizes(char *fileName, struct hash *chromHash, struct chromGenes *chromList) /* Add size of chromosome to all chromosomes in hash */ { char *row[2]; struct lineFile *lf = lineFileOpen(fileName, TRUE); struct chromGenes *chrom; while (lineFileRow(lf, row)) { if ((chrom = hashFindVal(chromHash, row[0])) != NULL) chrom->size = lineFileNeedNum(lf, row, 1); } lineFileClose(&lf); for (chrom = chromList; chrom != NULL; chrom = chrom->next) { if (chrom->size == 0) errAbort("No size for %s in %s", chrom->name, fileName); } }
struct agpFrag *readAgpFile(char *agpName) /* Read agps from file. */ { struct lineFile *lf = lineFileOpen(agpName, TRUE); int wordCount; char *words[16]; struct agpFrag *list = NULL, *el; while ((wordCount = lineFileChop(lf, words)) != 0) { if (words[4][0] != 'N') { lineFileExpectWords(lf, 9, wordCount); el = agpFragLoad(words); slAddHead(&list, el); } } lineFileClose(&lf); slReverse(&list); return list; }
struct hash *readSizes(char *fileName) /* Read tab-separated file into hash with * name key size value. */ { struct lineFile *lf = lineFileOpen(fileName, TRUE); struct hash *hash = newHash(0); char *row[2]; while (lineFileRow(lf, row)) { char *name = row[0]; int size = lineFileNeedNum(lf, row, 1); if (hashLookup(hash, name) != NULL) warn("Duplicate %s, ignoring all but first\n", name); else { hashAdd(hash, name, intToPt(size)); } } lineFileClose(&lf); return hash; }
struct hash *pslIntoHash(char *fileName) /* Read psl into a hash of pslLists keyed by psl->qName. */ { struct lineFile *lf = pslFileOpen(fileName); struct hash *hash = newHash(18); struct psl *psl; struct pslList *pl, *plList = NULL; while ((psl = pslNext(lf)) != NULL) { if ((pl = hashFindVal(hash, psl->qName)) == NULL) { AllocVar(pl); hashAdd(hash, psl->qName, pl); slAddHead(&plList, pl); } slAddHead(&pl->list, psl); } lineFileClose(&lf); return hash; }
void setAliBits(char *axtBestDir, char *chrom, int chromSize, Bits *aliBits, Bits *matchBits) /* Set bits where there are alignments and matches. */ { char axtFileName[512]; struct axt *axt; struct lineFile *lf; sprintf(axtFileName, "%s/%s.axt", axtBestDir, chrom); if ((lf = lineFileMayOpen(axtFileName, TRUE)) == NULL) { warn("Couldn't open %s", axtFileName); return; } while ((axt = axtRead(lf)) != NULL) { axtSetBits(axt, chromSize, aliBits, matchBits); axtFree(&axt); } lineFileClose(&lf); }
struct hash *refSeqVerInfoFromFile(struct sqlConnection *conn, char *accList, struct refSeqVerInfo **refSeqVerInfoList) /* load refSeqVerInfo table for all native refseqs specified in a file, then validate it against * the database. */ { struct hash *refSeqVerInfoTbl = hashNew(18); *refSeqVerInfoList = NULL; struct lineFile *lf = lineFileOpen(accList, TRUE); int errCnt = 0; char *line; while (lineFileNextReal(lf, &line)) { char *acc = trimSpaces(line); if (fromFileAdd(refSeqVerInfoTbl, refSeqVerInfoNewFile(acc), conn, refSeqVerInfoList) == refSeqVerInfoError) errCnt++; } lineFileClose(&lf); if (errCnt > 0) errAbort("%d errors detected loading RefSeq accessioned from %s", errCnt, accList); slSort(refSeqVerInfoList, refSeqVerInfoCmp); return refSeqVerInfoTbl; }
void lineCount(int fileCount, char *fileNames[]) /* lineCount - Count lines in a file. */ { long total = 0; long oneFile = 0; struct lineFile *lf; char *line; int i; for (i=0; i<fileCount; ++i) { lf = lineFileOpen(fileNames[i], FALSE); oneFile = 0; while (lineFileNext(lf, &line, NULL)) ++oneFile; printf("%ld\t%s\n", oneFile, lf->fileName); lineFileClose(&lf); total += oneFile; } if (fileCount > 1) printf("%ld\n", total); }
static char *hAssemblyDescription(char *db) /* Return a string containing db's description.html, or NULL if not found. */ //#*** LIBIFY: Code lifted from hgFind.c's hgPositionsHelpHtml. { char *htmlPath = hHtmlPath(db); char *htmlString = NULL; if (htmlPath != NULL) { if (fileExists(htmlPath)) readInGulp(htmlPath, &htmlString, NULL); else if (startsWith("http://" , htmlPath) || startsWith("https://", htmlPath) || startsWith("ftp://" , htmlPath)) { struct lineFile *lf = udcWrapShortLineFile(htmlPath, NULL, 256*1024); htmlString = lineFileReadAll(lf); lineFileClose(&lf); } } return htmlString; }