[sword-svn] r429 - in trunk/clucene/src/CLucene: config util

scribe at crosswire.org scribe at crosswire.org
Sun Jun 25 18:33:29 MST 2006


Author: scribe
Date: 2006-06-25 18:33:27 -0700 (Sun, 25 Jun 2006)
New Revision: 429

Added:
   trunk/clucene/src/CLucene/config/threads.cpp
   trunk/clucene/src/CLucene/util/BitSet.cpp
   trunk/clucene/src/CLucene/util/bufferedstream.h
   trunk/clucene/src/CLucene/util/fileinputstream.cpp
   trunk/clucene/src/CLucene/util/fileinputstream.h
   trunk/clucene/src/CLucene/util/inputstreambuffer.h
Log:
Added new needed files from latest clucene svn

Added: trunk/clucene/src/CLucene/config/threads.cpp
===================================================================
--- trunk/clucene/src/CLucene/config/threads.cpp	2006-06-26 00:39:24 UTC (rev 428)
+++ trunk/clucene/src/CLucene/config/threads.cpp	2006-06-26 01:33:27 UTC (rev 429)
@@ -0,0 +1,163 @@
+/*------------------------------------------------------------------------------
+* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
+* 
+* Distributable under the terms of either the Apache License (Version 2.0) or 
+* the GNU Lesser General Public License, as specified in the COPYING file.
+------------------------------------------------------------------------------*/
+#include "CLucene/StdHeader.h"
+
+#ifndef _CL_DISABLE_MULTITHREADING
+CL_NS_DEF(util)
+
+
+mutexGuard::mutexGuard(const mutexGuard& clone){
+	//no autoclone
+	mrMutex = NULL;
+}
+mutexGuard::mutexGuard( _LUCENE_THREADMUTEX& rMutex ) :
+	mrMutex(&rMutex)
+{
+	mrMutex->lock();
+}
+mutexGuard::~mutexGuard()
+{
+	mrMutex->unlock();
+}
+
+#if defined(_LUCENE_DONTIMPLEMENT_THREADMUTEX)
+	//do nothing
+	#if defined(_LUCENE_PRAGMA_WARNINGS)
+	 #pragma message ("==================Not implementing any thread mutex==================")
+	#else
+	 #warning "==================Not implementing any thread mutex=================="
+	#endif
+
+
+
+#elif defined(_CLCOMPILER_MSVC) || defined(__MINGW32__)
+	#include "CLucene/config/threadCSection.h"
+
+   #if !defined(LUCENE_USE_WINDOWS_H) && !defined(_WINDOWS_)
+      //we have not explicity included windows.h and windows.h has
+      //not been included (check _WINDOWS_), then we must define
+      //our own definitions to the thread locking functions:
+      extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(CRITICAL_SECTION *);
+      extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(CRITICAL_SECTION *);
+      extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(CRITICAL_SECTION *);
+      extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(CRITICAL_SECTION *);
+	  extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
+   #endif
+	
+	mutex_win32::mutex_win32(const mutex_win32& clone){
+		InitializeCriticalSection(&mtx); 
+	}
+	mutex_win32::mutex_win32()
+	{ 
+		InitializeCriticalSection(&mtx); 
+	}
+	
+	mutex_win32::~mutex_win32()
+	{ 
+		DeleteCriticalSection(&mtx); 
+	}
+	
+	void mutex_win32::lock()
+	{ 
+		EnterCriticalSection(&mtx); 
+	}
+	
+	void mutex_win32::unlock()
+	{ 
+		LeaveCriticalSection(&mtx); 
+	}
+
+
+
+#elif defined(_CL_HAVE_PTHREAD)
+	#include "CLucene/config/threadPthread.h"
+		
+	#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
+		bool mutex_pthread_attr_initd=false;
+		pthread_mutexattr_t mutex_pthread_attr;
+	#endif
+	
+	#ifdef _CL__CND_DEBUG
+		//todo: add back CND_PRECONDITION(c==0,m) 
+		#define _CLPTHREAD_CHECK(c,m) c; //CND_PRECONDITION(c==0,m)
+	#else
+		#define _CLPTHREAD_CHECK(c,m) c;
+	#endif
+
+	mutex_pthread::mutex_pthread(const mutex_pthread& clone){
+		#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
+		_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed")
+		#else
+	  	#if defined(__hpux) && defined(_DECTHREADS_)
+			_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed")
+		#else
+			_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed")
+		#endif
+		lockCount=0;
+		lockOwner=0;
+		#endif
+	}
+	mutex_pthread::mutex_pthread()
+	{ 
+		#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
+	  	if ( mutex_pthread_attr_initd == false ){
+	  		pthread_mutexattr_init(&mutex_pthread_attr);
+		  	pthread_mutexattr_settype(&mutex_pthread_attr, PTHREAD_MUTEX_RECURSIVE);
+		  	mutex_pthread_attr_initd = true;
+		}
+		_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed")
+		#else
+	  	#if defined(__hpux) && defined(_DECTHREADS_)
+			_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed")
+		#else
+			_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed")
+		#endif
+		lockCount=0;
+		lockOwner=0;
+		#endif
+	}
+	
+	mutex_pthread::~mutex_pthread()
+	{ 
+		_CLPTHREAD_CHECK(pthread_mutex_destroy(&mtx), "~mutex_pthread destructor failed") 
+	}
+	
+	void mutex_pthread::lock()
+	{ 
+		#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
+		pthread_t currentThread = pthread_self();
+		if( pthread_equal( lockOwner, currentThread ) ) {
+			++lockCount;
+		} else {
+			_CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock")
+			lockOwner = currentThread;
+			lockCount = 1;
+		}
+		#else
+		_CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock")
+		#endif
+	}
+	
+	void mutex_pthread::unlock()
+	{ 
+		#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
+		--lockCount;
+		if( lockCount == 0 )
+		{
+			lockOwner = 0;
+			_CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock")
+		}
+		#else
+		_CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock")
+		#endif
+	}
+
+#endif //thread impl choice
+
+
+CL_NS_END
+#endif //!_CL_DISABLE_MULTITHREADING

Added: trunk/clucene/src/CLucene/util/BitSet.cpp
===================================================================
--- trunk/clucene/src/CLucene/util/BitSet.cpp	2006-06-26 00:39:24 UTC (rev 428)
+++ trunk/clucene/src/CLucene/util/BitSet.cpp	2006-06-26 01:33:27 UTC (rev 429)
@@ -0,0 +1,113 @@
+/*------------------------------------------------------------------------------
+* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
+* 
+* Distributable under the terms of either the Apache License (Version 2.0) or 
+* the GNU Lesser General Public License, as specified in the COPYING file.
+------------------------------------------------------------------------------*/
+#include "CLucene/StdHeader.h"
+#include "BitSet.h"
+#include "CLucene/store/Directory.h"
+
+CL_NS_USE(store)
+CL_NS_DEF(util)
+
+BitSet::BitSet( const BitSet& copy ) :
+	_size( copy._size ),
+	_count(-1)
+{
+	int32_t len = (_size >> 3) + 1;
+	bits = _CL_NEWARRAY(uint8_t, len);
+	memcpy( bits, copy.bits, len );
+}
+
+///Create a bitset with the specified size
+BitSet::BitSet ( int32_t size ):
+  _size(size)
+{
+	int32_t len = (_size >> 3) + 1;
+	bits = _CL_NEWARRAY(uint8_t, len);
+	memset(bits,0,len);
+}
+
+BitSet::BitSet(CL_NS(store)::Directory* d, const char* name) {
+	_count=-1;
+	CL_NS(store)::IndexInput* input = d->openInput( name );
+	try {
+		_size = input->readInt();			  // read size
+	  	_count = input->readInt();			  // read count
+
+		bits = _CL_NEWARRAY(uint8_t,(_size >> 3) + 1);		  // allocate bits
+		input->readBytes(bits, 0, (_size >> 3) + 1);	  // read bits
+	} _CLFINALLY (
+	    input->close();
+	    _CLDELETE(input );
+	);
+}
+	
+void BitSet::write(CL_NS(store)::Directory* d, const char* name) {
+	CL_NS(store)::IndexOutput* output = d->createOutput(name);
+	try {
+	  output->writeInt(size());			  // write size
+	  output->writeInt(count());			  // write count
+	  output->writeBytes(bits, (_size >> 3) + 1);	  // write bits
+	} _CLFINALLY (
+	    output->close();
+	    _CLDELETE(output);
+	);
+}
+
+///Destructor for the bit set
+BitSet::~BitSet(){
+	_CLDELETE_ARRAY(bits);
+}
+///set the value of the specified bit
+void BitSet::set(const int32_t bit, bool val){
+	_count = -1;
+
+	if (val)
+		bits[bit >> 3] |= 1 << (bit & 7);
+	else
+		bits[bit >> 3] &= ~(1 << (bit & 7));
+	_count =-1;
+}
+///returns the size of the bitset
+int32_t BitSet::size() const {
+  return _size;
+}
+/// Returns the total number of one bits in this BitSet.  This is efficiently
+///	computed and cached, so that, if the BitSet is not changed, no
+///	recomputation is done for repeated calls. 
+int32_t BitSet::count(){
+	// if the BitSet has been modified
+    if (_count == -1) {
+      static const uint8_t BYTE_COUNTS[] = {  
+            0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+            1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+            1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+            1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+            3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+            1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+            3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+            3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+            3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+            4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
+
+      int32_t c = 0;
+      int32_t end = (_size >> 3) + 1;
+      for (int32_t i = 0; i < end; i++)
+        c += BYTE_COUNTS[bits[i] & 0xFF];	  // sum bits per uint8_t
+      _count = c;
+    }
+    return _count;
+}
+BitSet* BitSet::clone() const {
+	return _CLNEW BitSet( *this );
+}
+
+CL_NS_END

Added: trunk/clucene/src/CLucene/util/bufferedstream.h
===================================================================
--- trunk/clucene/src/CLucene/util/bufferedstream.h	2006-06-26 00:39:24 UTC (rev 428)
+++ trunk/clucene/src/CLucene/util/bufferedstream.h	2006-06-26 01:33:27 UTC (rev 429)
@@ -0,0 +1,145 @@
+/**
+ * Copyright 2003-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef BUFFEREDSTREAM_H
+#define BUFFEREDSTREAM_H
+
+#include "streambase.h"
+#include "inputstreambuffer.h"
+
+namespace jstreams {
+
+template <class T>
+class BufferedInputStream : public StreamBase<T> {
+private:
+    bool finishedWritingToBuffer;
+    InputStreamBuffer<T> buffer;
+
+    void writeToBuffer(int32_t minsize);
+    int32_t read_(const T*& start, int32_t min, int32_t max);
+protected:
+    /**
+     * This function must be implemented by the subclasses.
+     * It should write a maximum of @p space characters at the buffer
+     * position pointed to by @p start. If no more data is avaiable due to
+     * end of file, -1 should be returned. If an error occurs, the status
+     * should be set to Error, an error message should be set and the function
+     * must return -1.
+     **/
+    virtual int32_t fillBuffer(T* start, int32_t space) = 0;
+    // this function might be useful if you want to reuse a bufferedstream
+    void resetBuffer() {printf("implement 'resetBuffer'\n");}
+public:
+    BufferedInputStream<T>();
+    int32_t read(const T*& start, int32_t min, int32_t max);
+    int64_t mark(int32_t readlimit);
+    int64_t reset(int64_t);
+    virtual int64_t skip(int64_t ntoskip);
+};
+
+template <class T>
+BufferedInputStream<T>::BufferedInputStream() {
+    finishedWritingToBuffer = false;
+}
+
+template <class T>
+void
+BufferedInputStream<T>::writeToBuffer(int32_t ntoread) {
+    int32_t missing = ntoread - buffer.avail;
+    int32_t nwritten = 0;
+    while (missing > 0 && nwritten >= 0) {
+        int32_t space;
+        space = buffer.makeSpace(missing);
+        T* start = buffer.readPos + buffer.avail;
+        nwritten = fillBuffer(start, space);
+        if (nwritten > 0) {
+            buffer.avail += nwritten;
+            missing = ntoread - buffer.avail;
+        }
+    }
+    if (nwritten < 0) {
+        finishedWritingToBuffer = true;
+    }
+}
+template <class T>
+int32_t
+BufferedInputStream<T>::read(const T*& start, int32_t min, int32_t max) {
+    if (StreamBase<T>::status == Error) return -2;
+    if (StreamBase<T>::status == Eof) return -1;
+
+    // do we need to read data into the buffer?
+    if (!finishedWritingToBuffer && min > buffer.avail) {
+        // do we have enough space in the buffer?
+        writeToBuffer(min);
+        if (StreamBase<T>::status == Error) return -2;
+        if (StreamBase<T>::status == Eof) return -1;
+    }
+
+    int32_t nread = buffer.read(start, max);
+/*    if (nread == 0) {
+        printf("bis: start %p min %i max %i nread %i avail %i bsize %i pos %lli size %lli\n",
+        start, min, max, nread, buffer.avail, buffer.size, BufferedInputStream<T>::position, BufferedInputStream<T>::size);
+        printf("buf: start %p readpos %p marpos %p\n", buffer.start, buffer.readPos, buffer.markPos);
+    }*/
+
+    BufferedInputStream<T>::position += nread;
+    if (BufferedInputStream<T>::status == Ok && buffer.avail == 0
+            && finishedWritingToBuffer) {
+        BufferedInputStream<T>::status = Eof;
+        // save one call to read() by already returning -1 if no data is there
+        if (nread == 0) nread = -1;
+    }
+    return nread;
+}
+template <class T>
+int64_t
+BufferedInputStream<T>::mark(int32_t readlimit) {
+    buffer.mark(readlimit);
+    return StreamBase<T>::position;
+}
+template <class T>
+int64_t
+BufferedInputStream<T>::reset(int64_t newpos) {
+    if (StreamBase<T>::status == Error) return -2;
+    // check to see if we have this position
+    int64_t d = BufferedInputStream<T>::position - newpos;
+    if (buffer.readPos - d >= buffer.start && -d < buffer.avail) {
+        BufferedInputStream<T>::position -= d;
+        buffer.avail += d;
+        buffer.readPos -= d;
+        StreamBase<T>::status = Ok;
+    }
+    return StreamBase<T>::position;
+}
+template <class T>
+int64_t
+BufferedInputStream<T>::skip(int64_t ntoskip) {
+    const T *begin;
+    int32_t nread;
+    int64_t skipped = 0;
+    while (ntoskip) {
+        int32_t step = (int32_t)((ntoskip > buffer.size) ?buffer.size :ntoskip);
+        nread = read(begin, 1, step);
+        if (nread <= 0) {
+            return skipped;
+        }
+        ntoskip -= nread;
+        skipped += nread;
+    }
+    return skipped;
+}
+}
+
+#endif

