1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/*
* 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<BlobBuilder, BlobBuilderCore>;
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 Bu::Blob &rSrc );
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<BlobBuilder, BlobBuilderCore>
{
protected:
using SharedCore<BlobBuilder, BlobBuilderCore>::core;
using SharedCore<BlobBuilder, BlobBuilderCore>::_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
|