00001
00002
00003
00004
00005
00006
00007
00008 #include "common.h"
00009 #include "spaceSaver.h"
00010
00011 static char const rcsid[] = "$Id: spaceSaver.c,v 1.10 2004/09/02 20:08:44 kent Exp $";
00012
00013
00014 struct spaceSaver *spaceSaverMaxCellsNew(int winStart, int winEnd, int maxRows, int maxCells)
00015
00016 {
00017 struct spaceSaver *ss;
00018 float winWidth;
00019
00020 AllocVar(ss);
00021 ss->winStart = winStart;
00022 ss->winEnd = winEnd;
00023 ss->maxRows = maxRows;
00024 winWidth = winEnd - winStart;
00025 ss->cellsInRow = winWidth;
00026 while (ss->cellsInRow > maxCells)
00027 ss->cellsInRow /= 2;
00028 ss->scale = ss->cellsInRow/winWidth;
00029 return ss;
00030 }
00031
00032 struct spaceSaver *spaceSaverNew(int winStart, int winEnd, int maxRows)
00033
00034 {
00035 return spaceSaverMaxCellsNew(winStart, winEnd, maxRows, 800);
00036 }
00037
00038 void spaceSaverFree(struct spaceSaver **pSs)
00039
00040 {
00041 struct spaceSaver *ss = *pSs;
00042 if (ss != NULL)
00043 {
00044 struct spaceRowTracker *srt;
00045 for (srt = ss->rowList; srt != NULL; srt = srt->next)
00046 freeMem(srt->used);
00047 slFreeList(&ss->rowList);
00048 slFreeList(&ss->nodeList);
00049 freez(pSs);
00050 }
00051 }
00052
00053 static boolean allClear(bool *b, int count)
00054
00055 {
00056 int i;
00057 for (i=0; i<count; ++i)
00058 if (b[i])
00059 return FALSE;
00060 return TRUE;
00061 }
00062
00063 struct spaceNode *spaceSaverAddOverflow(struct spaceSaver *ss, int start, int end,
00064 void *val, boolean allowOverflow)
00065
00066
00067
00068 {
00069 int cellStart, cellEnd, cellWidth;
00070 struct spaceRowTracker *srt, *freeSrt = NULL;
00071 int rowIx = 0;
00072 struct spaceNode *sn;
00073
00074 if (ss->isFull)
00075 return NULL;
00076
00077 if ((start -= ss->winStart) < 0)
00078 start = 0;
00079 end -= ss->winStart;
00080
00081 cellStart = round(start * ss->scale);
00082 cellEnd = round(end * ss->scale)+1;
00083 if (cellEnd > ss->cellsInRow)
00084 cellEnd = ss->cellsInRow;
00085 cellWidth = cellEnd - cellStart;
00086
00087
00088 for (srt = ss->rowList; srt != NULL; srt = srt->next)
00089 {
00090 if (allClear(srt->used + cellStart, cellWidth))
00091 {
00092 freeSrt = srt;
00093 break;
00094 }
00095 ++rowIx;
00096 }
00097
00098
00099 if (freeSrt == NULL)
00100 {
00101 if (ss->rowCount >= ss->maxRows)
00102 {
00103
00104
00105 if(!allowOverflow)
00106 {
00107 ss->isFull = TRUE;
00108 return NULL;
00109 }
00110 }
00111 else
00112 {
00113 AllocVar(freeSrt);
00114 freeSrt->used = needMem(ss->cellsInRow);
00115 slAddTail(&ss->rowList, freeSrt);
00116 ++ss->rowCount;
00117 }
00118 }
00119
00120
00121 if(freeSrt != NULL)
00122 memset(freeSrt->used + cellStart, 1, cellWidth);
00123
00124
00125
00126 AllocVar(sn);
00127 sn->row = rowIx;
00128 sn->val = val;
00129 slAddHead(&ss->nodeList, sn);
00130 return sn;
00131 }
00132
00133 struct spaceNode *spaceSaverAdd(struct spaceSaver *ss,
00134 int start, int end, void *val)
00135
00136
00137 {
00138 return spaceSaverAddOverflow(ss, start, end, val, FALSE);
00139 }
00140
00141 void spaceSaverFinish(struct spaceSaver *ss)
00142
00143 {
00144 slReverse(&ss->nodeList);
00145 }