#ifndef BZS_DB_BLOBBUFFER_H #define BZS_DB_BLOBBUFFER_H /*================================================================= Copyright (C) 2013 BizStation Corp All rights reserved. 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. =================================================================*/ #include <boost/noncopyable.hpp> #include "IBlobBuffer.h" #include <assert.h> #include <boost/shared_array.hpp> #define FILE_MAP_SIZE 3145728-1024//3M namespace bzs { namespace db { static const char nullbyte[2] = {0x00}; /** holds blob ptr and make boost multiplebuffer */ class blobBuffer : public IblobBuffer, private boost::noncopyable { std::vector<blob> m_blobs; blobHeader m_bh; std::vector<boost::shared_array<unsigned char> > m_strings; public: blobBuffer(){m_bh.fieldCount = 0;} const blobHeader* getHeader()const {return &m_bh;}; void clear() { m_blobs.clear(); m_bh.fieldCount = 0; m_bh.rows=0; m_strings.clear(); } size_t blobs(){return m_blobs.size();}; /** * @param dataPtr blob data body pointer in result record image. */ void addBlob(unsigned int bloblen, unsigned short fieldNum, const unsigned char* dataPtr) { unsigned char* p = new unsigned char[bloblen]; m_strings.push_back(boost::shared_array<unsigned char>(p)); memcpy(p, dataPtr, bloblen); m_blobs.push_back(blob(bloblen, fieldNum, p)); } void addBlob(const blob& b) { m_blobs.push_back(b); } void setFieldCount(unsigned int v){m_bh.fieldCount=v;}; unsigned int fieldCount(){return m_bh.fieldCount;} /** Make boost::asio::multibuffer<const_buffer> from added blob. * and write offset to record image of blob fields. * @image pointer of normal result image. * @size bytes of normal result image length. * @return * result buffer image * --------------------------- * n record image * 2 fieldNum * 4 dataLength * n(dataLength) data * 2 null terminate * 2 fieldNum ... * ---------------------------- */ unsigned int makeMultiBuffer(std::vector<boost::asio::const_buffer>& mbuffer) { unsigned int size = 0; if (m_bh.fieldCount) { //write buffer header m_bh.rows = (unsigned short)(m_blobs.size()/m_bh.fieldCount); mbuffer.push_back(boost::asio::buffer((char*)&m_bh, sizeof(blobHeader))); size += sizeof(blobHeader); for (size_t i=0;i<m_blobs.size();i++) { const blob& b = m_blobs[i]; //add field desc mbuffer.push_back(boost::asio::buffer((char*)&b.bf, sizeof(blobField))); size += sizeof(blobField); //add field body mbuffer.push_back(boost::asio::buffer(b.ptr, b.bf.size)); //add null terminate mbuffer.push_back(boost::asio::buffer(nullbyte, 2)); //update record image pointer to offset from record start size += b.bf.size + 2; } } return size; } /** Copy to single buffer. * this is use for pipe server only. * @param stat [out] return additional status. ex. STATUS_BUFFERTOOSMALL * @return length of written by this function. * result buffer image * --------------------------- * n record image * 2 fieldNum * 4 dataLength * n(dataLength) data * 2 null terminate * 2 fieldNum ... * ---------------------------- */ unsigned int writeBuffer(unsigned char* buffer, unsigned int maxsize, int& stat) { stat = 0; unsigned char* p = buffer;// + offset ; if (m_bh.fieldCount) { //write buffer header m_bh.rows = (unsigned short)(m_blobs.size()/m_bh.fieldCount); memcpy(p, &m_bh, sizeof(blobHeader)); p += sizeof(blobHeader); for (size_t i=0;i<m_blobs.size();i++) { const blob& b = m_blobs[i]; if (maxsize > (p - buffer) + b.bf.size + 2) { //write field desc memcpy(p, &b.bf, sizeof(blobField)); p += sizeof(blobField); //write field body memcpy(p, b.ptr, b.bf.size); //write null terminate p += b.bf.size; memcpy(p, nullbyte, 2); p += 2; }else { stat = STATUS_BUFFERTOOSMALL; break; } } } return(unsigned int)(p - buffer); } }; }//namespace db }//namespace bzs #endif //BZS_DB_BLOBBUFFER_H