Added: trunk/clucene/src/CLucene/util/fileinputstream.cpp
===================================================================
--- trunk/clucene/src/CLucene/util/fileinputstream.cpp	2006-06-26 00:39:24 UTC (rev 428)
+++ trunk/clucene/src/CLucene/util/fileinputstream.cpp	2006-06-26 01:33:27 UTC (rev 429)
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2003-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "jstreamsconfig.h"
+#include "fileinputstream.h"
+#include <cerrno>
+#include <cstring>
+using namespace jstreams;
+
+const int32_t FileInputStream::defaultBufferSize = 1048576;
+FileInputStream::FileInputStream(const char *filepath, int32_t buffersize) {
+
+    // try to open the file for reading
+    file = fopen(filepath, "rb");
+    this->filepath = filepath;
+    if (file == 0) {
+        // handle error
+        error = "Could not read file '";
+        error += filepath;
+        error += "': ";
+	error += strerror(errno);
+        status = Error;
+        return;
+    }
+    // determine file size. if the stream is not seekable, the size will be -1
+    fseek(file, 0, SEEK_END);
+    size = ftell(file);
+    fseek(file, 0, SEEK_SET);
+
+    // if the file has size 0, make sure that it's really empty
+    // this is useful for filesystems like /proc that report files as size 0
+    // for files that do contain content
+    if (size == 0) {
+        char dummy[1];
+        size_t n = fread(dummy, 1, 1, file);
+        if (n == 1) {
+            size = -1;
+            fseek(file, 0, SEEK_SET);
+        } else {
+            fclose(file);
+            file = 0;
+            return;
+        }
+    }
+
+    // allocate memory in the buffer
+    mark(buffersize);
+}
+FileInputStream::~FileInputStream() {
+    if (file) {
+        if (fclose(file)) {
+            // handle error
+            error = "Could not close file '" + filepath + "'.";
+        }
+    }
+}
+int32_t
+FileInputStream::fillBuffer(char* start, int32_t space) {
+    if (file == 0) return -1;
+    // read into the buffer
+    int32_t nwritten = fread(start, 1, space, file);
+    // check the file stream status
+    if (ferror(file)) {
+        error = "Could not read from file '" + filepath + "'.";
+        fclose(file);
+        file = 0;
+        status = Error;
+        return -1;
+    }
+    if (feof(file)) {
+        fclose(file);
+        file = 0;
+    }
+    return nwritten;
+}

