/* * Copyright (C) 2007-2019 Xagasoft, All rights reserved. * * This file is part of the libbu++ library and is released under the * terms of the license contained in the file LICENSE. */ #ifndef BU_BLOB_BUILDER_H #define BU_BLOB_BUILDER_H #include "bu/config.h" #include "bu/sharedcore.h" namespace Bu { class Blob; class BlobBuilder; /** @cond DEVEL */ class BlobBuilderCore { friend class BlobBuilder; friend class SharedCore; private: class Chunk { public: Chunk( const char *pSrc, int32_t iLength ); ~Chunk(); void append( const char *&pSrc, int32_t &iLength ); /** * Splits this chunk into two chunks, and fixes the links. *@param iIndex The first byte to be in the new chunk, if this is * zero or less then it has no effect. *@returns A pointer to the new chunk, or null if no work was * done. */ Chunk *split( int32_t iIndex ); int32_t iLength; char *pData; Chunk *pNext; }; BlobBuilderCore(); BlobBuilderCore( const BlobBuilderCore &rSrc ); virtual ~BlobBuilderCore(); void clear(); void append( const char *pSrc, int32_t iLength ); void prepend( const char *pSrc, int32_t iLength ); void insert( int32_t iBefore, const char *pSrc, int32_t iLength ); void set( const char *pSrc, int32_t iLength ); void copyTo( void *pDestRaw, int32_t iLength ) const; char getAt( int32_t iIndex ) const; Chunk *pFirst; Chunk *pLast; int32_t iLength; }; /** @endcond */ /** * This makes creating a Blob piece at a time easy and fast. You can * append, prepend, or insert with reasonable efficiency. The underlying * data structure is currently a linked list, and the individual links are * actually block allocated memory. If an amount of data is appended that * is less than the minimum page size then the minimum page size is * allocated. Subsequent appends will share that allocated buffer until it * is full, at which point a new buffer will be created. If an amount * greater than the minimum page size is appended then any extra space in * the last buffer is used, and then the rest is placed in a single buffer. * At most one buffer will be allocated for any given append or prepend * operation. Due to the nature of insert, up to two buffers could be * allocated. * * Insert operations will take O(N) time to find the location to insert to * in the linked list, at that point the foud chunk will be split into two * and the new data will be added at the new location. This will also * attempt to share the existing buffers, but if there's extra it will * allocate a new buffer for the remaining data. */ class BlobBuilder : public Bu::SharedCore { protected: using SharedCore::core; using SharedCore::_hardCopy; public: BlobBuilder(); BlobBuilder( const Blob &rSrc ); BlobBuilder( const BlobBuilder &rSrc ); virtual ~BlobBuilder(); void set( const Blob &rSrc ); void set( const char *pSrc, int32_t iLength ); void set( const char *pSrc ); void append( const Blob &rSrc ); void append( const char *pSrc, int32_t iLength ); void append( const char *pSrc ); void prepend( const Blob &rSrc ); void prepend( const char *pSrc, int32_t iLength ); void prepend( const char *pSrc ); void insert( int32_t iBefore, const Blob &rSrc ); void insert( int32_t iBefore, const char *pSrc, int32_t iLength ); void insert( int32_t iBefore, const char *pSrc ); void clear(); int32_t getSize() const; Blob getBlob() const; void copyTo( void *pDestRaw, int32_t iDestSize ) const; char operator[]( int32_t iIndex ) const; BlobBuilder &operator=( const Blob &rSrc ); BlobBuilder &operator=( const char *pSrc ); BlobBuilder &operator=( const char chr ); BlobBuilder &operator+=( const Blob &rSrc ); BlobBuilder &operator+=( const char *pSrc ); BlobBuilder &operator+=( const char chr ); private: }; }; #endif