xref: /aoo41x/main/binaryurp/source/marshal.cxx (revision 0848378b)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "sal/config.h"
25 
26 #include <vector>
27 
28 #include "boost/noncopyable.hpp"
29 #include "com/sun/star/uno/Reference.hxx"
30 #include "com/sun/star/uno/RuntimeException.hpp"
31 #include "com/sun/star/uno/Sequence.hxx"
32 #include "com/sun/star/uno/XInterface.hpp"
33 #include "cppu/unotype.hxx"
34 #include "osl/diagnose.h"
35 #include "rtl/byteseq.hxx"
36 #include "rtl/string.hxx"
37 #include "rtl/textcvt.h"
38 #include "rtl/textenc.h"
39 #include "rtl/ustring.h"
40 #include "rtl/ustring.hxx"
41 #include "sal/types.h"
42 #include "typelib/typeclass.h"
43 #include "typelib/typedescription.h"
44 #include "typelib/typedescription.hxx"
45 #include "uno/dispatcher.hxx"
46 
47 #include "binaryany.hxx"
48 #include "bridge.hxx"
49 #include "cache.hxx"
50 #include "lessoperators.hxx"
51 #include "marshal.hxx"
52 
53 namespace binaryurp {
54 
55 namespace {
56 
57 namespace css = com::sun::star;
58 
write64(std::vector<unsigned char> * buffer,sal_uInt64 value)59 void write64(std::vector< unsigned char > * buffer, sal_uInt64 value) {
60     Marshal::write8(buffer, value >> 56);
61     Marshal::write8(buffer, (value >> 48) & 0xFF);
62     Marshal::write8(buffer, (value >> 40) & 0xFF);
63     Marshal::write8(buffer, (value >> 32) & 0xFF);
64     Marshal::write8(buffer, (value >> 24) & 0xFF);
65     Marshal::write8(buffer, (value >> 16) & 0xFF);
66     Marshal::write8(buffer, (value >> 8) & 0xFF);
67     Marshal::write8(buffer, value & 0xFF);
68 }
69 
writeCompressed(std::vector<unsigned char> * buffer,sal_uInt32 value)70 void writeCompressed(std::vector< unsigned char > * buffer, sal_uInt32 value) {
71     if (value < 0xFF) {
72         Marshal::write8(buffer, static_cast< sal_uInt8 >(value));
73     } else {
74         Marshal::write8(buffer, 0xFF);
75         Marshal::write32(buffer, value);
76     }
77 }
78 
writeString(std::vector<unsigned char> * buffer,rtl::OUString const & value)79 void writeString(
80     std::vector< unsigned char > * buffer, rtl::OUString const & value)
81 {
82     OSL_ASSERT(buffer != 0);
83     rtl::OString v;
84     if (!value.convertToString(
85             &v, RTL_TEXTENCODING_UTF8,
86             (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
87              RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
88     {
89         throw css::uno::RuntimeException(
90             rtl::OUString(
91                 RTL_CONSTASCII_USTRINGPARAM(
92                     "UNO string contains invalid UTF-16 sequence")),
93             css::uno::Reference< css::uno::XInterface >());
94     }
95     writeCompressed(buffer, static_cast< sal_uInt32 >(v.getLength()));
96     buffer->insert(buffer->end(), v.getStr(), v.getStr() + v.getLength());
97 }
98 
99 }
100 
Marshal(rtl::Reference<Bridge> const & bridge,WriterState & state)101 Marshal::Marshal(rtl::Reference< Bridge > const & bridge, WriterState & state):
102     bridge_(bridge), state_(state)
103 {
104     OSL_ASSERT(bridge.is());
105 }
106 
~Marshal()107 Marshal::~Marshal() {}
108 
write8(std::vector<unsigned char> * buffer,sal_uInt8 value)109 void Marshal::write8(std::vector< unsigned char > * buffer, sal_uInt8 value) {
110     OSL_ASSERT(buffer != 0);
111     buffer->push_back(value);
112 }
113 
write16(std::vector<unsigned char> * buffer,sal_uInt16 value)114 void Marshal::write16(std::vector< unsigned char > * buffer, sal_uInt16 value) {
115     write8(buffer, value >> 8);
116     write8(buffer, value & 0xFF);
117 }
118 
write32(std::vector<unsigned char> * buffer,sal_uInt32 value)119 void Marshal::write32(std::vector< unsigned char > * buffer, sal_uInt32 value) {
120     write8(buffer, value >> 24);
121     write8(buffer, (value >> 16) & 0xFF);
122     write8(buffer, (value >> 8) & 0xFF);
123     write8(buffer, value & 0xFF);
124 }
125 
writeValue(std::vector<unsigned char> * buffer,css::uno::TypeDescription const & type,BinaryAny const & value)126 void Marshal::writeValue(
127     std::vector< unsigned char > * buffer,
128     css::uno::TypeDescription const & type, BinaryAny const & value)
129 {
130     OSL_ASSERT(
131         type.is() &&
132         (type.get()->eTypeClass == typelib_TypeClass_ANY ||
133          value.getType().equals(type)));
134     writeValue(buffer, type, value.getValue(type));
135 }
136 
writeType(std::vector<unsigned char> * buffer,css::uno::TypeDescription const & value)137 void Marshal::writeType(
138     std::vector< unsigned char > * buffer,
139     css::uno::TypeDescription const & value)
140 {
141     value.makeComplete();
142     OSL_ASSERT(value.is());
143     typelib_TypeClass tc = value.get()->eTypeClass;
144     if (tc <= typelib_TypeClass_ANY) {
145         write8(buffer, static_cast< sal_uInt8 >(tc));
146     } else {
147         bool found;
148         sal_uInt16 idx = state_.typeCache.add(value, &found);
149         if (found) {
150             write8(buffer, static_cast< sal_uInt8 >(tc));
151             write16(buffer, idx);
152         } else {
153             write8(buffer, static_cast< sal_uInt8 >(tc) | 0x80);
154             write16(buffer, idx);
155             writeString(buffer, rtl::OUString(value.get()->pTypeName));
156         }
157     }
158 }
159 
writeOid(std::vector<unsigned char> * buffer,rtl::OUString const & oid)160 void Marshal::writeOid(
161     std::vector< unsigned char > * buffer, rtl::OUString const & oid)
162 {
163     bool found;
164     sal_uInt16 idx;
165     if ( oid.isEmpty() ) {
166         found = true;
167         idx = cache::ignore;
168     } else {
169         idx = state_.oidCache.add(oid, &found);
170     }
171     if (found) {
172         write8(buffer, 0);
173     } else {
174         writeString(buffer, oid);
175     }
176     write16(buffer, idx);
177 }
178 
writeTid(std::vector<unsigned char> * buffer,rtl::ByteSequence const & tid)179 void Marshal::writeTid(
180     std::vector< unsigned char > * buffer, rtl::ByteSequence const & tid)
181 {
182     bool found;
183     sal_uInt16 idx = state_.tidCache.add(tid, &found);
184     if (found) {
185         write8(buffer, 0);
186     } else {
187         sal_Sequence * p = tid.getHandle();
188         writeValue(
189             buffer,
190             css::uno::TypeDescription(
191                 cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get()), &p);
192     }
193     write16(buffer, idx);
194 }
195 
writeValue(std::vector<unsigned char> * buffer,css::uno::TypeDescription const & type,void const * value)196 void Marshal::writeValue(
197     std::vector< unsigned char > * buffer,
198     css::uno::TypeDescription const & type, void const * value)
199 {
200     OSL_ASSERT(buffer != 0 && type.is());
201     type.makeComplete();
202     switch (type.get()->eTypeClass) {
203     case typelib_TypeClass_VOID:
204         break;
205     case typelib_TypeClass_BOOLEAN:
206         OSL_ASSERT(*static_cast< sal_uInt8 const * >(value) <= 1);
207         // fall through
208     case typelib_TypeClass_BYTE:
209         write8(buffer, *static_cast< sal_uInt8 const * >(value));
210         break;
211     case typelib_TypeClass_SHORT:
212     case typelib_TypeClass_UNSIGNED_SHORT:
213     case typelib_TypeClass_CHAR:
214         write16(buffer, *static_cast< sal_uInt16 const * >(value));
215         break;
216     case typelib_TypeClass_LONG:
217     case typelib_TypeClass_UNSIGNED_LONG:
218     case typelib_TypeClass_FLOAT:
219     case typelib_TypeClass_ENUM:
220         write32(buffer, *static_cast< sal_uInt32 const * >(value));
221         break;
222     case typelib_TypeClass_HYPER:
223     case typelib_TypeClass_UNSIGNED_HYPER:
224     case typelib_TypeClass_DOUBLE:
225         write64(buffer, *static_cast< sal_uInt64 const * >(value));
226         break;
227     case typelib_TypeClass_STRING:
228         writeString(
229             buffer,
230             rtl::OUString(*static_cast< rtl_uString * const * >(value)));
231         break;
232     case typelib_TypeClass_TYPE:
233         writeType(
234             buffer,
235             css::uno::TypeDescription(
236                 *static_cast< typelib_TypeDescriptionReference * const * >(
237                     value)));
238         break;
239     case typelib_TypeClass_ANY:
240         {
241             uno_Any const * p = static_cast< uno_Any const * >(value);
242             css::uno::TypeDescription t(p->pType);
243             writeType(buffer, t);
244             writeValue(buffer, t, p->pData);
245             break;
246         }
247     case typelib_TypeClass_SEQUENCE:
248         {
249             sal_Sequence * p = *static_cast< sal_Sequence * const * >(value);
250             writeCompressed(buffer, static_cast< sal_uInt32 >(p->nElements));
251             css::uno::TypeDescription ctd(
252                 reinterpret_cast< typelib_IndirectTypeDescription * >(
253                     type.get())->
254                 pType);
255             OSL_ASSERT(ctd.is());
256             if (ctd.get()->eTypeClass == typelib_TypeClass_BYTE) {
257                 buffer->insert(
258                     buffer->end(), p->elements, p->elements + p->nElements);
259             } else {
260                 for (sal_Int32 i = 0; i != p->nElements; ++i) {
261                     writeValue(buffer, ctd, p->elements + i * ctd.get()->nSize);
262                 }
263             }
264             break;
265         }
266     case typelib_TypeClass_STRUCT:
267     case typelib_TypeClass_EXCEPTION:
268         writeMemberValues(buffer, type, value);
269         break;
270     case typelib_TypeClass_INTERFACE:
271         writeOid(
272             buffer,
273             bridge_->registerOutgoingInterface(
274                 css::uno::UnoInterfaceReference(
275                     *static_cast< uno_Interface * const * >(value)),
276                 type));
277         break;
278     default:
279         OSL_ASSERT(false); // this cannot happen
280         break;
281     }
282 }
283 
writeMemberValues(std::vector<unsigned char> * buffer,css::uno::TypeDescription const & type,void const * aggregateValue)284 void Marshal::writeMemberValues(
285     std::vector< unsigned char > * buffer,
286     css::uno::TypeDescription const & type, void const * aggregateValue)
287 {
288     OSL_ASSERT(
289         type.is() &&
290         (type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
291          type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
292         aggregateValue != 0);
293     type.makeComplete();
294     typelib_CompoundTypeDescription * ctd =
295         reinterpret_cast< typelib_CompoundTypeDescription * >(type.get());
296     if (ctd->pBaseTypeDescription != 0) {
297         writeMemberValues(
298             buffer,
299             css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase),
300             aggregateValue);
301     }
302     for (sal_Int32 i = 0; i != ctd->nMembers; ++i) {
303         writeValue(
304             buffer, css::uno::TypeDescription(ctd->ppTypeRefs[i]),
305             (static_cast< char const * >(aggregateValue) +
306              ctd->pMemberOffsets[i]));
307     }
308 }
309 
310 }
311