28#include <com/sun/star/io/IOException.hpp>
29#include <com/sun/star/uno/RuntimeException.hpp>
30#include <com/sun/star/uno/Sequence.hxx>
32#include <rtl/byteseq.hxx>
34#include <rtl/textcvt.h>
35#include <rtl/textenc.h>
36#include <rtl/ustring.h>
37#include <rtl/ustring.hxx>
39#include <typelib/typeclass.h>
40#include <typelib/typedescription.h>
41#include <typelib/typedescription.hxx>
44#include <uno/dispatcher.hxx>
56void * allocate(sal_Size
size) {
57 void *
p = std::malloc(
size);
59 throw std::bad_alloc();
64std::vector< BinaryAny >::iterator copyMemberValues(
65 css::uno::TypeDescription
const & type,
66 std::vector< BinaryAny >::iterator
const & it,
void * buffer)
noexcept
70 (
type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
71 type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
74 std::vector< BinaryAny >::iterator
i(it);
75 typelib_CompoundTypeDescription * ctd =
76 reinterpret_cast< typelib_CompoundTypeDescription *
>(
type.get());
77 if (ctd->pBaseTypeDescription !=
nullptr) {
79 css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase), i,
82 for (sal_Int32 j = 0; j != ctd->nMembers; ++j) {
84 static_cast< char *
>(buffer) + ctd->pMemberOffsets[j],
85 i++->getValue(css::uno::TypeDescription(ctd->ppTypeRefs[j])),
86 ctd->ppTypeRefs[j],
nullptr);
95 css::uno::Sequence< sal_Int8 >
const & buffer):
96 bridge_(
std::move(bridge)), state_(state), buffer_(buffer)
98 data_ =
reinterpret_cast< sal_uInt8 const *
>(buffer_.getConstArray());
99 end_ = data_ + buffer_.getLength();
102Unmarshal::~Unmarshal() {}
109sal_uInt16 Unmarshal::read16() {
111 sal_uInt16
n =
static_cast< sal_uInt16
>(*data_++) << 8;
115sal_uInt32 Unmarshal::read32() {
117 sal_uInt32
n =
static_cast< sal_uInt32
>(*data_++) << 24;
118 n |=
static_cast< sal_uInt32
>(*data_++) << 16;
119 n |=
static_cast< sal_uInt32
>(*data_++) << 8;
123css::uno::TypeDescription Unmarshal::readType() {
125 typelib_TypeClass tc =
static_cast< typelib_TypeClass
>(flags & 0x7F);
127 case typelib_TypeClass_VOID:
128 case typelib_TypeClass_BOOLEAN:
129 case typelib_TypeClass_BYTE:
130 case typelib_TypeClass_SHORT:
131 case typelib_TypeClass_UNSIGNED_SHORT:
132 case typelib_TypeClass_LONG:
133 case typelib_TypeClass_UNSIGNED_LONG:
134 case typelib_TypeClass_HYPER:
135 case typelib_TypeClass_UNSIGNED_HYPER:
136 case typelib_TypeClass_FLOAT:
137 case typelib_TypeClass_DOUBLE:
138 case typelib_TypeClass_CHAR:
139 case typelib_TypeClass_STRING:
140 case typelib_TypeClass_TYPE:
141 case typelib_TypeClass_ANY:
142 if ((flags & 0x80) != 0) {
143 throw css::io::IOException(
144 "binaryurp::Unmarshal: cache flag of simple type is set");
146 return css::uno::TypeDescription(
148 case typelib_TypeClass_SEQUENCE:
149 case typelib_TypeClass_ENUM:
150 case typelib_TypeClass_STRUCT:
151 case typelib_TypeClass_EXCEPTION:
152 case typelib_TypeClass_INTERFACE:
154 sal_uInt16
idx = readCacheIndex();
155 if ((flags & 0x80) == 0) {
157 throw css::io::IOException(
158 "binaryurp::Unmarshal: unknown type cache index");
160 return state_.typeCache[
idx];
163 css::uno::TypeDescription
t(str);
164 if (!
t.is() ||
t.get()->eTypeClass != tc) {
166 throw css::io::IOException(
167 "binaryurp::Unmarshal: type with unknown name: " + str);
169 for (css::uno::TypeDescription t2(
t);
170 t2.get()->eTypeClass == typelib_TypeClass_SEQUENCE;)
173 t2 = css::uno::TypeDescription(
174 reinterpret_cast< typelib_IndirectTypeDescription *
>(
177 throw css::io::IOException(
178 "binaryurp::Unmarshal: sequence type with unknown"
181 switch (t2.get()->eTypeClass) {
182 case typelib_TypeClass_VOID:
183 case typelib_TypeClass_EXCEPTION:
184 throw css::io::IOException(
185 "binaryurp::Unmarshal: sequence type with bad"
192 state_.typeCache[
idx] =
t;
198 throw css::io::IOException(
199 "binaryurp::Unmarshal: type of unknown type class");
203OUString Unmarshal::readOid() {
205 for (sal_Int32
i = 0;
i != oid.getLength(); ++
i) {
207 throw css::io::IOException(
208 "binaryurp::Unmarshal: OID contains non-ASCII character");
211 sal_uInt16
idx = readCacheIndex();
213 if (state_.oidCache[
idx].isEmpty()) {
214 throw css::io::IOException(
215 "binaryurp::Unmarshal: unknown OID cache index");
217 return state_.oidCache[
idx];
220 state_.oidCache[
idx] = oid;
225rtl::ByteSequence Unmarshal::readTid() {
226 rtl::ByteSequence tid(
229 css::uno::TypeDescription(
232 css::uno::TypeDescription(
234 sal_uInt16
idx = readCacheIndex();
235 if (tid.getLength() == 0) {
237 throw css::io::IOException(
238 "binaryurp::Unmarshal: unknown TID cache index");
240 return state_.tidCache[
idx];
243 state_.tidCache[
idx] = tid;
248BinaryAny Unmarshal::readValue(css::uno::TypeDescription
const & type) {
250 switch (
type.get()->eTypeClass) {
254 case typelib_TypeClass_VOID:
256 case typelib_TypeClass_BOOLEAN:
260 throw css::io::IOException(
261 "binaryurp::Unmarshal: boolean of unknown value");
265 case typelib_TypeClass_BYTE:
270 case typelib_TypeClass_SHORT:
271 case typelib_TypeClass_UNSIGNED_SHORT:
272 case typelib_TypeClass_CHAR:
274 sal_uInt16
v = read16();
277 case typelib_TypeClass_LONG:
278 case typelib_TypeClass_UNSIGNED_LONG:
279 case typelib_TypeClass_FLOAT:
281 sal_uInt32
v = read32();
284 case typelib_TypeClass_HYPER:
285 case typelib_TypeClass_UNSIGNED_HYPER:
286 case typelib_TypeClass_DOUBLE:
288 sal_uInt64
v = read64();
291 case typelib_TypeClass_STRING:
296 case typelib_TypeClass_TYPE:
298 css::uno::TypeDescription
v(readType());
302 case typelib_TypeClass_ANY:
304 css::uno::TypeDescription
t(readType());
305 if (
t.get()->eTypeClass == typelib_TypeClass_ANY) {
306 throw css::io::IOException(
307 "binaryurp::Unmarshal: any of type ANY");
311 case typelib_TypeClass_SEQUENCE:
313 return readSequence(
type);
314 case typelib_TypeClass_ENUM:
316 sal_Int32
v =
static_cast< sal_Int32
>(read32());
318 typelib_EnumTypeDescription * etd =
319 reinterpret_cast< typelib_EnumTypeDescription *
>(
type.get());
321 for (sal_Int32
i = 0;
i != etd->nEnumValues; ++
i) {
322 if (etd->pEnumValues[
i] ==
v) {
328 throw css::io::IOException(
329 "binaryurp::Unmarshal: unknown enum value");
333 case typelib_TypeClass_STRUCT:
334 case typelib_TypeClass_EXCEPTION:
336 std::vector< BinaryAny > as;
337 readMemberValues(
type, &as);
338 void * buf = allocate(
type.get()->nSize);
339 copyMemberValues(
type, as.begin(), buf);
341 raw.pType =
reinterpret_cast< typelib_TypeDescriptionReference *
>(
344 raw.pReserved =
nullptr;
347 case typelib_TypeClass_INTERFACE:
349 css::uno::UnoInterfaceReference obj(
350 bridge_->registerIncomingInterface(readOid(),
type));
356void Unmarshal::done()
const {
358 throw css::io::IOException(
359 "binaryurp::Unmarshal: block contains excess data");
363void Unmarshal::check(sal_Int32
size)
const {
364 if (end_ - data_ <
size) {
365 throw css::io::IOException(
366 "binaryurp::Unmarshal: trying to read past end of block");
370sal_uInt32 Unmarshal::readCompressed() {
372 return n == 0xFF ? read32() :
n;
375sal_uInt16 Unmarshal::readCacheIndex() {
376 sal_uInt16
idx = read16();
378 throw css::io::IOException(
379 "binaryurp::Unmarshal: cache index out of range");
384sal_uInt64 Unmarshal::read64() {
386 sal_uInt64
n =
static_cast< sal_uInt64
>(*data_++) << 56;
387 n |=
static_cast< sal_uInt64
>(*data_++) << 48;
388 n |=
static_cast< sal_uInt64
>(*data_++) << 40;
389 n |=
static_cast< sal_uInt64
>(*data_++) << 32;
390 n |=
static_cast< sal_uInt64
>(*data_++) << 24;
391 n |=
static_cast< sal_uInt64
>(*data_++) << 16;
392 n |=
static_cast< sal_uInt64
>(*data_++) << 8;
396OUString Unmarshal::readString() {
397 sal_uInt32
n = readCompressed();
399 throw css::uno::RuntimeException(
400 "binaryurp::Unmarshal: string size too large");
402 check(
static_cast< sal_Int32
>(
n));
404 if (!rtl_convertStringToUString(
405 &s.pData,
reinterpret_cast< char const *
>(data_),
406 static_cast< sal_Int32
>(
n), RTL_TEXTENCODING_UTF8,
407 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
408 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
409 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
411 throw css::io::IOException(
412 "binaryurp::Unmarshal: string does not contain UTF-8");
418BinaryAny Unmarshal::readSequence(css::uno::TypeDescription
const & type) {
419 assert(
type.is() &&
type.get()->eTypeClass == typelib_TypeClass_SEQUENCE);
420 sal_uInt32
n = readCompressed();
422 throw css::uno::RuntimeException(
423 "binaryurp::Unmarshal: sequence size too large");
428 css::uno::TypeDescription ctd(
429 reinterpret_cast< typelib_IndirectTypeDescription *
>(
431 if (ctd.get()->eTypeClass == typelib_TypeClass_BYTE) {
432 check(
static_cast< sal_Int32
>(
n));
434 reinterpret_cast< sal_Int8 const *
>(data_),
435 static_cast< sal_Int32
>(
n));
440 std::vector< BinaryAny > as;
442 for (sal_uInt32
i = 0;
i !=
n; ++
i) {
443 as.push_back(readValue(ctd));
445 assert(ctd.get()->nSize >= 0);
446 sal_uInt64
size =
static_cast< sal_uInt64
>(
n) *
447 static_cast< sal_uInt64
>(ctd.get()->nSize);
450 throw css::uno::RuntimeException(
451 "binaryurp::Unmarshal: sequence size too large");
453 void * buf = allocate(
457 static_cast< sal_Int32
>(
n);
458 for (sal_uInt32
i = 0;
i !=
n; ++
i) {
460 static_cast< sal_Sequence *
>(buf)->elements +
i * ctd.get()->nSize,
461 as[
i].getValue(ctd), ctd.get(),
nullptr);
466void Unmarshal::readMemberValues(
467 css::uno::TypeDescription
const & type, std::vector< BinaryAny > * values)
471 (
type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
472 type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
475 typelib_CompoundTypeDescription * ctd =
476 reinterpret_cast< typelib_CompoundTypeDescription *
>(
type.get());
477 if (ctd->pBaseTypeDescription !=
nullptr) {
479 css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase),
483 for (sal_Int32
i = 0;
i != ctd->nMembers; ++
i) {
485 readValue(css::uno::TypeDescription(ctd->ppTypeRefs[
i])));
Unmarshal(rtl::Reference< Bridge > bridge, ReaderState &state, com::sun::star::uno::Sequence< sal_Int8 > const &buffer)
void SAL_CALL uno_type_copyData(void *pDest, void *pSource, typelib_TypeDescriptionReference *pType, uno_AcquireFunc acquire) SAL_THROW_EXTERN_C()
void SAL_CALL uno_copyData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_AcquireFunc acquire) SAL_THROW_EXTERN_C()
struct _typelib_TypeDescription typelib_TypeDescription
css::uno::UnoInterfaceReference get()
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > check(dp_misc::DescriptionInfoset const &infoset)
css::beans::Optional< css::uno::Any > getValue(std::u16string_view id)
std::vector< char * > values
sal_uInt32 readString(const sal_uInt8 *buffer, sal_Unicode *v, sal_uInt32 maxSize)
typelib_TypeDescriptionReference **SAL_CALL typelib_static_type_getByTypeClass(typelib_TypeClass eTypeClass) SAL_THROW_EXTERN_C()
#define SAL_SEQUENCE_HEADER_SIZE