diff anagram/support/agstack.cpp @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/anagram/support/agstack.cpp	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,164 @@
+/**********************************************************
+
+The AnaGram Class Library
+
+The AgStackStorage Class
+Copyright 1997 Parsifal Software. All Rights Reserved.
+See the file COPYING for license and usage terms.
+
+***********************************************************/
+
+#include "agstack.h"
+#include "assert.h"
+
+// Caution - enabling this causes AG to core before anything is logged
+//#define INCLUDE_LOGGING
+#include "log.h"
+
+
+static int bytesAllocated = 0;
+//int constructorCalls = 0;
+//int copyConstructorCalls = 0;
+//int destructorCalls = 0;
+
+AgStackStorage::AgStackStorage(const unsigned quantum_,
+			       const unsigned logSize_,
+			       const unsigned bsLogSize_)
+  : buffer(malloc((unsigned)(quantum_ * (1<< logSize_))))
+  , bufferStack(0)
+  , count(0)
+  , usage(1)
+  , quantum((unsigned short) quantum_)
+  , bufferSize((unsigned short) (1 << logSize_))
+  , mask((unsigned short) (bufferSize - 1))
+  , index(0)
+  , logSize((unsigned char) logSize_)
+  , bsLogSize((unsigned char) bsLogSize_)
+{
+  LOGSECTION("AgStackStorage::AgStackStorage");
+  bytesAllocated += quantum * bufferSize;
+  //LOGV(bytesAllocated) LCV(quantum * bufferSize);
+}
+
+void *AgStackStorage::push() {
+  if (index >= bufferSize) {
+    if (bufferStack == 0) {
+      bufferStack = new AgStack<void *>(bsLogSize);
+    }
+    bufferStack->push(buffer);
+    //buffer = ::operator new(quantum*bufferSize);
+    buffer = malloc(quantum*bufferSize);
+    LOGS("AgStackStorage::push");
+    bytesAllocated += quantum*bufferSize;
+    //LOGV(bytesAllocated) LCV(quantum*bufferSize);
+    index = 0;
+  }
+  count++;
+  return (char *)buffer+quantum*index++;
+}
+
+void *AgStackStorage::pop() {
+  assert(count > 0);
+  if (index == 0) {
+    //delete buffer;
+    free(buffer);
+    LOGS("AgStackStorage::pop");
+    bytesAllocated -= quantum*bufferSize;
+    //LOGV(bytesAllocated) LCV(quantum * bufferSize);
+    buffer = bufferStack->pop();
+    if (bufferStack->size() == 0) {
+      delete bufferStack;
+      bufferStack = 0;
+    }
+    index = bufferSize;
+  }
+  count--;
+  return (char *)buffer+quantum*(--index);
+}
+
+AgStackStorage &AgStackStorage::discardData(unsigned n) {
+  assert(count >= n);
+  unsigned k = (unsigned) index < n ? index : n;
+
+  LOGSECTION("AgStackStorage::discardData");
+  LOGV(n) LCV(count) LCV(index) LCV(k) LCV((int) buffer) LCV(logSize);
+
+  count -= k;
+  index -= (unsigned short) k;
+  if (count == 0) {
+    return *this;
+  }
+  n -= k;
+  if (index == 0 && bufferStack != 0) {
+    //delete buffer;
+    free(buffer);
+    k = (n-1) >> logSize;
+    LOGV(k);
+    //if (k > 1) {
+      //k--;
+    if (k) {
+      bufferStack->discardData(k);
+      k <<= logSize;
+      n -= k;
+      count -= k;
+    }
+    LOGV(k) LCV(n) LCV(count);
+    buffer = bufferStack->pop();
+    if (bufferStack->size() == 0) {
+      delete bufferStack;
+      bufferStack = 0;
+    }
+    index = bufferSize;
+  }
+  count -= n;
+  index -= (unsigned short) n;
+  LOGV(n);
+  LOGV(count);
+  LOGV(index);
+  LOGV(k);
+  return *this;
+}
+
+void *AgStackStorage::locate(const unsigned n) const {
+#ifdef INCLUDE_LOGGING
+  if (n >= count) {
+    LOGSECTION("AgStackStorage::locate");
+    LOGV(n);
+    LOGV(count);
+  }
+#endif
+  assert(n < count);
+  if (bufferStack == 0) {
+    return (char *) buffer + quantum*n;
+  }
+  unsigned q = n >> logSize;
+  //void *buf = (q >= bufferStack->size()) ? buffer : (*bufferStack)[q];
+  //return (char *)buf + quantum * (n&mask);
+  if (q < bufferStack->size()) {
+    return (char *)(*bufferStack)[q] + quantum * (n&mask);
+  }
+  return (char *) buffer + quantum * (n&mask);
+
+}
+
+AgStackStorage::~AgStackStorage() {
+  LOGSECTION("AgStackStorage::~AgStackStorage");
+  //delete buffer;
+  free(buffer);
+  bytesAllocated -= quantum*bufferSize;
+  //LOGV(bytesAllocated) LCV(quantum*bufferSize);
+  if (bufferStack) {
+    int n = bufferStack->size();
+    LOGV(n);
+    while (n--) {
+      // XXX. I believe this should be free(), not delete.
+      delete (char *)bufferStack->pop();
+    }
+    delete bufferStack;
+  }
+}
+
+AgStackStorage &AgStackStorage::discardData() {
+  discardData(count);
+  return *this;
+}