[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