Mercurial > ~dholland > hg > ag > index.cgi
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; +}