/* exonGraph.c was originally generated by the autoSql program, which also 
 * generated exonGraph.h and exonGraph.sql.  This module links the database and
 * the RAM representation of objects. */

#include "common.h"
#include "linefile.h"
#include "dystring.h"
#include "jksql.h"
#include "exonGraph.h"


struct exonNode **_egTmpLoadingArray = NULL;
int _egTmpLoadingArraySize = 0;

struct exonNode *exonNodeLoad(char **row)
/* Load a exonNode from row fetched with select * from exonNode
 * from database.  Dispose of this with exonNodeFree(). */
{
struct exonNode *ret;
int sizeOne;

AllocVar(ret);
ret->startCount = sqlUnsigned(row[12]);
ret->endCount = sqlUnsigned(row[14]);
ret->edgeInCount = sqlUnsigned(row[16]);
ret->edgeOutCount = sqlUnsigned(row[18]);
ret->accCount = sqlUnsigned(row[20]);
ret->tName = cloneString(row[0]);
ret->tStart = sqlSigned(row[1]);
ret->tEnd = sqlSigned(row[2]);
strcpy(ret->strand, row[3]);
ret->id = sqlUnsigned(row[4]);
ret->startClass = sqlUnsigned(row[5]);
ret->endClass = sqlUnsigned(row[6]);
ret->startType = sqlUnsigned(row[7]);
ret->endType = sqlUnsigned(row[8]);
ret->type = sqlUnsigned(row[9]);
ret->class = sqlSigned(row[10]);
ret->color = sqlUnsigned(row[11]);
sqlUnsignedDynamicArray(row[13], &ret->starts, &sizeOne);
assert(sizeOne == ret->startCount);
sqlUnsignedDynamicArray(row[15], &ret->ends, &sizeOne);
assert(sizeOne == ret->endCount);
sqlUnsignedDynamicArray(row[17], &ret->edgesIn, &sizeOne);
assert(sizeOne == ret->edgeInCount);
sqlUnsignedDynamicArray(row[19], &ret->edgesOut, &sizeOne);
assert(sizeOne == ret->edgeOutCount);
sqlStringDynamicArray(row[21], &ret->accs, &sizeOne);
assert(sizeOne == ret->accCount);
if(_egTmpLoadingArray != NULL)
    {
    assert(_egTmpLoadingArraySize < ret->id);
    _egTmpLoadingArray[ret->id] = ret;
    }
return ret;
}

struct exonNode *exonNodeLoadAll(char *fileName) 
/* Load all exonNode from a tab-separated file.
 * Dispose of this with exonNodeFreeList(). */
{
struct exonNode *list = NULL, *el;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[22];

while (lineFileRow(lf, row))
    {
    el = exonNodeLoad(row);
    slAddHead(&list, el);
    }
lineFileClose(&lf);
slReverse(&list);
return list;
}

struct exonNode *exonNodeCommaIn(char **pS, struct exonNode *ret)
/* Create a exonNode out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new exonNode */
{
char *s = *pS;
int i;

if (ret == NULL)
    AllocVar(ret);
ret->tName = sqlStringComma(&s);
ret->tStart = sqlSignedComma(&s);
ret->tEnd = sqlSignedComma(&s);
sqlFixedStringComma(&s, ret->strand, sizeof(ret->strand));
ret->id = sqlUnsignedComma(&s);
ret->startClass = sqlUnsignedComma(&s);
ret->endClass = sqlUnsignedComma(&s);
ret->startType = sqlUnsignedComma(&s);
ret->endType = sqlUnsignedComma(&s);
ret->type = sqlUnsignedComma(&s);
ret->class = sqlSignedComma(&s);
ret->color = sqlUnsignedComma(&s);
ret->startCount = sqlUnsignedComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->starts, ret->startCount);
for (i=0; i<ret->startCount; ++i)
    {
    ret->starts[i] = sqlUnsignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->endCount = sqlUnsignedComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->ends, ret->endCount);
for (i=0; i<ret->endCount; ++i)
    {
    ret->ends[i] = sqlUnsignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->edgeInCount = sqlUnsignedComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->edgesIn, ret->edgeInCount);
for (i=0; i<ret->edgeInCount; ++i)
    {
    ret->edgesIn[i] = sqlUnsignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->edgeOutCount = sqlUnsignedComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->edgesOut, ret->edgeOutCount);
for (i=0; i<ret->edgeOutCount; ++i)
    {
    ret->edgesOut[i] = sqlUnsignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->accCount = sqlUnsignedComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->accs, ret->accCount);
for (i=0; i<ret->accCount; ++i)
    {
    ret->accs[i] = sqlStringComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
*pS = s;
return ret;
}

