1//
2// LOB.h
3//
4// Library: Data
5// Package: DataCore
6// Module: LOB
7//
8// Definition of the LOB class.
9//
10// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Data_LOB_INCLUDED
18#define Data_LOB_INCLUDED
19
20
21#include "Poco/Data/Data.h"
22#include "Poco/SharedPtr.h"
23#include "Poco/Dynamic/VarHolder.h"
24#include "Poco/Exception.h"
25#include <vector>
26#include <algorithm>
27
28
29namespace Poco {
30namespace Data {
31
32
33template <typename T>
34class LOB
35 /// Representation of a Large OBject.
36 ///
37 /// A LOB can hold arbitrary data.
38 /// The maximum size depends on the underlying database.
39 ///
40 /// The LOBInputStream and LOBOutputStream classes provide
41 /// a convenient way to access the data in a LOB.
42{
43public:
44 typedef typename std::vector<T>::const_iterator Iterator;
45 typedef T ValueType;
46 typedef typename std::vector<T> Container;
47 typedef Poco::SharedPtr<Container> ContentPtr;
48
49 LOB(): _pContent(new std::vector<T>())
50 /// Creates an empty LOB.
51 {
52 }
53
54 LOB(const std::vector<T>& rContent):
55 _pContent(new std::vector<T>(rContent))
56 /// Creates the LOB, content is deep-copied.
57 {
58 }
59
60 LOB(const T* const pContent, std::size_t objectSize):
61 _pContent(new std::vector<T>(pContent, pContent + objectSize))
62 /// Creates the LOB by deep-copying pContent.
63 {
64 }
65
66 LOB(const std::basic_string<T>& rContent):
67 _pContent(new std::vector<T>(rContent.begin(), rContent.end()))
68 /// Creates a LOB from a string.
69 {
70 }
71
72 LOB(const LOB& other): _pContent(other._pContent)
73 /// Creates a LOB by copying another one.
74 {
75 }
76
77 ~LOB()
78 /// Destroys the LOB.
79 {
80 }
81
82 LOB& operator = (const LOB& other)
83 /// Assignment operator.
84 {
85 LOB tmp(other);
86 swap(tmp);
87 return *this;
88 }
89
90 bool operator == (const LOB& other) const
91 /// Compares for equality LOB by value.
92 {
93 return *_pContent == *other._pContent;
94 }
95
96 bool operator != (const LOB& other) const
97 /// Compares for inequality LOB by value.
98 {
99 return *_pContent != *other._pContent;
100 }
101
102 void swap(LOB& other)
103 /// Swaps the LOB with another one.
104 {
105 using std::swap;
106 swap(_pContent, other._pContent);
107 }
108
109 const std::vector<T>& content() const
110 /// Returns the content.
111 {
112 return *_pContent;
113 }
114
115 const T* rawContent() const
116 /// Returns the raw content.
117 ///
118 /// If the LOB is empty, returns NULL.
119 {
120 if (_pContent->empty())
121 return 0;
122 else
123 return &(*_pContent)[0];
124 }
125
126 void assignVal(std::size_t count, const T& val)
127 /// Assigns raw content to internal storage.
128 {
129 ContentPtr tmp = new Container(count, val);
130 _pContent.swap(tmp);
131 }
132
133 void assignRaw(const T* ptr, std::size_t count)
134 /// Assigns raw content to internal storage.
135 {
136 poco_assert_dbg (ptr);
137 LOB tmp(ptr, count);
138 swap(tmp);
139 }
140
141 void appendRaw(const T* pChar, std::size_t count)
142 /// Assigns raw content to internal storage.
143 {
144 poco_assert_dbg (pChar);
145 _pContent->insert(_pContent->end(), pChar, pChar+count);
146 }
147
148 void clear(bool doCompact = false)
149 /// Clears the content of the blob.
150 /// If doCompact is true, trims the excess capacity.
151 {
152 _pContent->clear();
153 if (doCompact) compact();
154 }
155
156 void compact()
157 /// Trims the internal storage excess capacity.
158 {
159 std::vector<T>(*_pContent).swap(*_pContent);
160 }
161
162 Iterator begin() const
163 {
164 return _pContent->begin();
165 }
166
167 Iterator end() const
168 {
169 return _pContent->end();
170 }
171
172 std::size_t size() const
173 /// Returns the size of the LOB in bytes.
174 {
175 return static_cast<std::size_t>(_pContent->size());
176 }
177
178private:
179 ContentPtr _pContent;
180};
181
182
183typedef LOB<unsigned char> BLOB;
184typedef LOB<char> CLOB;
185
186
187//
188// inlines
189//
190
191template <typename T>
192inline void swap(LOB<T>& b1, LOB<T>& b2)
193{
194 b1.swap(b2);
195}
196
197
198} } // namespace Poco::Data
199
200
201namespace std
202{
203 template<>
204 inline void swap<Poco::Data::BLOB>(Poco::Data::BLOB& b1,
205 Poco::Data::BLOB& b2)
206 /// Full template specialization of std:::swap for BLOB
207 {
208 b1.swap(b2);
209 }
210
211 template<>
212 inline void swap<Poco::Data::CLOB>(Poco::Data::CLOB& c1,
213 Poco::Data::CLOB& c2)
214 /// Full template specialization of std:::swap for CLOB
215 {
216 c1.swap(c2);
217 }
218}
219
220
221//
222// VarHolderImpl<LOB>
223//
224
225
226namespace Poco {
227namespace Dynamic {
228
229
230template <>
231class VarHolderImpl<Poco::Data::BLOB>: public VarHolder
232{
233public:
234 VarHolderImpl(const Poco::Data::BLOB& val): _val(val)
235 {
236 }
237
238 ~VarHolderImpl()
239 {
240 }
241
242 const std::type_info& type() const
243 {
244 return typeid(Poco::Data::BLOB);
245 }
246
247 void convert(std::string& val) const
248 {
249 val.assign(_val.begin(), _val.end());
250 }
251
252 VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
253 {
254 return cloneHolder(pVarHolder, _val);
255 }
256
257 const Poco::Data::BLOB& value() const
258 {
259 return _val;
260 }
261
262private:
263 VarHolderImpl();
264 Poco::Data::BLOB _val;
265};
266
267
268template <>
269class VarHolderImpl<Poco::Data::CLOB>: public VarHolder
270{
271public:
272 VarHolderImpl(const Poco::Data::CLOB& val): _val(val)
273 {
274 }
275
276 ~VarHolderImpl()
277 {
278 }
279
280 const std::type_info& type() const
281 {
282 return typeid(Poco::Data::CLOB);
283 }
284
285 void convert(std::string& val) const
286 {
287 val.assign(_val.begin(), _val.end());
288 }
289
290 VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
291 {
292 return cloneHolder(pVarHolder, _val);
293 }
294
295 const Poco::Data::CLOB& value() const
296 {
297 return _val;
298 }
299
300private:
301 VarHolderImpl();
302 Poco::Data::CLOB _val;
303};
304
305
306} } // namespace Poco::Dynamic
307
308
309#endif // Data_LOB_INCLUDED
310