/* AbiSource Program Utilities * Copyright (C) 1998 AbiSource, Inc. * * 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 #include #include #include "ut_assert.h" #include "ut_types.h" #include "ut_bytebuf.h" #include "ut_go_file.h" #include #define DEFAULT_CHUNK 1024 #define MIN_CHUNK 256 UT_ByteBuf::UT_ByteBuf(UT_uint32 iChunk) : m_pBuf(0), m_iSize(0), m_iSpace(0) { if (iChunk < MIN_CHUNK) iChunk = DEFAULT_CHUNK; m_iChunk = iChunk; // we defer the g_try_malloc until the first use. } UT_ByteBuf::~UT_ByteBuf() { FREEP(m_pBuf); } bool UT_ByteBuf::_byteBuf(UT_uint32 spaceNeeded) { // expand the buffer if necessary to accomidate the requested space. // round up to the next multiple of the chunk size. UT_uint32 newSize = ((m_iSize+spaceNeeded+m_iChunk-1)/m_iChunk)*m_iChunk; UT_Byte * pNew = static_cast(UT_calloc(newSize,sizeof(*m_pBuf))); if (!pNew) return false; if (m_pBuf) { memmove(pNew,m_pBuf,m_iSize*sizeof(*m_pBuf)); g_free(m_pBuf); } m_pBuf = pNew; m_iSpace = newSize; return true; } bool UT_ByteBuf::append(const UT_Byte * pValue, UT_uint32 length) { return ins(m_iSize,pValue,length); } bool UT_ByteBuf::ins(UT_uint32 position, const UT_Byte * pValue, UT_uint32 length) { // insert the given buffer into the bytebuf if (!length) { UT_ASSERT(!pValue); return true; } UT_ASSERT(pValue); if (m_iSpace-m_iSize < length) if (!_byteBuf(length)) return false; if (m_iSize > position) memmove(m_pBuf+position+length,m_pBuf+position,(m_iSize-position)*sizeof(*m_pBuf)); m_iSize += length; memmove(m_pBuf+position,pValue,length*sizeof(*m_pBuf)); return true; } bool UT_ByteBuf::ins(UT_uint32 position, UT_uint32 length) { // insert zeroed space into the bytebuf if (!length) return true; if (m_iSpace-m_iSize < length) if (!_byteBuf(length)) return false; if (m_iSize > position) memmove(m_pBuf+position+length,m_pBuf+position,(m_iSize-position)*sizeof(*m_pBuf)); m_iSize += length; memset(m_pBuf+position,0,length*sizeof(*m_pBuf)); return true; } bool UT_ByteBuf::del(UT_uint32 position, UT_uint32 amount) { if (!amount) return true; if (!m_pBuf) return false; UT_ASSERT(position < m_iSize); UT_ASSERT(position+amount <= m_iSize); memmove(m_pBuf+position,m_pBuf+position+amount,(m_iSize-position-amount)*sizeof(*m_pBuf)); m_iSize -= amount; UT_uint32 newSpace = ((m_iSize+m_iChunk-1)/m_iChunk)*m_iChunk; //Calculate the new space needed if (newSpace != m_iSpace) { m_pBuf = static_cast(g_try_realloc(m_pBuf, newSpace*sizeof(*m_pBuf))); //Re-allocate to the smaller size m_iSpace = newSpace; //update m_iSpace to the new figure } return true; } UT_uint32 UT_ByteBuf::getLength(void) const { // return the number of items in the buffer return m_iSize; } const UT_Byte * UT_ByteBuf::getPointer(UT_uint32 position) const { // return a read-only pointer to the buffer if (!m_pBuf || !m_iSize) return 0; UT_ASSERT(position < m_iSize); return m_pBuf+position; } bool UT_ByteBuf::overwrite(UT_uint32 position, const UT_Byte * pValue, UT_uint32 length) { // overwrite the current cells at the given position for the given length. if (!length) { UT_ASSERT(!pValue); return true; } UT_ASSERT(pValue); if (m_iSpace < position+length) if (!_byteBuf(position+length-m_iSpace)) return false; memmove(m_pBuf+position,pValue,length*sizeof(*m_pBuf)); return true; } void UT_ByteBuf::truncate(UT_uint32 position) { if (position < m_iSize) m_iSize = position; UT_uint32 newSpace = ((m_iSize+m_iChunk-1)/m_iChunk)*m_iChunk; //Calculate the new space needed if (newSpace != m_iSpace) { m_pBuf = static_cast(g_try_realloc(m_pBuf, newSpace*sizeof(*m_pBuf))); //Re-allocate to the smaller size m_iSpace = newSpace; //update m_iSpace to the new figure } } bool UT_ByteBuf::insertFromURI(UT_uint32 iPosition, const char *szURI) { GsfInput *fp = UT_go_file_open(szURI, NULL); if(!fp) return false; bool res = insertFromInput (iPosition, fp); g_object_unref (fp); return res; } bool UT_ByteBuf::insertFromInput(UT_uint32 iPosition, GsfInput * fp) { UT_return_val_if_fail (fp != NULL, false); UT_uint32 iLengthOfFile = gsf_input_size(fp); // create a lot of space initialized to 0s this->ins (iPosition, iLengthOfFile); UT_Byte *pBuf = m_pBuf + iPosition; gsf_input_read(fp, iLengthOfFile, pBuf); return true; } bool UT_ByteBuf::insertFromFile(UT_uint32 iPosition, FILE * fp) { UT_uint32 iLengthOfFile = ftell (fp); if (0 != fseek(fp, 0, SEEK_SET)) { return false; } // create a lot of space initialized to 0s this->ins (iPosition, iLengthOfFile); UT_Byte *pBuf = m_pBuf + iPosition; UT_uint32 iBytesRead = 0; while (iBytesRead < iLengthOfFile) { iBytesRead += fread (pBuf + iBytesRead, sizeof(UT_Byte), iLengthOfFile - iBytesRead, fp); } return true; } bool UT_ByteBuf::insertFromFile(UT_uint32 iPosition, const char* pszFileName) { UT_ASSERT(pszFileName && pszFileName[0]); FILE* fp = fopen(pszFileName, "rb"); if (!fp) { return false; } if (0 != fseek(fp, 0, SEEK_END)) { fclose(fp); return false; } bool b = this->insertFromFile (iPosition, fp); fclose(fp); return b; } bool UT_ByteBuf::writeToFile(const char* pszFileName) const { UT_ASSERT(pszFileName && pszFileName[0]); if (!strncmp (pszFileName, "file://", 7)) pszFileName += 7; FILE* fp = fopen(pszFileName, "wb"); if (!fp) { return false; } UT_uint32 iBytesWritten = fwrite(m_pBuf, 1, m_iSize, fp); if (iBytesWritten != m_iSize) { fclose(fp); return false; } fclose(fp); return true; } bool UT_ByteBuf::writeToURI(const char* pszURI) const { UT_ASSERT(pszURI && pszURI[0]); GsfOutput *fp = UT_go_file_create(pszURI, NULL); if (!fp) return false; gboolean res = gsf_output_write(fp, m_iSize, (guint8*)m_pBuf); gsf_output_close(fp); g_object_unref(G_OBJECT(fp)); return static_cast(res); }