xref: /trunk/main/binaryurp/source/unmarshal.cxx (revision 0848378b)
137adc4f0SAndrew Rist /**************************************************************
237adc4f0SAndrew Rist  *
337adc4f0SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
437adc4f0SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
537adc4f0SAndrew Rist  * distributed with this work for additional information
637adc4f0SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
737adc4f0SAndrew Rist  * to you under the Apache License, Version 2.0 (the
837adc4f0SAndrew Rist  * "License"); you may not use this file except in compliance
937adc4f0SAndrew Rist  * with the License.  You may obtain a copy of the License at
1037adc4f0SAndrew Rist  *
1137adc4f0SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1237adc4f0SAndrew Rist  *
1337adc4f0SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1437adc4f0SAndrew Rist  * software distributed under the License is distributed on an
1537adc4f0SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1637adc4f0SAndrew Rist  * KIND, either express or implied.  See the License for the
1737adc4f0SAndrew Rist  * specific language governing permissions and limitations
1837adc4f0SAndrew Rist  * under the License.
1937adc4f0SAndrew Rist  *
2037adc4f0SAndrew Rist  *************************************************************/
2137adc4f0SAndrew Rist 
2237adc4f0SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "sal/config.h"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include <cstdlib>
27cdf0e10cSrcweir #include <new>
28cdf0e10cSrcweir #include <vector>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include "boost/noncopyable.hpp"
31cdf0e10cSrcweir #include "com/sun/star/io/IOException.hpp"
32cdf0e10cSrcweir #include "com/sun/star/uno/Reference.hxx"
33cdf0e10cSrcweir #include "com/sun/star/uno/RuntimeException.hpp"
34cdf0e10cSrcweir #include "com/sun/star/uno/Sequence.hxx"
35cdf0e10cSrcweir #include "com/sun/star/uno/XInterface.hpp"
36cdf0e10cSrcweir #include "cppu/unotype.hxx"
37cdf0e10cSrcweir #include "osl/diagnose.h"
38cdf0e10cSrcweir #include "rtl/byteseq.hxx"
39cdf0e10cSrcweir #include "rtl/ref.hxx"
40cdf0e10cSrcweir #include "rtl/textcvt.h"
41cdf0e10cSrcweir #include "rtl/textenc.h"
42cdf0e10cSrcweir #include "rtl/ustring.h"
43cdf0e10cSrcweir #include "rtl/ustring.hxx"
44cdf0e10cSrcweir #include "sal/types.h"
45cdf0e10cSrcweir #include "typelib/typeclass.h"
46cdf0e10cSrcweir #include "typelib/typedescription.h"
47cdf0e10cSrcweir #include "typelib/typedescription.hxx"
48cdf0e10cSrcweir #include "uno/any2.h"
49cdf0e10cSrcweir #include "uno/data.h"
50cdf0e10cSrcweir #include "uno/dispatcher.hxx"
51cdf0e10cSrcweir 
52cdf0e10cSrcweir #include "binaryany.hxx"
53cdf0e10cSrcweir #include "bridge.hxx"
54cdf0e10cSrcweir #include "cache.hxx"
55cdf0e10cSrcweir #include "readerstate.hxx"
56cdf0e10cSrcweir #include "unmarshal.hxx"
57cdf0e10cSrcweir 
58cdf0e10cSrcweir namespace binaryurp {
59cdf0e10cSrcweir 
60cdf0e10cSrcweir namespace {
61cdf0e10cSrcweir 
62cdf0e10cSrcweir namespace css = com::sun::star;
63cdf0e10cSrcweir 
allocate(sal_Size size)64cdf0e10cSrcweir void * allocate(sal_Size size) {
65cdf0e10cSrcweir     void * p = rtl_allocateMemory(size);
66cdf0e10cSrcweir     if (p == 0) {
67cdf0e10cSrcweir         throw std::bad_alloc();
68cdf0e10cSrcweir     }
69cdf0e10cSrcweir     return p;
70cdf0e10cSrcweir }
71cdf0e10cSrcweir 
copyMemberValues(css::uno::TypeDescription const & type,std::vector<BinaryAny>::iterator const & it,void * buffer)72cdf0e10cSrcweir std::vector< BinaryAny >::iterator copyMemberValues(
73cdf0e10cSrcweir     css::uno::TypeDescription const & type,
74cdf0e10cSrcweir     std::vector< BinaryAny >::iterator const & it, void * buffer) throw ()
75cdf0e10cSrcweir {
76cdf0e10cSrcweir     OSL_ASSERT(
77cdf0e10cSrcweir         type.is() &&
78cdf0e10cSrcweir         (type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
79cdf0e10cSrcweir          type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
80cdf0e10cSrcweir         buffer != 0);
81cdf0e10cSrcweir     type.makeComplete();
82cdf0e10cSrcweir     std::vector< BinaryAny >::iterator i(it);
83cdf0e10cSrcweir     typelib_CompoundTypeDescription * ctd =
84cdf0e10cSrcweir         reinterpret_cast< typelib_CompoundTypeDescription * >(type.get());
85cdf0e10cSrcweir     if (ctd->pBaseTypeDescription != 0) {
86cdf0e10cSrcweir         i = copyMemberValues(
87cdf0e10cSrcweir             css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase), i,
88cdf0e10cSrcweir             buffer);
89cdf0e10cSrcweir     }
90cdf0e10cSrcweir     for (sal_Int32 j = 0; j != ctd->nMembers; ++j) {
91cdf0e10cSrcweir         uno_type_copyData(
92cdf0e10cSrcweir             static_cast< char * >(buffer) + ctd->pMemberOffsets[j],
93cdf0e10cSrcweir             const_cast< void * >(
94cdf0e10cSrcweir                 i++->getValue(css::uno::TypeDescription(ctd->ppTypeRefs[j]))),
95cdf0e10cSrcweir             ctd->ppTypeRefs[j], 0);
96cdf0e10cSrcweir     }
97cdf0e10cSrcweir     return i;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir 
100cdf0e10cSrcweir }
101cdf0e10cSrcweir 
Unmarshal(rtl::Reference<Bridge> const & bridge,ReaderState & state,css::uno::Sequence<sal_Int8> const & buffer)102cdf0e10cSrcweir Unmarshal::Unmarshal(
103cdf0e10cSrcweir     rtl::Reference< Bridge > const & bridge, ReaderState & state,
104cdf0e10cSrcweir     css::uno::Sequence< sal_Int8 > const & buffer):
105cdf0e10cSrcweir     bridge_(bridge), state_(state), buffer_(buffer)
106cdf0e10cSrcweir {
107cdf0e10cSrcweir     data_ = reinterpret_cast< sal_uInt8 const * >(buffer_.getConstArray());
108cdf0e10cSrcweir     end_ = data_ + buffer_.getLength();
109cdf0e10cSrcweir }
110cdf0e10cSrcweir 
~Unmarshal()111cdf0e10cSrcweir Unmarshal::~Unmarshal() {}
112cdf0e10cSrcweir 
read8()113cdf0e10cSrcweir sal_uInt8 Unmarshal::read8() {
114cdf0e10cSrcweir     check(1);
115cdf0e10cSrcweir     return *data_++;
116cdf0e10cSrcweir }
117cdf0e10cSrcweir 
read16()118cdf0e10cSrcweir sal_uInt16 Unmarshal::read16() {
119cdf0e10cSrcweir     check(2);
120cdf0e10cSrcweir     sal_uInt16 n = static_cast< sal_uInt16 >(*data_++) << 8;
121cdf0e10cSrcweir     return n | *data_++;
122cdf0e10cSrcweir }
123cdf0e10cSrcweir 
read32()124cdf0e10cSrcweir sal_uInt32 Unmarshal::read32() {
125cdf0e10cSrcweir     check(4);
126cdf0e10cSrcweir     sal_uInt32 n = static_cast< sal_uInt32 >(*data_++) << 24;
127cdf0e10cSrcweir     n |= static_cast< sal_uInt32 >(*data_++) << 16;
128cdf0e10cSrcweir     n |= static_cast< sal_uInt32 >(*data_++) << 8;
129cdf0e10cSrcweir     return n | *data_++;
130cdf0e10cSrcweir }
131cdf0e10cSrcweir 
readType()132cdf0e10cSrcweir css::uno::TypeDescription Unmarshal::readType() {
133cdf0e10cSrcweir     sal_uInt8 flags = read8();
134cdf0e10cSrcweir     typelib_TypeClass tc = static_cast< typelib_TypeClass >(flags & 0x7F);
135cdf0e10cSrcweir     switch (tc) {
136cdf0e10cSrcweir     case typelib_TypeClass_VOID:
137cdf0e10cSrcweir     case typelib_TypeClass_BOOLEAN:
138cdf0e10cSrcweir     case typelib_TypeClass_BYTE:
139cdf0e10cSrcweir     case typelib_TypeClass_SHORT:
140cdf0e10cSrcweir     case typelib_TypeClass_UNSIGNED_SHORT:
141cdf0e10cSrcweir     case typelib_TypeClass_LONG:
142cdf0e10cSrcweir     case typelib_TypeClass_UNSIGNED_LONG:
143cdf0e10cSrcweir     case typelib_TypeClass_HYPER:
144cdf0e10cSrcweir     case typelib_TypeClass_UNSIGNED_HYPER:
145cdf0e10cSrcweir     case typelib_TypeClass_FLOAT:
146cdf0e10cSrcweir     case typelib_TypeClass_DOUBLE:
147cdf0e10cSrcweir     case typelib_TypeClass_CHAR:
148cdf0e10cSrcweir     case typelib_TypeClass_STRING:
149cdf0e10cSrcweir     case typelib_TypeClass_TYPE:
150cdf0e10cSrcweir     case typelib_TypeClass_ANY:
151cdf0e10cSrcweir         if ((flags & 0x80) != 0) {
152cdf0e10cSrcweir             throw css::io::IOException(
153cdf0e10cSrcweir                 rtl::OUString(
154cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
155cdf0e10cSrcweir                         "binaryurp::Unmarshal: cache flag of simple type is"
156cdf0e10cSrcweir                         " set")),
157cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
158cdf0e10cSrcweir         }
159cdf0e10cSrcweir         return css::uno::TypeDescription(
160cdf0e10cSrcweir             *typelib_static_type_getByTypeClass(
161cdf0e10cSrcweir                 static_cast< typelib_TypeClass >(tc)));
162cdf0e10cSrcweir     case typelib_TypeClass_SEQUENCE:
163cdf0e10cSrcweir     case typelib_TypeClass_ENUM:
164cdf0e10cSrcweir     case typelib_TypeClass_STRUCT:
165cdf0e10cSrcweir     case typelib_TypeClass_EXCEPTION:
166cdf0e10cSrcweir     case typelib_TypeClass_INTERFACE:
167cdf0e10cSrcweir         {
168cdf0e10cSrcweir             sal_uInt16 idx = readCacheIndex();
169cdf0e10cSrcweir             if ((flags & 0x80) == 0) {
170cdf0e10cSrcweir                 if (idx == cache::ignore || !state_.typeCache[idx].is()) {
171cdf0e10cSrcweir                     throw css::io::IOException(
172cdf0e10cSrcweir                         rtl::OUString(
173cdf0e10cSrcweir                             RTL_CONSTASCII_USTRINGPARAM(
174cdf0e10cSrcweir                                 "binaryurp::Unmarshal: unknown type cache"
175cdf0e10cSrcweir                                 " index")),
176cdf0e10cSrcweir                         css::uno::Reference< css::uno::XInterface >());
177cdf0e10cSrcweir                 }
178cdf0e10cSrcweir                 return state_.typeCache[idx];
179cdf0e10cSrcweir             } else {
180cdf0e10cSrcweir                 css::uno::TypeDescription t(readString());
181cdf0e10cSrcweir                 if (!t.is() ||
182cdf0e10cSrcweir                     t.get()->eTypeClass != static_cast< typelib_TypeClass >(tc))
183cdf0e10cSrcweir                 {
184cdf0e10cSrcweir                     throw css::io::IOException(
185cdf0e10cSrcweir                         rtl::OUString(
186cdf0e10cSrcweir                             RTL_CONSTASCII_USTRINGPARAM(
187cdf0e10cSrcweir                                 "binaryurp::Unmarshal: type with unknown"
188cdf0e10cSrcweir                                 " name")),
189cdf0e10cSrcweir                         css::uno::Reference< css::uno::XInterface >());
190cdf0e10cSrcweir                 }
191cdf0e10cSrcweir                 for (css::uno::TypeDescription t2(t);
192cdf0e10cSrcweir                      t2.get()->eTypeClass == typelib_TypeClass_SEQUENCE;)
193cdf0e10cSrcweir                 {
194cdf0e10cSrcweir                     t2.makeComplete();
195cdf0e10cSrcweir                     t2 = css::uno::TypeDescription(
196cdf0e10cSrcweir                         reinterpret_cast< typelib_IndirectTypeDescription * >(
197cdf0e10cSrcweir                             t2.get())->pType);
198cdf0e10cSrcweir                     if (!t2.is()) {
199cdf0e10cSrcweir                         throw css::io::IOException(
200cdf0e10cSrcweir                             rtl::OUString(
201cdf0e10cSrcweir                                 RTL_CONSTASCII_USTRINGPARAM(
202cdf0e10cSrcweir                                     "binaryurp::Unmarshal: sequence type with"
203cdf0e10cSrcweir                                     " unknown component type")),
204cdf0e10cSrcweir                             css::uno::Reference< css::uno::XInterface >());
205cdf0e10cSrcweir                     }
206cdf0e10cSrcweir                     switch (t2.get()->eTypeClass) {
207cdf0e10cSrcweir                     case typelib_TypeClass_VOID:
208cdf0e10cSrcweir                     case typelib_TypeClass_EXCEPTION:
209cdf0e10cSrcweir                         throw css::io::IOException(
210cdf0e10cSrcweir                             rtl::OUString(
211cdf0e10cSrcweir                                 RTL_CONSTASCII_USTRINGPARAM(
212cdf0e10cSrcweir                                     "binaryurp::Unmarshal: sequence type with"
213cdf0e10cSrcweir                                     " bad component type")),
214cdf0e10cSrcweir                             css::uno::Reference< css::uno::XInterface >());
215cdf0e10cSrcweir                     default:
216cdf0e10cSrcweir                         break;
217cdf0e10cSrcweir                     }
218cdf0e10cSrcweir                 }
219cdf0e10cSrcweir                 if (idx != cache::ignore) {
220cdf0e10cSrcweir                     state_.typeCache[idx] = t;
221cdf0e10cSrcweir                 }
222cdf0e10cSrcweir                 return t;
223cdf0e10cSrcweir             }
224cdf0e10cSrcweir         }
225cdf0e10cSrcweir     default:
226cdf0e10cSrcweir         throw css::io::IOException(
227cdf0e10cSrcweir             rtl::OUString(
228cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
229cdf0e10cSrcweir                     "binaryurp::Unmarshal: type of unknown type class")),
230cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
231cdf0e10cSrcweir     }
232cdf0e10cSrcweir }
233cdf0e10cSrcweir 
readOid()234cdf0e10cSrcweir rtl::OUString Unmarshal::readOid() {
235cdf0e10cSrcweir     rtl::OUString oid(readString());
236cdf0e10cSrcweir     for (sal_Int32 i = 0; i != oid.getLength(); ++i) {
237cdf0e10cSrcweir         if (oid[i] > 0x7F) {
238cdf0e10cSrcweir             throw css::io::IOException(
239cdf0e10cSrcweir                 rtl::OUString(
240cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
241cdf0e10cSrcweir                         "binaryurp::Unmarshal: OID contains non-ASCII"
242cdf0e10cSrcweir                         " character")),
243cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
244cdf0e10cSrcweir         }
245cdf0e10cSrcweir     }
246cdf0e10cSrcweir     sal_uInt16 idx = readCacheIndex();
247*0848378bSHerbert Dürr     if (oid.isEmpty() && idx != cache::ignore) {
248*0848378bSHerbert Dürr         if ( state_.oidCache[idx].isEmpty() ) {
249cdf0e10cSrcweir             throw css::io::IOException(
250cdf0e10cSrcweir                 rtl::OUString(
251cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
252cdf0e10cSrcweir                         "binaryurp::Unmarshal: unknown OID cache index")),
253cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
254cdf0e10cSrcweir         }
255cdf0e10cSrcweir         return state_.oidCache[idx];
256cdf0e10cSrcweir     }
257cdf0e10cSrcweir     if (idx != cache::ignore) {
258cdf0e10cSrcweir         state_.oidCache[idx] = oid;
259cdf0e10cSrcweir     }
260cdf0e10cSrcweir     return oid;
261cdf0e10cSrcweir }
262cdf0e10cSrcweir 
readTid()263cdf0e10cSrcweir rtl::ByteSequence Unmarshal::readTid() {
264cdf0e10cSrcweir     rtl::ByteSequence tid(
265cdf0e10cSrcweir         *static_cast< sal_Sequence * const * >(
266cdf0e10cSrcweir             readSequence(
267cdf0e10cSrcweir                 css::uno::TypeDescription(
268cdf0e10cSrcweir                     cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get())).
269cdf0e10cSrcweir             getValue(
270cdf0e10cSrcweir                 css::uno::TypeDescription(
271cdf0e10cSrcweir                     cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get()))));
272cdf0e10cSrcweir     sal_uInt16 idx = readCacheIndex();
273cdf0e10cSrcweir     if (tid.getLength() == 0) {
274cdf0e10cSrcweir         if (idx == cache::ignore || state_.tidCache[idx].getLength() == 0) {
275cdf0e10cSrcweir             throw css::io::IOException(
276cdf0e10cSrcweir                 rtl::OUString(
277cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
278cdf0e10cSrcweir                         "binaryurp::Unmarshal: unknown TID cache index")),
279cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
280cdf0e10cSrcweir         }
281cdf0e10cSrcweir         return state_.tidCache[idx];
282cdf0e10cSrcweir     }
283cdf0e10cSrcweir     if (idx != cache::ignore) {
284cdf0e10cSrcweir         state_.tidCache[idx] = tid;
285cdf0e10cSrcweir     }
286cdf0e10cSrcweir     return tid;
287cdf0e10cSrcweir }
288cdf0e10cSrcweir 
readValue(css::uno::TypeDescription const & type)289cdf0e10cSrcweir BinaryAny Unmarshal::readValue(css::uno::TypeDescription const & type) {
290cdf0e10cSrcweir     OSL_ASSERT(type.is());
291cdf0e10cSrcweir     switch (type.get()->eTypeClass) {
292cdf0e10cSrcweir     default:
293cdf0e10cSrcweir         std::abort(); // this cannot happen
294cdf0e10cSrcweir         // pseudo fall-through to avoid compiler warnings
295cdf0e10cSrcweir     case typelib_TypeClass_VOID:
296cdf0e10cSrcweir         return BinaryAny();
297cdf0e10cSrcweir     case typelib_TypeClass_BOOLEAN:
298cdf0e10cSrcweir         {
299cdf0e10cSrcweir             sal_uInt8 v = read8();
300cdf0e10cSrcweir             if (v > 1) {
301cdf0e10cSrcweir                 throw css::io::IOException(
302cdf0e10cSrcweir                     rtl::OUString(
303cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM(
304cdf0e10cSrcweir                             "binaryurp::Unmarshal: boolean of unknown value")),
305cdf0e10cSrcweir                     css::uno::Reference< css::uno::XInterface >());
306cdf0e10cSrcweir             }
307cdf0e10cSrcweir             return BinaryAny(type, &v);
308cdf0e10cSrcweir         }
309cdf0e10cSrcweir     case typelib_TypeClass_BYTE:
310cdf0e10cSrcweir         {
311cdf0e10cSrcweir             sal_uInt8 v = read8();
312cdf0e10cSrcweir             return BinaryAny(type, &v);
313cdf0e10cSrcweir         }
314cdf0e10cSrcweir     case typelib_TypeClass_SHORT:
315cdf0e10cSrcweir     case typelib_TypeClass_UNSIGNED_SHORT:
316cdf0e10cSrcweir     case typelib_TypeClass_CHAR:
317cdf0e10cSrcweir         {
318cdf0e10cSrcweir             sal_uInt16 v = read16();
319cdf0e10cSrcweir             return BinaryAny(type, &v);
320cdf0e10cSrcweir         }
321cdf0e10cSrcweir     case typelib_TypeClass_LONG:
322cdf0e10cSrcweir     case typelib_TypeClass_UNSIGNED_LONG:
323cdf0e10cSrcweir     case typelib_TypeClass_FLOAT:
324cdf0e10cSrcweir         {
325cdf0e10cSrcweir             sal_uInt32 v = read32();
326cdf0e10cSrcweir             return BinaryAny(type, &v);
327cdf0e10cSrcweir         }
328cdf0e10cSrcweir     case typelib_TypeClass_HYPER:
329cdf0e10cSrcweir     case typelib_TypeClass_UNSIGNED_HYPER:
330cdf0e10cSrcweir     case typelib_TypeClass_DOUBLE:
331cdf0e10cSrcweir         {
332cdf0e10cSrcweir             sal_uInt64 v = read64();
333cdf0e10cSrcweir             return BinaryAny(type, &v);
334cdf0e10cSrcweir         }
335cdf0e10cSrcweir     case typelib_TypeClass_STRING:
336cdf0e10cSrcweir         {
337cdf0e10cSrcweir             rtl::OUString v(readString());
338cdf0e10cSrcweir             return BinaryAny(type, &v.pData);
339cdf0e10cSrcweir         }
340cdf0e10cSrcweir     case typelib_TypeClass_TYPE:
341cdf0e10cSrcweir         {
342cdf0e10cSrcweir             css::uno::TypeDescription v(readType());
343cdf0e10cSrcweir             typelib_TypeDescription * p = v.get();
344cdf0e10cSrcweir             return BinaryAny(type, &p);
345cdf0e10cSrcweir         }
346cdf0e10cSrcweir     case typelib_TypeClass_ANY:
347cdf0e10cSrcweir         {
348cdf0e10cSrcweir             css::uno::TypeDescription t(readType());
349cdf0e10cSrcweir             if (t.get()->eTypeClass == typelib_TypeClass_ANY) {
350cdf0e10cSrcweir                 throw css::io::IOException(
351cdf0e10cSrcweir                     rtl::OUString(
352cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM(
353cdf0e10cSrcweir                             "binaryurp::Unmarshal: any of type ANY")),
354cdf0e10cSrcweir                     css::uno::Reference< css::uno::XInterface >());
355cdf0e10cSrcweir             }
356cdf0e10cSrcweir             return readValue(t);
357cdf0e10cSrcweir         }
358cdf0e10cSrcweir     case typelib_TypeClass_SEQUENCE:
359cdf0e10cSrcweir         type.makeComplete();
360cdf0e10cSrcweir         return readSequence(type);
361cdf0e10cSrcweir     case typelib_TypeClass_ENUM:
362cdf0e10cSrcweir         {
363cdf0e10cSrcweir             sal_Int32 v = static_cast< sal_Int32 >(read32());
364cdf0e10cSrcweir             type.makeComplete();
365cdf0e10cSrcweir             typelib_EnumTypeDescription * etd =
366cdf0e10cSrcweir                 reinterpret_cast< typelib_EnumTypeDescription * >(type.get());
367cdf0e10cSrcweir             bool found = false;
368cdf0e10cSrcweir             for (sal_Int32 i = 0; i != etd->nEnumValues; ++i) {
369cdf0e10cSrcweir                 if (etd->pEnumValues[i] == v) {
370cdf0e10cSrcweir                     found = true;
371cdf0e10cSrcweir                     break;
372cdf0e10cSrcweir                 }
373cdf0e10cSrcweir             }
374cdf0e10cSrcweir             if (!found) {
375cdf0e10cSrcweir                 throw css::io::IOException(
376cdf0e10cSrcweir                     rtl::OUString(
377cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM(
378cdf0e10cSrcweir                             "binaryurp::Unmarshal: unknown enum value")),
379cdf0e10cSrcweir                     css::uno::Reference< css::uno::XInterface >());
380cdf0e10cSrcweir             }
381cdf0e10cSrcweir             return BinaryAny(type, &v);
382cdf0e10cSrcweir         }
383cdf0e10cSrcweir     case typelib_TypeClass_STRUCT:
384cdf0e10cSrcweir     case typelib_TypeClass_EXCEPTION:
385cdf0e10cSrcweir         {
386cdf0e10cSrcweir             std::vector< BinaryAny > as;
387cdf0e10cSrcweir             readMemberValues(type, &as);
388cdf0e10cSrcweir             void * buf = allocate(type.get()->nSize);
389cdf0e10cSrcweir             copyMemberValues(type, as.begin(), buf);
390cdf0e10cSrcweir             uno_Any raw;
391cdf0e10cSrcweir             raw.pType = reinterpret_cast< typelib_TypeDescriptionReference * >(
392cdf0e10cSrcweir                 type.get());
393cdf0e10cSrcweir             raw.pData = buf;
394cdf0e10cSrcweir             raw.pReserved = 0;
395cdf0e10cSrcweir             return BinaryAny(raw);
396cdf0e10cSrcweir         }
397cdf0e10cSrcweir     case typelib_TypeClass_INTERFACE:
398cdf0e10cSrcweir         {
399cdf0e10cSrcweir             css::uno::UnoInterfaceReference obj(
400cdf0e10cSrcweir                 bridge_->registerIncomingInterface(readOid(), type));
401cdf0e10cSrcweir             return BinaryAny(type, &obj.m_pUnoI);
402cdf0e10cSrcweir         }
403cdf0e10cSrcweir     }
404cdf0e10cSrcweir }
405cdf0e10cSrcweir 
done() const406cdf0e10cSrcweir void Unmarshal::done() const {
407cdf0e10cSrcweir     if (data_ != end_) {
408cdf0e10cSrcweir         throw css::io::IOException(
409cdf0e10cSrcweir             rtl::OUString(
410cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
411cdf0e10cSrcweir                     "binaryurp::Unmarshal: block contains excess data")),
412cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
413cdf0e10cSrcweir     }
414cdf0e10cSrcweir }
415cdf0e10cSrcweir 
check(sal_Int32 size) const416cdf0e10cSrcweir void Unmarshal::check(sal_Int32 size) const {
417cdf0e10cSrcweir     if (end_ - data_ < size) {
418cdf0e10cSrcweir         throw css::io::IOException(
419cdf0e10cSrcweir             rtl::OUString(
420cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
421cdf0e10cSrcweir                     "binaryurp::Unmarshal: trying to read past end of block")),
422cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
423cdf0e10cSrcweir     }
424cdf0e10cSrcweir }
425cdf0e10cSrcweir 
readCompressed()426cdf0e10cSrcweir sal_uInt32 Unmarshal::readCompressed() {
427cdf0e10cSrcweir     sal_uInt8 n = read8();
428cdf0e10cSrcweir     return n == 0xFF ? read32() : n;
429cdf0e10cSrcweir }
430cdf0e10cSrcweir 
readCacheIndex()431cdf0e10cSrcweir sal_uInt16 Unmarshal::readCacheIndex() {
432cdf0e10cSrcweir     sal_uInt16 idx = read16();
433cdf0e10cSrcweir     if (idx >= cache::size && idx != cache::ignore) {
434cdf0e10cSrcweir         throw css::io::IOException(
435cdf0e10cSrcweir             rtl::OUString(
436cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
437cdf0e10cSrcweir                     "binaryurp::Unmarshal: cache index out of range")),
438cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
439cdf0e10cSrcweir     }
440cdf0e10cSrcweir     return idx;
441cdf0e10cSrcweir }
442cdf0e10cSrcweir 
read64()443cdf0e10cSrcweir sal_uInt64 Unmarshal::read64() {
444cdf0e10cSrcweir     check(8);
445cdf0e10cSrcweir     sal_uInt64 n = static_cast< sal_uInt64 >(*data_++) << 56;
446cdf0e10cSrcweir     n |= static_cast< sal_uInt64 >(*data_++) << 48;
447cdf0e10cSrcweir     n |= static_cast< sal_uInt64 >(*data_++) << 40;
448cdf0e10cSrcweir     n |= static_cast< sal_uInt64 >(*data_++) << 32;
449cdf0e10cSrcweir     n |= static_cast< sal_uInt64 >(*data_++) << 24;
450cdf0e10cSrcweir     n |= static_cast< sal_uInt64 >(*data_++) << 16;
451cdf0e10cSrcweir     n |= static_cast< sal_uInt64 >(*data_++) << 8;
452cdf0e10cSrcweir     return n | *data_++;
453cdf0e10cSrcweir }
454cdf0e10cSrcweir 
readString()455cdf0e10cSrcweir rtl::OUString Unmarshal::readString() {
456cdf0e10cSrcweir     sal_uInt32 n = readCompressed();
457cdf0e10cSrcweir     if (n > SAL_MAX_INT32) {
458cdf0e10cSrcweir         throw css::uno::RuntimeException(
459cdf0e10cSrcweir             rtl::OUString(
460cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
461cdf0e10cSrcweir                     "binaryurp::Unmarshal: string size too large")),
462cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
463cdf0e10cSrcweir     }
464cdf0e10cSrcweir     check(static_cast< sal_Int32 >(n));
465cdf0e10cSrcweir     rtl::OUString s;
466cdf0e10cSrcweir     if (!rtl_convertStringToUString(
467cdf0e10cSrcweir             &s.pData, reinterpret_cast< char const * >(data_),
468cdf0e10cSrcweir             static_cast< sal_Int32 >(n), RTL_TEXTENCODING_UTF8,
469cdf0e10cSrcweir             (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
470cdf0e10cSrcweir              RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
471cdf0e10cSrcweir              RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
472cdf0e10cSrcweir     {
473cdf0e10cSrcweir         throw css::io::IOException(
474cdf0e10cSrcweir             rtl::OUString(
475cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
476cdf0e10cSrcweir                     "binaryurp::Unmarshal: string does not contain UTF-8")),
477cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
478cdf0e10cSrcweir     }
479cdf0e10cSrcweir     data_ += n;
480cdf0e10cSrcweir     return s;
481cdf0e10cSrcweir }
482cdf0e10cSrcweir 
readSequence(css::uno::TypeDescription const & type)483cdf0e10cSrcweir BinaryAny Unmarshal::readSequence(css::uno::TypeDescription const & type) {
484cdf0e10cSrcweir     OSL_ASSERT(
485cdf0e10cSrcweir         type.is() && type.get()->eTypeClass == typelib_TypeClass_SEQUENCE);
486cdf0e10cSrcweir     sal_uInt32 n = readCompressed();
487cdf0e10cSrcweir     if (n > SAL_MAX_INT32) {
488cdf0e10cSrcweir         throw css::uno::RuntimeException(
489cdf0e10cSrcweir             rtl::OUString(
490cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
491cdf0e10cSrcweir                     "binaryurp::Unmarshal: sequence size too large")),
492cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
493cdf0e10cSrcweir     }
494cdf0e10cSrcweir     if (n == 0) {
495cdf0e10cSrcweir         return BinaryAny(type, 0);
496cdf0e10cSrcweir     }
497cdf0e10cSrcweir     css::uno::TypeDescription ctd(
498cdf0e10cSrcweir         reinterpret_cast< typelib_IndirectTypeDescription * >(
499cdf0e10cSrcweir             type.get())->pType);
500cdf0e10cSrcweir     if (ctd.get()->eTypeClass == typelib_TypeClass_BYTE) {
501cdf0e10cSrcweir         check(static_cast< sal_Int32 >(n));
502cdf0e10cSrcweir         rtl::ByteSequence s(
503cdf0e10cSrcweir             reinterpret_cast< sal_Int8 const * >(data_),
504cdf0e10cSrcweir             static_cast< sal_Int32 >(n));
505cdf0e10cSrcweir         data_ += n;
506cdf0e10cSrcweir         sal_Sequence * p = s.getHandle();
507cdf0e10cSrcweir         return BinaryAny(type, &p);
508cdf0e10cSrcweir     }
509cdf0e10cSrcweir     std::vector< BinaryAny > as;
510cdf0e10cSrcweir     for (sal_uInt32 i = 0; i != n; ++i) {
511cdf0e10cSrcweir         as.push_back(readValue(ctd));
512cdf0e10cSrcweir     }
513cdf0e10cSrcweir     OSL_ASSERT(ctd.get()->nSize >= 0);
514cdf0e10cSrcweir     sal_uInt64 size = static_cast< sal_uInt64 >(n) *
515cdf0e10cSrcweir         static_cast< sal_uInt64 >(ctd.get()->nSize);
516cdf0e10cSrcweir         // sal_uInt32 * sal_Int32 -> sal_uInt64 cannot overflow
517cdf0e10cSrcweir     if (size > SAL_MAX_SIZE - SAL_SEQUENCE_HEADER_SIZE) {
518cdf0e10cSrcweir         throw css::uno::RuntimeException(
519cdf0e10cSrcweir             rtl::OUString(
520cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
521cdf0e10cSrcweir                     "binaryurp::Unmarshal: sequence size too large")),
522cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
523cdf0e10cSrcweir     }
524cdf0e10cSrcweir     void * buf = allocate(
525cdf0e10cSrcweir         SAL_SEQUENCE_HEADER_SIZE + static_cast< sal_Size >(size));
526cdf0e10cSrcweir     static_cast< sal_Sequence * >(buf)->nRefCount = 0;
527cdf0e10cSrcweir     static_cast< sal_Sequence * >(buf)->nElements =
528cdf0e10cSrcweir         static_cast< sal_Int32 >(n);
529cdf0e10cSrcweir     for (sal_uInt32 i = 0; i != n; ++i) {
530cdf0e10cSrcweir         uno_copyData(
531cdf0e10cSrcweir             static_cast< sal_Sequence * >(buf)->elements + i * ctd.get()->nSize,
532cdf0e10cSrcweir             const_cast< void * >(as[i].getValue(ctd)), ctd.get(), 0);
533cdf0e10cSrcweir     }
534cdf0e10cSrcweir     return BinaryAny(type, reinterpret_cast< sal_Sequence ** >(&buf));
535cdf0e10cSrcweir }
536cdf0e10cSrcweir 
readMemberValues(css::uno::TypeDescription const & type,std::vector<BinaryAny> * values)537cdf0e10cSrcweir void Unmarshal::readMemberValues(
538cdf0e10cSrcweir     css::uno::TypeDescription const & type, std::vector< BinaryAny > * values)
539cdf0e10cSrcweir {
540cdf0e10cSrcweir     OSL_ASSERT(
541cdf0e10cSrcweir         type.is() &&
542cdf0e10cSrcweir         (type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
543cdf0e10cSrcweir          type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
544cdf0e10cSrcweir         values != 0);
545cdf0e10cSrcweir     type.makeComplete();
546cdf0e10cSrcweir     typelib_CompoundTypeDescription * ctd =
547cdf0e10cSrcweir         reinterpret_cast< typelib_CompoundTypeDescription * >(type.get());
548cdf0e10cSrcweir     if (ctd->pBaseTypeDescription != 0) {
549cdf0e10cSrcweir         readMemberValues(
550cdf0e10cSrcweir             css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase),
551cdf0e10cSrcweir             values);
552cdf0e10cSrcweir     }
553cdf0e10cSrcweir     for (sal_Int32 i = 0; i != ctd->nMembers; ++i) {
554cdf0e10cSrcweir         values->push_back(
555cdf0e10cSrcweir             readValue(css::uno::TypeDescription(ctd->ppTypeRefs[i])));
556cdf0e10cSrcweir     }
557cdf0e10cSrcweir }
558cdf0e10cSrcweir 
559cdf0e10cSrcweir }
560