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