void exonNodeFree(struct exonNode **pEl)
/* Free a single dynamically allocated exonNode such as created
 * with exonNodeLoad(). */
{
struct exonNode *el;

if ((el = *pEl) == NULL) return;
freeMem(el->tName);
freeMem(el->starts);
freeMem(el->ends);
freeMem(el->edgesIn);
freeMem(el->edgesOut);
if(el->accDeepFree) 
    {
    int i;
    for(i=0; i<el->accCount; i++)
	freez(&el->accs[i]);
    }
else 
    {
/* All strings in accs are allocated at once, so only need to free first. */
    if (el->accs != NULL)
	freeMem(el->accs[0]);
    }
freeMem(el->accs);
freez(pEl);
}

void exonNodeFreeList(struct exonNode **pList)
/* Free a list of dynamically allocated exonNode's */
{
struct exonNode *el, *next;

for (el = *pList; el != NULL; el = next)
    {
    next = el->next;
    exonNodeFree(&el);
    }
*pList = NULL;
}

void exonNodeOutput(struct exonNode *el, FILE *f, char sep, char lastSep) 
/* Print out exonNode.  Separate fields with sep. Follow last field with lastSep. */
{
int i;
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->tName);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%d", el->tStart);
fputc(sep,f);
fprintf(f, "%d", el->tEnd);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->strand);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%u", el->id);
fputc(sep,f);
fprintf(f, "%u", el->startClass);
fputc(sep,f);
fprintf(f, "%u", el->endClass);
fputc(sep,f);
fprintf(f, "%u", el->startType);
fputc(sep,f);
fprintf(f, "%u", el->endType);
fputc(sep,f);
fprintf(f, "%u", el->type);
fputc(sep,f);
fprintf(f, "%d", el->class);
fputc(sep,f);
fprintf(f, "%u", el->color);
fputc(sep,f);
fprintf(f, "%u", el->startCount);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->startCount; ++i)
    {
    fprintf(f, "%u", el->starts[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
fprintf(f, "%u", el->endCount);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->endCount; ++i)
    {
    fprintf(f, "%u", el->ends[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
fprintf(f, "%u", el->edgeInCount);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->edgeInCount; ++i)
    {
    fprintf(f, "%u", el->edgesIn[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
fprintf(f, "%u", el->edgeOutCount);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->edgeOutCount; ++i)
    {
    fprintf(f, "%u", el->edgesOut[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
fprintf(f, "%u", el->accCount);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->accCount; ++i)
    {
    if (sep == ',') fputc('"',f);
    fprintf(f, "%s", el->accs[i]);
    if (sep == ',') fputc('"',f);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(lastSep,f);
}

struct exonPath *exonPathLoad(char **row)
/* Load a exonPath from row fetched with select * from exonPath
 * from database.  Dispose of this with exonPathFree(). */
{
struct exonPath *ret;
int i;
char *s;

AllocVar(ret);
ret->nodeCount = sqlUnsigned(row[6]);
ret->tName = cloneString(row[0]);
ret->tStart = sqlSigned(row[1]);
ret->tEnd = sqlSigned(row[2]);
ret->qName = cloneString(row[3]);
strcpy(ret->strand, row[4]);
ret->path = cloneString(row[5]);
s = row[7];
for (i=0; i<ret->nodeCount; ++i)
    {
    s = sqlEatChar(s, '{');
    slSafeAddHead(&ret->nodes, exonNodeCommaIn(&s, NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->nodes);
return ret;
}

struct exonPath *exonPathLoadAll(char *fileName) 
/* Load all exonPath from a tab-separated file.
 * Dispose of this with exonPathFreeList(). */
{
struct exonPath *list = NULL, *el;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[8];

while (lineFileRow(lf, row))
    {
    el = exonPathLoad(row);
    slAddHead(&list, el);
    }
lineFileClose(&lf);
slReverse(&list);
return list;
}

struct exonPath *exonPathCommaIn(char **pS, struct exonPath *ret)
/* Create a exonPath out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new exonPath */
{
char *s = *pS;
int i;

if (ret == NULL)
    AllocVar(ret);
ret->tName = sqlStringComma(&s);
ret->tStart = sqlSignedComma(&s);
ret->tEnd = sqlSignedComma(&s);
ret->qName = sqlStringComma(&s);
sqlFixedStringComma(&s, ret->strand, sizeof(ret->strand));
ret->path = sqlStringComma(&s);
ret->nodeCount = sqlUnsignedComma(&s);
s = sqlEatChar(s, '{');
for (i=0; i<ret->nodeCount; ++i)
    {
    s = sqlEatChar(s, '{');
    slSafeAddHead(&ret->nodes, exonNodeCommaIn(&s,NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->nodes);
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
*pS = s;
return ret;
}

void exonPathFree(struct exonPath **pEl)
/* Free a single dynamically allocated exonPath such as created
 * with exonPathLoad(). */
{
struct exonPath *el;

if ((el = *pEl) == NULL) return;
freeMem(el->tName);
freeMem(el->qName);
freeMem(el->path);
exonNodeFreeList(&el->nodes);
freez(pEl);
}

void exonPathFreeList(struct exonPath **pList)
/* Free a list of dynamically allocated exonPath's */
{
struct exonPath *el, *next;

for (el = *pList; el != NULL; el = next)
    {
    next = el->next;
    exonPathFree(&el);
    }
*pList = NULL;
}

void exonPathOutput(struct exonPath *el, FILE *f, char sep, char lastSep) 
/* Print out exonPath.  Separate fields with sep. Follow last field with lastSep. */
{
int i;
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->tName);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%d", el->tStart);
fputc(sep,f);
fprintf(f, "%d", el->tEnd);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->qName);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->strand);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->path);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%u", el->nodeCount);
fputc(sep,f);
/* Loading exonNode list. */
    {
    struct exonNode *it = el->nodes;
    if (sep == ',') fputc('{',f);
    for (i=0; i<el->nodeCount; ++i)
        {
        fputc('{',f);
        exonNodeCommaOut(it,f);
        it = it->next;
        fputc('}',f);
        fputc(',',f);
        }
    if (sep == ',') fputc('}',f);
    }
fputc(lastSep,f);
}

struct exonGraph *exonGraphLoad(char **row)
/* Load a exonGraph from row fetched with select * from exonGraph
 * from database.  Dispose of this with exonGraphFree(). */
{
struct exonGraph *ret;
int sizeOne,i;
char *s;

AllocVar(ret);
ret->classCount = sqlUnsigned(row[4]);
ret->pathCount = sqlUnsigned(row[10]);
ret->tName = cloneString(row[0]);
ret->tStart = sqlSigned(row[1]);
ret->tEnd = sqlSigned(row[2]);
strcpy(ret->strand, row[3]);
sqlUnsignedDynamicArray(row[5], &ret->classStarts, &sizeOne);
assert(sizeOne == ret->classCount);
sqlUnsignedDynamicArray(row[6], &ret->classEnds, &sizeOne);
assert(sizeOne == ret->classCount);
sqlUnsignedDynamicArray(row[7], &ret->classTypes, &sizeOne);
assert(sizeOne == ret->classCount);
ret->nodeCount = sqlUnsigned(row[8]);
ret->nodeCapacity = sqlUnsigned(row[9]);

/* Set our nodes array such that nodes will register themselves as they come
   into existence. */
_egTmpLoadingArray = ret->nodes;
_egTmpLoadingArraySize = ret->nodeCapacity;

s = row[11];
for (i=0; i<ret->pathCount; ++i)
    {
    s = sqlEatChar(s, '{');
    slSafeAddHead(&ret->paths, exonPathCommaIn(&s, NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->paths);
/* Don't let other nodes register themselves... */
_egTmpLoadingArraySize = 0;
_egTmpLoadingArray = NULL;
return ret;
}

struct exonGraph *exonGraphLoadAll(char *fileName) 
/* Load all exonGraph from a tab-separated file.
 * Dispose of this with exonGraphFreeList(). */
{
struct exonGraph *list = NULL, *el;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[12];

while (lineFileRow(lf, row))
    {
    el = exonGraphLoad(row);
    slAddHead(&list, el);
    }
lineFileClose(&lf);
slReverse(&list);
return list;
}

struct exonGraph *exonGraphCommaIn(char **pS, struct exonGraph *ret)
/* Create a exonGraph out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new exonGraph */
{
char *s = *pS;
int i;

if (ret == NULL)
    AllocVar(ret);
ret->tName = sqlStringComma(&s);
ret->tStart = sqlSignedComma(&s);
ret->tEnd = sqlSignedComma(&s);
sqlFixedStringComma(&s, ret->strand, sizeof(ret->strand));
ret->classCount = sqlUnsignedComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->classStarts, ret->classCount);
for (i=0; i<ret->classCount; ++i)
    {
    ret->classStarts[i] = sqlUnsignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
s = sqlEatChar(s, '{');
AllocArray(ret->classEnds, ret->classCount);
for (i=0; i<ret->classCount; ++i)
    {
    ret->classEnds[i] = sqlUnsignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
s = sqlEatChar(s, '{');
AllocArray(ret->classTypes, ret->classCount);
for (i=0; i<ret->classCount; ++i)
    {
    ret->classTypes[i] = sqlUnsignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->nodeCount = sqlUnsignedComma(&s);
ret->nodeCapacity = sqlUnsignedComma(&s);
ret->pathCount = sqlUnsignedComma(&s);
s = sqlEatChar(s, '{');
for (i=0; i<ret->pathCount; ++i)
    {
    s = sqlEatChar(s, '{');
    slSafeAddHead(&ret->paths, exonPathCommaIn(&s,NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->paths);
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
*pS = s;
return ret;
}

void exonGraphFree(struct exonGraph **pEl)
/* Free a single dynamically allocated exonGraph such as created
 * with exonGraphLoad(). */
{
struct exonGraph *el;

if ((el = *pEl) == NULL) return;
freeMem(el->tName);
freeMem(el->classStarts);
freeMem(el->classEnds);
freeMem(el->classTypes);
exonPathFreeList(&el->paths);
exonPathFreeList(&el->rejects);
freez(&el->nodes);
freez(pEl);
}

void exonGraphFreeList(struct exonGraph **pList)
/* Free a list of dynamically allocated exonGraph's */
{
struct exonGraph *el, *next;

for (el = *pList; el != NULL; el = next)
    {
    next = el->next;
    exonGraphFree(&el);
    }
*pList = NULL;
}

void exonGraphOutput(struct exonGraph *el, FILE *f, char sep, char lastSep) 
/* Print out exonGraph.  Separate fields with sep. Follow last field with lastSep. */
{
int i;
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->tName);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%d", el->tStart);
fputc(sep,f);
fprintf(f, "%d", el->tEnd);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->strand);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%u", el->classCount);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->classCount; ++i)
    {
    fprintf(f, "%u", el->classStarts[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->classCount; ++i)
    {
    fprintf(f, "%u", el->classEnds[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->classCount; ++i)
    {
    fprintf(f, "%u", el->classTypes[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
fprintf(f, "%u", el->nodeCount);
fputc(sep,f);
fprintf(f, "%u", el->nodeCapacity);
fputc(sep,f);
fprintf(f, "%u", el->pathCount);
fputc(sep,f);
/* Loading exonPath list. */
    {
    struct exonPath *it = el->paths;
    if (sep == ',') fputc('{',f);
    for (i=0; i<el->pathCount; ++i)
        {
        fputc('{',f);
        exonPathCommaOut(it,f);
        it = it->next;
        fputc('}',f);
        fputc(',',f);
        }
    if (sep == ',') fputc('}',f);
    }
fputc(lastSep,f);
}

/* -------------------------------- End autoSql Generated Code -------------------------------- */


void exonGraphIncreaseCapacity(struct exonGraph *eg, int neededSize)
/* Increase the nodeCapcity of nodes for exonGraph. */
{

if(eg->nodeCapacity == 0)
    {
    if(neededSize < 50) neededSize = 50;
    ExpandArray(eg->nodes, eg->nodeCapacity, neededSize);
    eg->nodeCapacity = neededSize;
    }
else
    {
    while(eg->nodeCapacity <= neededSize)
	{
	ExpandArray(eg->nodes, eg->nodeCapacity, eg->nodeCapacity*2);
	eg->nodeCapacity = eg->nodeCapacity*2;
	}
    }
}

void exonGraphAddNode(struct exonGraph *eg, struct exonNode *en)
/* Add the exonNode en to the array of node pointers maintained by the exonGraph. */
{
if(eg->nodeCount + 1 >= eg->nodeCapacity)
    exonGraphIncreaseCapacity(eg, eg->nodeCount+1);
en->id = eg->nodeCount;
eg->nodes[en->id] = en;
eg->nodeCount++;
}

void exonNodeConnect(struct exonNode *en1, struct exonNode *en2)
/* Create a directed edge from en1 to en2. And register e1 as connecting to e2. */
{
assert(en1);
assert(en2);
ExpandArray(en1->edgesOut, en1->edgeOutCount, en1->edgeOutCount+1);
en1->edgesOut[en1->edgeOutCount] = en2->id;
en1->edgeOutCount++;
ExpandArray(en2->edgesIn, en2->edgeInCount, en2->edgeInCount+1);
en2->edgesIn[en2->edgeInCount] = en1->id;
en2->edgeInCount++;
}

void addExonNodeEnd(struct exonNode *en, unsigned int end)
/* Add another exon node end to an exonNode. */
{
int oldCount = en->endCount++;
ExpandArray(en->ends, oldCount, en->endCount);
en->ends[oldCount] = end;
}

void addExonNodeStart(struct exonNode *en, unsigned int start)
/* Add another exon node start to an exonNode. */
{
int oldCount = en->startCount++;
ExpandArray(en->starts, oldCount, en->startCount);
en->starts[oldCount] = start;
}

