📄 engine.cpp
字号:
// Copyright (C) 1999-2005 Open Source Telecom Corporation.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by// the GNU General Public License. //// This exception applies only to the code released under the name GNU// Common C++. If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way. To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include <cc++/config.h>#include <cc++/string.h>#include <cc++/exception.h>#if !defined(_MSC_VER) || _MSC_VER >= 1300#include <cc++/export.h>#include <cc++/persist.h>#ifndef HAVE_EXCEPTION#include "assert.h"#endif#ifdef CCXX_NAMESPACESnamespace ost {using namespace std;#endif#ifndef NO_COMPRESSIONconst uint32 MAX_BUFFER = 16384;#endif#ifdef CCXX_EXCEPTIONSEngine::Exception::Exception(const String &reason): PersistException(reason) {}#endif/** * NullObject is a const uint32 which is the ID streamed to disk * if an attempt to stream a NULL Persistence::BaseObject or * Derivative is made... */const uint32 NullObject = 0xffffffff;Engine::Engine(std::iostream& stream, EngineMode mode) THROWS (PersistException) : myUnderlyingStream(stream), myOperationalMode(mode){ // Nothing else to initialise for now#ifndef NO_COMPRESSION myZStream.zalloc = (alloc_func)NULL; myZStream.zfree = (free_func)NULL; myZStream.opaque = (voidpf)NULL; myCompressedDataBuffer = new uint8[MAX_BUFFER]; myUncompressedDataBuffer = new uint8[MAX_BUFFER]; myLastUncompressedDataRead = myUncompressedDataBuffer; if (myOperationalMode == modeRead) { myZStream.next_in = myCompressedDataBuffer; myZStream.next_out = myUncompressedDataBuffer; myZStream.avail_in = 0; myZStream.avail_out = MAX_BUFFER; int err = inflateInit(&myZStream); if (err != Z_OK) { THROW (PersistException(String("zLib didn't initialise for inflating."))); } } else { myZStream.next_in = myUncompressedDataBuffer; myZStream.next_out = myCompressedDataBuffer; myZStream.avail_in = 0; myZStream.avail_out = MAX_BUFFER; int err = deflateInit(&myZStream,9); // TODO: tweak compression level if (err != Z_OK) { THROW ( PersistException(String("zLib didn't initialise for deflating."))); } }#endif}void Engine::sync(){ // Flush compression buffers etc here.#ifndef NO_COMPRESSION if (myOperationalMode == modeRead) { inflateEnd(&myZStream); } else { int zret = Z_OK; while (myZStream.avail_in > 0 || zret == Z_OK) { zret = deflate(&myZStream,Z_FINISH); if (myZStream.avail_out >= 0) { myUnderlyingStream.write((char*)myCompressedDataBuffer,MAX_BUFFER - myZStream.avail_out); myZStream.next_out = myCompressedDataBuffer; myZStream.avail_out = MAX_BUFFER; } } deflateEnd(&myZStream); }#endif}Engine::~Engine(){ if (myUnderlyingStream.good()) sync();#ifndef NO_COMPRESSION delete [] myCompressedDataBuffer; delete [] myUncompressedDataBuffer;#endif}void Engine::writeBinary(const uint8* data, const uint32 size) THROWS (Engine::Exception){ if(myOperationalMode != modeWrite) THROW("Cannot write to an input Engine");#ifdef NO_COMPRESSION myUnderlyingStream.write((const char *)data,size);#else // Compress the data here and doit :) uint32 written = 0; while (written < size) { // transfer as much information as we can into the input buffer. if (myZStream.avail_in < MAX_BUFFER) { uint32 toAdd = size - written; if (toAdd > (MAX_BUFFER - myZStream.avail_in)) toAdd = (MAX_BUFFER - myZStream.avail_in); memcpy(myZStream.next_in + myZStream.avail_in, data+written,toAdd); written += toAdd; myZStream.avail_in += toAdd; } if (myZStream.avail_in < MAX_BUFFER) return; // We have not filled the buffer, so let's carry on streaming // We have a full input buffer, so we compressit. while (myZStream.avail_in > 0) { deflate(&myZStream,0); if (myZStream.avail_out == 0) { // We filled the output buffer, let's stream it myUnderlyingStream.write((char*)myCompressedDataBuffer,MAX_BUFFER); myZStream.next_out = myCompressedDataBuffer; myZStream.avail_out = MAX_BUFFER; } // Repeat whilst the input buffer isn't flushed } // Now we have flushed the input buffer we can reset it myZStream.avail_in = 0; myZStream.next_in = myUncompressedDataBuffer; }#endif}void Engine::readBinary(uint8* data, uint32 size) THROWS (Engine::Exception){ if(myOperationalMode != modeRead) THROW("Cannot read from an output Engine");#ifdef NO_COMPRESSION myUnderlyingStream.read((char *)data,size);#else uint32 read = 0; while (read < size) { // If we have any data left in the uncompressed buffer - use it if (myLastUncompressedDataRead < myZStream.next_out) { uint32 toRead = size - read; if (toRead > (uint32)(myZStream.next_out - myLastUncompressedDataRead)) toRead = (myZStream.next_out - myLastUncompressedDataRead); memcpy(data+read,myLastUncompressedDataRead,toRead); myLastUncompressedDataRead += toRead; read += toRead; } if (read == size) return; // We have read all we need to // Reset the stream for the next block of data myLastUncompressedDataRead = myUncompressedDataBuffer; myZStream.next_out = myUncompressedDataBuffer; myZStream.avail_out = MAX_BUFFER; // Next we have to deal such that, until we have a full output buffer, // (Or we run out of input) if (myUnderlyingStream.good()) { while (myUnderlyingStream.good() && myZStream.avail_out > 0) { // Right then, if we have run out of input, fetch another chunk if (myZStream.avail_in == 0) { myZStream.next_in = myCompressedDataBuffer; myUnderlyingStream.read((char*)myCompressedDataBuffer,MAX_BUFFER); myZStream.avail_in = myUnderlyingStream.gcount(); } inflate(&myZStream,0); } } else { // Oh dear - we ran out of input on the buffer. // Maybe we can still inflate some inflate(&myZStream,0); if (myZStream.avail_out == MAX_BUFFER)// THROW (PersistException(String("Oh dear - ran out of input"))); THROW (Exception(String("Oh dear - ran out of input"))); } }#endif}/* * note, does not (yet?) throw an exception, but interface * prepared .. */void Engine::write(const BaseObject *object) THROWS (Engine::Exception){ // Pre-step, if object is NULL, then don't serialise it - serialise a // marker to say that it is null. // as ID's are uint32's, NullObject will do nicely for the task if (object == NULL) { uint32 id = NullObject; write(id);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -