/*------------------------------------------------------------------------------
* 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 "IndexOutput.h"
CL_NS_USE(util)
CL_NS_DEF(store)
IndexOutput::IndexOutput()
{
}
IndexOutput::~IndexOutput(){
}
BufferedIndexOutput::BufferedIndexOutput()
{
buffer = _CL_NEWARRAY(uint8_t, BUFFER_SIZE );
bufferStart = 0;
bufferPosition = 0;
}
BufferedIndexOutput::~BufferedIndexOutput(){
if ( buffer != NULL )
{
_CLDELETE_ARRAY( buffer );
bufferStart = 0;
bufferPosition = 0;
}
}
void BufferedIndexOutput::close(){
flush();
_CLDELETE_ARRAY( buffer );
bufferStart = 0;
bufferPosition = 0;
}
void BufferedIndexOutput::writeByte(const uint8_t b) {
CND_PRECONDITION(buffer!=NULL,"IndexOutput is closed")
if (bufferPosition >= BUFFER_SIZE)
flush();
buffer[bufferPosition++] = b;
}
void BufferedIndexOutput::writeBytes(const uint8_t* b, const int32_t length) {
if ( length < 0 )
_CLTHROWA(CL_ERR_IllegalArgument, "IO Argument Error. Value must be a positive value.");
int32_t bytesLeft = BUFFER_SIZE - bufferPosition;
// is there enough space in the buffer?
if (bytesLeft >= length) {
// we add the data to the end of the buffer
memcpy(buffer + bufferPosition, b, length);
bufferPosition += length;
// if the buffer is full, flush it
if (BUFFER_SIZE - bufferPosition == 0)
flush();
} else {
// is data larger then buffer?
if (length > BUFFER_SIZE) {
// we flush the buffer
if (bufferPosition > 0)
flush();
// and write data at once
flushBuffer(b, length);
bufferStart += length;
} else {
// we fill/flush the buffer (until the input is written)
int64_t pos = 0; // position in the input data
int32_t pieceLength;
while (pos < length) {
if ( length - pos < bytesLeft )
pieceLength = length - pos;
else
pieceLength = bytesLeft;
memcpy(buffer + bufferPosition, b + pos, pieceLength);
pos += pieceLength;
bufferPosition += pieceLength;
// if the buffer is full, flush it
bytesLeft = BUFFER_SIZE - bufferPosition;
if (bytesLeft == 0) {
flush();
bytesLeft = BUFFER_SIZE;
}
}
}
}
}
void IndexOutput::writeInt(const int32_t i) {
writeByte((uint8_t)(i >> 24));
writeByte((uint8_t)(i >> 16));
writeByte((uint8_t)(i >> 8));
writeByte((uint8_t) i);
}
void IndexOutput::writeVInt(const int32_t vi) {
uint32_t i = vi;
while ((i & ~0x7F) != 0) {
writeByte((uint8_t)((i & 0x7f) | 0x80));
i >>= 7; //doing unsigned shift
}
writeByte( (uint8_t)i );
}
void IndexOutput::writeLong(const int64_t i) {
writeInt((int32_t) (i >> 32));
writeInt((int32_t) i);
}
void IndexOutput::writeVLong(const int64_t vi) {
uint64_t i = vi;
while ((i & ~0x7F) != 0) {
writeByte((uint8_t)((i & 0x7f) | 0x80));
i >>= 7; //doing unsigned shift
}
writeByte((uint8_t)i);
}
void IndexOutput::writeString(const TCHAR* s, const int32_t length ) {
writeVInt(length);
writeChars(s, 0, length);
}
void IndexOutput::writeChars(const TCHAR* s, const int32_t start, const int32_t length){
if ( length < 0 || start < 0 )
_CLTHROWA(CL_ERR_IllegalArgument, "IO Argument Error. Value must be a positive value.");
const int32_t end = start + length;
for (int32_t i = start; i < end; ++i) {
const int32_t code = (int32_t)s[i];
if (code >= 0x01 && code <= 0x7F)
writeByte((uint8_t)code);
else if (((code >= 0x80) && (code <= 0x7FF)) || code == 0) {
writeByte((uint8_t)(0xC0 | (code >> 6)));
writeByte((uint8_t)(0x80 | (code & 0x3F)));
} else {
writeByte((uint8_t)(0xE0 | (((uint32_t)code) >> 12))); //unsigned shift
writeByte((uint8_t)(0x80 | ((code >> 6) & 0x3F)));
writeByte((uint8_t)(0x80 | (code & 0x3F)));
}
}
}
int64_t BufferedIndexOutput::getFilePointer() const{
return bufferStart + bufferPosition;
}
void BufferedIndexOutput::seek(const int64_t pos) {
flush();
bufferStart = pos;
}
void BufferedIndexOutput::flush() {
flushBuffer(buffer, bufferPosition);
bufferStart += bufferPosition;
bufferPosition = 0;
}
CL_NS_END