2727#include " Client.h"
2828#include " Transaction.h"
2929#include " fb-api/firebird/impl/inf_pub.h"
30+ #include < cstdint>
31+ #include < cstring>
3032#include < limits>
33+ #include < vector>
3134
3235using namespace fbcpp ;
3336using namespace fbcpp ::impl;
3437
35- namespace
36- {
37- std::pair<unsigned , const unsigned char *> getBpb (const BlobOptions& options)
38- {
39- const auto & bpb = options.getBpb ();
40-
41- if (bpb.size () > std::numeric_limits<unsigned >::max ())
42- throw FbCppException (" BPB too large" );
43-
44- const auto length = static_cast <unsigned >(bpb.size ());
45- const auto data = bpb.empty () ? nullptr : reinterpret_cast <const unsigned char *>(bpb.data ());
46-
47- return {length, data};
48- }
49- } // namespace
50-
51-
5238Blob::Blob (Attachment& attachment, Transaction& transaction, const BlobOptions& options)
5339 : attachment{attachment},
5440 transaction{transaction},
@@ -58,10 +44,10 @@ Blob::Blob(Attachment& attachment, Transaction& transaction, const BlobOptions&
5844 assert (attachment.isValid ());
5945 assert (transaction.isValid ());
6046
61- const auto [bpbLength, bpbData] = getBpb (options);
47+ const auto preparedBpb = prepareBpb (options);
6248
63- handle.reset (
64- attachment. getHandle ()-> createBlob (&statusWrapper, transaction. getHandle (). get ( ), &id. id , bpbLength, bpbData ));
49+ handle.reset (attachment. getHandle ()-> createBlob (&statusWrapper, transaction. getHandle (). get (), &id. id ,
50+ static_cast < unsigned >(preparedBpb. size () ), preparedBpb. data () ));
6551}
6652
6753Blob::Blob (Attachment& attachment, Transaction& transaction, const BlobId& blobId, const BlobOptions& options)
@@ -74,18 +60,55 @@ Blob::Blob(Attachment& attachment, Transaction& transaction, const BlobId& blobI
7460 assert (attachment.isValid ());
7561 assert (transaction.isValid ());
7662
77- const auto [bpbLength, bpbData] = getBpb (options);
63+ const auto preparedBpb = prepareBpb (options);
64+
65+ handle.reset (attachment.getHandle ()->openBlob (&statusWrapper, transaction.getHandle ().get (), &id.id ,
66+ static_cast <unsigned >(preparedBpb.size ()), preparedBpb.data ()));
67+ }
68+
69+ std::vector<std::uint8_t > Blob::prepareBpb (const BlobOptions& options)
70+ {
71+ const auto util = attachment.getClient ().getUtil ();
72+
73+ auto builder = fbUnique (util->getXpbBuilder (&statusWrapper, fb::IXpbBuilder::BPB ,
74+ reinterpret_cast <const std::uint8_t *>(options.getBpb ().data ()),
75+ static_cast <unsigned >(options.getBpb ().size ())));
76+
77+ if (const auto type = options.getType (); type.has_value ())
78+ builder->insertInt (&statusWrapper, isc_bpb_type, static_cast <int >(type.value ()));
79+
80+ if (const auto sourceType = options.getSourceType (); sourceType.has_value ())
81+ builder->insertInt (&statusWrapper, isc_bpb_source_type, static_cast <int >(sourceType.value ()));
82+
83+ if (const auto targetType = options.getTargetType (); targetType.has_value ())
84+ builder->insertInt (&statusWrapper, isc_bpb_target_type, static_cast <int >(targetType.value ()));
85+
86+ if (const auto sourceCharSet = options.getSourceCharSet (); sourceCharSet.has_value ())
87+ builder->insertInt (&statusWrapper, isc_bpb_source_interp, static_cast <int >(sourceCharSet.value ()));
88+
89+ if (const auto targetCharSet = options.getTargetCharSet (); targetCharSet.has_value ())
90+ builder->insertInt (&statusWrapper, isc_bpb_target_interp, static_cast <int >(targetCharSet.value ()));
91+
92+ if (const auto storage = options.getStorage (); storage.has_value ())
93+ builder->insertInt (&statusWrapper, isc_bpb_storage, static_cast <int >(storage.value ()));
94+
95+ const auto buffer = builder->getBuffer (&statusWrapper);
96+ const auto length = builder->getBufferLength (&statusWrapper);
97+
98+ std::vector<std::uint8_t > bpb (length);
99+
100+ if (length != 0 )
101+ std::memcpy (bpb.data (), buffer, length);
78102
79- handle.reset (
80- attachment.getHandle ()->openBlob (&statusWrapper, transaction.getHandle ().get (), &id.id , bpbLength, bpbData));
103+ return bpb;
81104}
82105
83106unsigned Blob::getLength ()
84107{
85108 assert (isValid ());
86109
87- const unsigned char items[] = {isc_info_blob_total_length};
88- unsigned char buffer[16 ]{};
110+ const std:: uint8_t items[] = {isc_info_blob_total_length};
111+ std:: uint8_t buffer[16 ]{};
89112
90113 handle->getInfo (&statusWrapper, sizeof (items), items, sizeof (buffer), buffer);
91114
0 commit comments