2f313d36a367752cb1925bf3b514cc5c11ce343b
tdreszer
  Mon Jan 28 11:45:16 2013 -0800
Added local memeory support for bits and a couple of routines to query lm size.
diff --git src/lib/localmem.c src/lib/localmem.c
index e364a66..276b663 100644
--- src/lib/localmem.c
+++ src/lib/localmem.c
@@ -62,73 +62,103 @@
 newBlock(lm, blockSize);
 return lm;
 }
 
 void lmCleanup(struct lm **pLm)
 /* Clean up a local memory pool. */
 {
     struct lm *lm = *pLm;
     if (lm == NULL)
         return;
     slFreeList(&lm->blocks);
     freeMem(lm);
     *pLm = NULL;
 }
 
+int lmFlushZ(struct lm *lm)
+// Zero's and makes available most recent block of pool, abandoning older blocks
+// USE WITH CAUTION: All previous pointers into lm will be invalid
+{
+slFreeList(&(lm->blocks->next));  // free any extra blocks
+struct lmBlock *mb = lm->blocks;
+mb->free = (char *)(mb+1);
+size_t fullSize = (mb->end - mb->free);
+memset(mb->free,0,fullSize);
+return fullSize;
+}
+
+size_t lmAvailable(struct lm *lm)
+// Returns currently available memory in pool
+{
+struct lmBlock *mb = lm->blocks;
+return (mb->end - mb->free);
+}
+
+size_t lmSize(struct lm *lm)
+// Returns current size of pool, even for memory already allocated
+{
+size_t fullSize = 0;
+
+struct lmBlock *mb = lm->blocks;
+for (;mb != NULL;mb = mb->next)
+    fullSize += (mb->end - (char *)(mb+1));
+
+return fullSize;
+}
+
 void *lmAlloc(struct lm *lm, size_t size)
 /* Allocate memory from local pool. */
 {
 struct lmBlock *mb = lm->blocks;
 void *ret;
 size_t memLeft = mb->end - mb->free;
 if (memLeft < size)
     mb = newBlock(lm, size);
 ret = mb->free;
 mb->free += ((size+lm->allignAdd)&lm->allignMask);
 if (mb->free > mb->end)
     mb->free = mb->end;
 return ret;
 }
 
-void *lmCloneMem(struct lm *lm, void *pt, size_t size)
-/* Return a local mem copy of memory block. */
-{
-void *d = lmAlloc(lm, size);
-memcpy(d, pt, size);
-return d;
-}
-
-char *lmCloneStringZ(struct lm *lm, char *string, int size)
-/* Return local mem copy of string. */
+void *lmAllocMoreMem(struct lm *lm, void *pt, size_t oldSize, size_t newSize)
+/* Adjust memory size on a block, possibly relocating it.  If block is grown,
+ * new memory is zeroed. */
 {
-if (string == NULL)
-    return NULL;
-else
+struct lmBlock *mb = lm->blocks;
+// rare case that pointer is to last lm alloc, but still try.
+// Note this is the one place where the pointer gets reused and it is known to be in this lm
+// Since lm allocs are never freed, this means the pointer CAN be reused (by lmCloneMem)
+if ((char *)pt + oldSize == mb->free
+&&  (char *)pt + newSize <= mb->end)
     {
-    char *s = lmAlloc(lm, size+1);
-    memcpy(s, string, size);
-    return s;
+    if (newSize > oldSize) // only move the free pointer on more mem
+        mb->free = pt + newSize;
+    return pt;
     }
+void *new = lmAlloc(lm, newSize);
+memcpy(new, pt, oldSize);
+return new;
 }
 
-char *lmCloneString(struct lm *lm, char *string)
+char *lmCloneStringZ(struct lm *lm, char *string, int size)
 /* Return local mem copy of string. */
 {
 if (string == NULL)
     return NULL;
-else
-    return lmCloneStringZ(lm, string, strlen(string));
+else                                                   // in rare cases, this returns the same mem
+    return lmAllocMoreMem(lm, string, size, size + 1); // but lm allocs are never freed so it works
 }
 
 char *lmCloneFirstWord(struct lm *lm, char *line)
 /* Clone first word in line */
 {
 char *startFirstWord = skipLeadingSpaces(line);
 if (startFirstWord == NULL)
     return NULL;
 char *endFirstWord = skipToSpaces(startFirstWord);
 if (endFirstWord == NULL)
     return lmCloneString(lm, startFirstWord);
 else
     return lmCloneStringZ(lm, startFirstWord, endFirstWord - startFirstWord);
 }