Added: trunk/clucene/src/CLucene/util/fileinputstream.h
===================================================================
--- trunk/clucene/src/CLucene/util/fileinputstream.h	2006-06-26 00:39:24 UTC (rev 428)
+++ trunk/clucene/src/CLucene/util/fileinputstream.h	2006-06-26 01:33:27 UTC (rev 429)
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2003-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef FILEINPUTSTREAM_H
+#define FILEINPUTSTREAM_H
+
+#include "bufferedstream.h"
+
+namespace jstreams {
+
+class FileInputStream : public BufferedInputStream<char> {
+private:
+    FILE *file;
+    std::string filepath;
+
+public:
+    static const int32_t defaultBufferSize;
+    FileInputStream(const char *filepath, int32_t buffersize=defaultBufferSize);
+    ~FileInputStream();
+    int32_t fillBuffer(char* start, int32_t space);
+};
+
+} // end namespace jstreams
+
+#endif
+

Added: trunk/clucene/src/CLucene/util/inputstreambuffer.h
===================================================================
--- trunk/clucene/src/CLucene/util/inputstreambuffer.h	2006-06-26 00:39:24 UTC (rev 428)
+++ trunk/clucene/src/CLucene/util/inputstreambuffer.h	2006-06-26 01:33:27 UTC (rev 429)
@@ -0,0 +1,176 @@
+/**
+ * Copyright 2003-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INPUTSTREAMBUFFER_H
+#define INPUTSTREAMBUFFER_H
+
+#include <cstdlib>
+
+namespace jstreams {
+
+template <class T>
+class InputStreamBuffer {
+private:
+public:
+    T* start;
+    int32_t size;
+    T* readPos;
+    int32_t avail;
+    T* markPos;
+    int32_t markLimit;
+
+    InputStreamBuffer();
+    ~InputStreamBuffer();
+    void setSize(int32_t size);
+    void mark(int32_t readlimit);
+    void reset();
+    int32_t read(const T*& start, int32_t max=0);
+
+    /**
+     * This function prepares the buffer for a new write.
+     * returns the number of available places.
+     **/
+     int32_t makeSpace(int32_t needed);
+};
+
+template <class T>
+InputStreamBuffer<T>::InputStreamBuffer() {
+    markPos = readPos = start = 0;
+    size = avail = 0;
+}
+template <class T>
+InputStreamBuffer<T>::~InputStreamBuffer() {
+    free(start);
+}
+template <class T>
+void
+InputStreamBuffer<T>::setSize(int32_t size) {
+    // store pointer information
+    int32_t offset = readPos - start;
+    int32_t markOffset = (markPos) ? markPos - start : -1;
+
+    // allocate memory in the buffer
+    start = (T*)realloc(start, size*sizeof(T));
+    this->size = size;
+
+    // restore pointer information
+    readPos = start + offset;
+    markPos = (markOffset == -1) ?0 :start + markOffset;
+}
+template <class T>
+void
+InputStreamBuffer<T>::mark(int32_t limit) {
+    // if there's no buffer yet, allocate one now
+    if (start == 0) {
+        setSize(limit+1);
+    }
+    // if we had a larger limit defined for the same position, do nothing
+    if (readPos == markPos && limit <= markLimit) {
+        return;
+    }
+            
+    markLimit = limit;
+    // if we have enough room, only set the mark
+    int32_t offset = readPos - start;
+    if (size - offset >= limit) {
+        markPos = readPos;
+        return;
+    }
+
+    // if we don't have enough room start by
+    // moving memory to the start of the buffer
+    if (readPos != start) {
+        memmove(start, readPos, avail*sizeof(T));
+        readPos = start;
+    }
+
+    // if we have enough room now, finish
+    if (size >= limit) {
+        markPos = readPos;
+        return;
+    }
+
+    // last resort: increase buffer size
+    setSize(limit+1);
+    markPos = readPos;
+}
+template <class T>
+void
+InputStreamBuffer<T>::reset() {
+    if (markPos != 0) {
+        avail += readPos - markPos;
+        readPos = markPos;
+    }
+}
+template <class T>
+int32_t
+InputStreamBuffer<T>::makeSpace(int32_t needed) {
+    // determine how much space is available for writing
+    int32_t space = size - (readPos - start) - avail;
+    if (space >= needed) {
+        // there's enough space
+        return space;
+    }
+
+    if (markPos && readPos - markPos <= markLimit) {
+        // move data to the start of the buffer while respecting the set mark
+        if (markPos != start) {
+//            printf("moving with mark\n");
+            int32_t n = avail + readPos - markPos;
+            memmove(start, markPos, n*sizeof(T));
+            readPos -= markPos - start;
+            space += markPos - start;
+            markPos = start;
+        }
+    } else if (avail) {
+        if (readPos != start) {
+//            printf("moving\n");
+            // move data to the start of the buffer
+            memmove(start, readPos, avail*sizeof(T));
+            space += readPos - start;
+            readPos = start;
+            markPos = 0;
+        }
+    } else {
+        // we may start writing at the start of the buffer
+        markPos = 0;
+        readPos = start;
+        space = size;
+    }
+    if (space >= needed) {
+        // there's enough space now
+        return space;
+    }
+
+    // still not enough space, we have to allocate more
+//    printf("resize %i %i %i %i %i\n", avail, needed, space, size + needed - space, size);
+    setSize(size + needed - space);
+    return needed;
+}
+template <class T>
+int32_t
+InputStreamBuffer<T>::read(const T*& start, int32_t max) {
+    start = readPos;
+    if (max <= 0 || max > avail) {
+        max = avail;
+    }
+    readPos += max;
+    avail -= max;
+    return max;
+}
+
+} // end namespace jstreams
+
+#endif



More information about the sword-cvs mailing list