/* spliceGraph.c was originally generated by the autoSql program, which also 
 * generated spliceGraph.h and spliceGraph.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 "spliceGraph.h"


struct spliceNode **_sgTmpLoadingArray = NULL;
int _sgTmpLoadingArraySize = 0;

struct spliceNode *spliceNodeLoad(char **row)
/* Load a spliceNode from row fetched with select * from spliceNode
 * from database.  Dispose of this with spliceNodeFree(). */
{
int sizeOne;
struct spliceNode *ret;

AllocVar(ret);
ret->edgeCount = sqlUnsigned(row[8]);
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->type = sqlUnsigned(row[5]);
ret->class = sqlUnsigned(row[6]);
ret->color = sqlUnsigned(row[7]);
sqlUnsignedDynamicArray(row[9], &ret->edges, &sizeOne);
assert(sizeOne == ret->edgeCount);

/* If we're loading this as part of a spliceGraph, register our nodes
   with the graph. */
if(_sgTmpLoadingArray != NULL)
    {
    assert(_sgTmpLoadingArraySize < ret->id);
    _sgTmpLoadingArray[ret->id] = ret;
    }

return ret;
}

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

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

struct spliceNode *spliceNodeCommaIn(char **pS, struct spliceNode *ret)
/* Create a spliceNode out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new spliceNode */
{
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->type = sqlUnsignedComma(&s);
ret->class = sqlUnsignedComma(&s);
ret->color = sqlUnsignedComma(&s);
ret->edgeCount = sqlUnsignedComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->edges, ret->edgeCount);
for (i=0; i<ret->edgeCount; ++i)
    {
    ret->edges[i] = sqlUnsignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
*pS = s;
return ret;
}

void spliceNodeFree(struct spliceNode **pEl)
/* Free a single dynamically allocated spliceNode such as created
 * with spliceNodeLoad(). */
{
struct spliceNode *el;

if ((el = *pEl) == NULL) return;
freeMem(el->tName);
freeMem(el->edges);
freez(pEl);
}

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

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

void spliceNodeOutput(struct spliceNode *el, FILE *f, char sep, char lastSep) 
/* Print out spliceNode.  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->type);
fputc(sep,f);
fprintf(f, "%u", el->class);
fputc(sep,f);
fprintf(f, "%u", el->color);
fputc(sep,f);
fprintf(f, "%u", el->edgeCount);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->edgeCount; ++i)
    {
    fprintf(f, "%u", el->edges[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(lastSep,f);
}

struct splicePath *splicePathLoad(char **row)
/* Load a splicePath from row fetched with select * from splicePath
 * from database.  Dispose of this with splicePathFree(). */
{
struct splicePath *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, spliceNodeCommaIn(&s, NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->nodes);
return ret;
}

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

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

struct splicePath *splicePathCommaIn(char **pS, struct splicePath *ret)
/* Create a splicePath out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new splicePath */
{
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, spliceNodeCommaIn(&s,NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->nodes);
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
*pS = s;
return ret;
}

void splicePathFree(struct splicePath **pEl)
/* Free a single dynamically allocated splicePath such as created
 * with splicePathLoad(). */
{
struct splicePath *el;

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

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

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

void splicePathOutput(struct splicePath *el, FILE *f, char sep, char lastSep) 
/* Print out splicePath.  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 spliceNode list. */
    {
    struct spliceNode *it = el->nodes;
    if (sep == ',') fputc('{',f);
    for (i=0; i<el->nodeCount; ++i)
        {
        fputc('{',f);
        spliceNodeCommaOut(it,f);
        it = it->next;
        fputc('}',f);
        fputc(',',f);
        }
    if (sep == ',') fputc('}',f);
    }
fputc(lastSep,f);
}

struct spliceGraph *spliceGraphLoad(char **row)
/* Load a spliceGraph from row fetched with select * from spliceGraph
 * from database.  Dispose of this with spliceGraphFree(). */
{
struct spliceGraph *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]);
AllocArray(ret->nodes, ret->nodeCapacity);

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

s = row[11];
for (i=0; i<ret->pathCount; ++i)
    {
    s = sqlEatChar(s, '{');
    slSafeAddHead(&ret->paths, splicePathCommaIn(&s, NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }

/* Don't let other nodes register themselves... */
_sgTmpLoadingArraySize = 0;
_sgTmpLoadingArray = NULL;
slReverse(&ret->paths);
return ret;
}

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

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

struct spliceGraph *spliceGraphCommaIn(char **pS, struct spliceGraph *ret)
/* Create a spliceGraph out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new spliceGraph */
{
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, splicePathCommaIn(&s,NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->paths);
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
*pS = s;
return ret;
}

void spliceGraphFree(struct spliceGraph **pEl)
/* Free a single dynamically allocated spliceGraph such as created
 * with spliceGraphLoad(). */
{
struct spliceGraph *el;

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

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

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

void spliceGraphOutput(struct spliceGraph *el, FILE *f, char sep, char lastSep) 
/* Print out spliceGraph.  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 splicePath list. */
    {
    struct splicePath *it = el->paths;
    if (sep == ',') fputc('{',f);
    for (i=0; i<el->pathCount; ++i)
        {
        fputc('{',f);
        splicePathCommaOut(it,f);
        it = it->next;
        fputc('}',f);
        fputc(',',f);
        }
    if (sep == ',') fputc('}',f);
    }
fputc(lastSep,f);
}

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

void spliceGraphIncreaseCapacity(struct spliceGraph *sg, int neededSize)
/* Increase the nodeCapcity of nodes for spliceGraph. */
{

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

void spliceGraphAddNode(struct spliceGraph *sg, struct spliceNode *sn)
/* Add the spliceNode sn to the array of node pointers maintained by the spliceGraph. */
{
if(sg->nodeCount + 1 >= sg->nodeCapacity)
    spliceGraphIncreaseCapacity(sg, sg->nodeCount+1);
sn->id = sg->nodeCount;
sg->nodes[sn->id] = sn;
sg->nodeCount++;
}

void spliceNodeConnect(struct spliceNode *sn1, struct spliceNode *sn2)
/* Create a directed edge from sn1 to sn2. */
{
assert(sn1);
assert(sn2);
ExpandArray(sn1->edges, sn1->edgeCount, sn1->edgeCount+1);
sn1->edges[sn1->edgeCount] = sn2->id;
sn1->edgeCount++;
}
