| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include "precompiled_bridges.hxx" |
| #include "sal/config.h" |
| |
| #include <cstddef> |
| #include <cstring> |
| #include <map> |
| #include <utility> |
| #include <vector> |
| |
| #include "bridges/cpp_uno/shared/arraypointer.hxx" |
| #include "com/sun/star/uno/Reference.hxx" |
| #include "com/sun/star/uno/RuntimeException.hpp" |
| #include "com/sun/star/uno/XInterface.hpp" |
| #include "com/sun/star/uno/genfunc.hxx" |
| #include "osl/diagnose.h" |
| #include "osl/mutex.hxx" |
| #include "rtl/strbuf.hxx" |
| #include "rtl/string.hxx" |
| #include "rtl/textenc.h" |
| #include "rtl/ustring.h" |
| #include "rtl/ustring.hxx" |
| #include "sal/types.h" |
| #include "typelib/typeclass.h" |
| #include "typelib/typedescription.h" |
| #include "uno/any2.h" |
| #include "uno/data.h" |
| #include "uno/mapping.h" |
| |
| #include "exceptions.hxx" |
| #include "flushcode.hxx" |
| |
| namespace { |
| |
| namespace css = com::sun::star; |
| |
| typedef void (* Function)(void *); |
| |
| Function toFunction(void * pointer) { |
| #pragma disable_warn |
| return reinterpret_cast< Function >(pointer); |
| #pragma enable_warn |
| } |
| |
| bool toUnoName(char const * rttiName, rtl::OUString * unoName) { |
| rtl::OStringBuffer buf; |
| for (;;) { |
| char const * p = std::strchr(rttiName, ':'); |
| if (p == NULL) { |
| buf.append(rttiName); |
| break; |
| } |
| if (p - rttiName > SAL_MAX_INT32) { |
| return false; |
| } |
| buf.append(rttiName, sal::static_int_cast< sal_Int32 >(p - rttiName)); |
| buf.append("."); |
| while (*p == ':') { |
| ++p; |
| } |
| rttiName = p; |
| } |
| *unoName = rtl::OStringToOUString( |
| buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8); |
| //TODO: check conversion failure |
| return true; |
| } |
| |
| class NistHash { |
| public: |
| NistHash(rtl::OString const & text); |
| |
| sal_uInt32 hashdata[5]; |
| |
| private: |
| static sal_uInt32 f1(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z) |
| { return z ^ (x & (y ^ z)); } |
| |
| static sal_uInt32 f2(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z) |
| { return x ^ y ^ z; } |
| |
| static sal_uInt32 f3(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z) |
| { return (x & y) + (z & (x ^ y)); } |
| |
| static sal_uInt32 rotl(sal_uInt32 value, sal_uInt32 bits) |
| { return (value << bits) | (value >> (32 - bits)); } |
| |
| sal_uInt32 expand_nostore(sal_uInt32 index) { |
| return data[index & 15] ^ data[(index - 14) & 15] ^ |
| data[(index - 8) & 15] ^ data[(index - 3) & 15]; |
| } |
| |
| sal_uInt32 expand_store(sal_uInt32 index) { |
| return data[index & 15] ^= data[(index - 14) & 15] ^ |
| data[(index - 8) & 15] ^ data[(index - 3) & 15]; |
| } |
| |
| void subRound( |
| sal_uInt32 a, sal_uInt32 & b, sal_uInt32 c, sal_uInt32 d, |
| sal_uInt32 & e, sal_uInt32 constant, sal_uInt32 datum, |
| sal_uInt32 function) |
| { |
| e += rotl(a, 5); |
| switch (function) { |
| case 1: |
| e += f1(b, c, d); |
| break; |
| case 2: |
| case 4: |
| e += f2(b, c, d); |
| break; |
| case 3: |
| e += f3(b, c, d); |
| break; |
| } |
| e += constant + datum; |
| b = rotl(b, 30); |
| } |
| |
| void transform(); |
| |
| sal_uInt32 data[16]; |
| }; |
| |
| NistHash::NistHash(rtl::OString const & text) { |
| hashdata[0] = 0x67452301; |
| hashdata[1] = 0xefcdab89; |
| hashdata[2] = 0x98badcfe; |
| hashdata[3] = 0x10325476; |
| hashdata[4] = 0xc3d2e1f0; |
| char const * p = text.getStr(); |
| sal_Int32 n = text.getLength(); |
| while (n >= sizeof data) { |
| std::memcpy(data, p, sizeof data); |
| p += sizeof data; |
| n -= sizeof data; |
| transform(); |
| } |
| std::memcpy(data, p, n); |
| reinterpret_cast< unsigned char *>(data)[n++] = 0x80; |
| if (n > sizeof data - 8) { |
| std::memset(reinterpret_cast< char * >(data) + n, 0, sizeof data - n); |
| transform(); |
| std::memset(data, 0, sizeof data - 8); |
| } else { |
| std::memset( |
| reinterpret_cast< char * >(data) + n, 0, sizeof data - 8 - n); |
| } |
| data[14] = 0; |
| data[15] = text.getLength() << 3; |
| transform(); |
| } |
| |
| void NistHash::transform() { |
| sal_uInt32 const K2 = 0x5A827999; |
| sal_uInt32 const K3 = 0x6ED9EBA1; |
| sal_uInt32 const K5 = 0x8F1BBCDC; |
| sal_uInt32 const K10 = 0xCA62C1D6; |
| sal_uInt32 a = hashdata[0]; |
| sal_uInt32 b = hashdata[1]; |
| sal_uInt32 c = hashdata[2]; |
| sal_uInt32 d = hashdata[3]; |
| sal_uInt32 e = hashdata[4]; |
| subRound(a, b, c, d, e, K2, data[ 0], 1); |
| subRound(e, a, b, c, d, K2, data[ 1], 1); |
| subRound(d, e, a, b, c, K2, data[ 2], 1); |
| subRound(c, d, e, a, b, K2, data[ 3], 1); |
| subRound(b, c, d, e, a, K2, data[ 4], 1); |
| subRound(a, b, c, d, e, K2, data[ 5], 1); |
| subRound(e, a, b, c, d, K2, data[ 6], 1); |
| subRound(d, e, a, b, c, K2, data[ 7], 1); |
| subRound(c, d, e, a, b, K2, data[ 8], 1); |
| subRound(b, c, d, e, a, K2, data[ 9], 1); |
| subRound(a, b, c, d, e, K2, data[10], 1); |
| subRound(e, a, b, c, d, K2, data[11], 1); |
| subRound(d, e, a, b, c, K2, data[12], 1); |
| subRound(c, d, e, a, b, K2, data[13], 1); |
| subRound(b, c, d, e, a, K2, data[14], 1); |
| subRound(a, b, c, d, e, K2, data[15], 1); |
| subRound(e, a, b, c, d, K2, expand_store(16), 1); |
| subRound(d, e, a, b, c, K2, expand_store(17), 1); |
| subRound(c, d, e, a, b, K2, expand_store(18), 1); |
| subRound(b, c, d, e, a, K2, expand_store(19), 1); |
| subRound(a, b, c, d, e, K3, expand_store(20), 2); |
| subRound(e, a, b, c, d, K3, expand_store(21), 2); |
| subRound(d, e, a, b, c, K3, expand_store(22), 2); |
| subRound(c, d, e, a, b, K3, expand_store(23), 2); |
| subRound(b, c, d, e, a, K3, expand_store(24), 2); |
| subRound(a, b, c, d, e, K3, expand_store(25), 2); |
| subRound(e, a, b, c, d, K3, expand_store(26), 2); |
| subRound(d, e, a, b, c, K3, expand_store(27), 2); |
| subRound(c, d, e, a, b, K3, expand_store(28), 2); |
| subRound(b, c, d, e, a, K3, expand_store(29), 2); |
| subRound(a, b, c, d, e, K3, expand_store(30), 2); |
| subRound(e, a, b, c, d, K3, expand_store(31), 2); |
| subRound(d, e, a, b, c, K3, expand_store(32), 2); |
| subRound(c, d, e, a, b, K3, expand_store(33), 2); |
| subRound(b, c, d, e, a, K3, expand_store(34), 2); |
| subRound(a, b, c, d, e, K3, expand_store(35), 2); |
| subRound(e, a, b, c, d, K3, expand_store(36), 2); |
| subRound(d, e, a, b, c, K3, expand_store(37), 2); |
| subRound(c, d, e, a, b, K3, expand_store(38), 2); |
| subRound(b, c, d, e, a, K3, expand_store(39), 2); |
| subRound(a, b, c, d, e, K5, expand_store(40), 3); |
| subRound(e, a, b, c, d, K5, expand_store(41), 3); |
| subRound(d, e, a, b, c, K5, expand_store(42), 3); |
| subRound(c, d, e, a, b, K5, expand_store(43), 3); |
| subRound(b, c, d, e, a, K5, expand_store(44), 3); |
| subRound(a, b, c, d, e, K5, expand_store(45), 3); |
| subRound(e, a, b, c, d, K5, expand_store(46), 3); |
| subRound(d, e, a, b, c, K5, expand_store(47), 3); |
| subRound(c, d, e, a, b, K5, expand_store(48), 3); |
| subRound(b, c, d, e, a, K5, expand_store(49), 3); |
| subRound(a, b, c, d, e, K5, expand_store(50), 3); |
| subRound(e, a, b, c, d, K5, expand_store(51), 3); |
| subRound(d, e, a, b, c, K5, expand_store(52), 3); |
| subRound(c, d, e, a, b, K5, expand_store(53), 3); |
| subRound(b, c, d, e, a, K5, expand_store(54), 3); |
| subRound(a, b, c, d, e, K5, expand_store(55), 3); |
| subRound(e, a, b, c, d, K5, expand_store(56), 3); |
| subRound(d, e, a, b, c, K5, expand_store(57), 3); |
| subRound(c, d, e, a, b, K5, expand_store(58), 3); |
| subRound(b, c, d, e, a, K5, expand_store(59), 3); |
| subRound(a, b, c, d, e, K10, expand_store(60), 4); |
| subRound(e, a, b, c, d, K10, expand_store(61), 4); |
| subRound(d, e, a, b, c, K10, expand_store(62), 4); |
| subRound(c, d, e, a, b, K10, expand_store(63), 4); |
| subRound(b, c, d, e, a, K10, expand_store(64), 4); |
| subRound(a, b, c, d, e, K10, expand_store(65), 4); |
| subRound(e, a, b, c, d, K10, expand_store(66), 4); |
| subRound(d, e, a, b, c, K10, expand_store(67), 4); |
| subRound(c, d, e, a, b, K10, expand_store(68), 4); |
| subRound(b, c, d, e, a, K10, expand_store(69), 4); |
| subRound(a, b, c, d, e, K10, expand_store(70), 4); |
| subRound(e, a, b, c, d, K10, expand_store(71), 4); |
| subRound(d, e, a, b, c, K10, expand_store(72), 4); |
| subRound(c, d, e, a, b, K10, expand_store(73), 4); |
| subRound(b, c, d, e, a, K10, expand_store(74), 4); |
| subRound(a, b, c, d, e, K10, expand_store(75), 4); |
| subRound(e, a, b, c, d, K10, expand_store(76), 4); |
| subRound(d, e, a, b, c, K10, expand_nostore(77), 4); |
| subRound(c, d, e, a, b, K10, expand_nostore(78), 4); |
| subRound(b, c, d, e, a, K10, expand_nostore(79), 4); |
| hashdata[0] += a; |
| hashdata[1] += b; |
| hashdata[2] += c; |
| hashdata[3] += d; |
| hashdata[4] += e; |
| } |
| |
| class RttiMap { |
| public: |
| static __Crun::static_type_info const * get( |
| typelib_CompoundTypeDescription const * type); |
| |
| private: |
| RttiMap(); // not defined |
| RttiMap(RttiMap &); // not defined |
| ~RttiMap(); // not defined |
| void operator =(RttiMap &); // not defined |
| |
| struct Data { |
| __Crun::static_type_info * info; |
| rtl::OString cppName; |
| std::vector< __Crun::class_base_descr > bases; |
| }; |
| typedef std::map< rtl::OUString, Data > Map; |
| |
| static void toCppNames( |
| rtl::OUString const & unoName, rtl::OString * cppName, |
| rtl::OString * rttiName); |
| |
| static Data const & get_(typelib_CompoundTypeDescription const * type); |
| |
| static osl::Mutex m_mutex; |
| static Map * m_map; |
| }; |
| |
| osl::Mutex RttiMap::m_mutex; |
| RttiMap::Map * RttiMap::m_map; |
| |
| __Crun::static_type_info const * RttiMap::get( |
| typelib_CompoundTypeDescription const * type) |
| { |
| osl::MutexGuard g(m_mutex); |
| if (m_map == NULL) { |
| m_map = new Map; // leaked |
| } |
| return get_(type).info; |
| } |
| |
| void RttiMap::toCppNames( |
| rtl::OUString const & unoName, rtl::OString * cppName, |
| rtl::OString * rttiName) |
| { |
| OSL_ASSERT(cppName != NULL && rttiName != NULL); |
| rtl::OStringBuffer bc; |
| rtl::OStringBuffer br; |
| br.append("__1n"); |
| for (sal_Int32 i = 0; i != -1;) { |
| rtl::OUString tok(unoName.getToken(0, '.', i)); |
| bc.append(rtl::OUStringToOString(tok, RTL_TEXTENCODING_UTF8)); |
| // conversion should never fail, as tok should be well-formed ASCII |
| if (i != -1) { |
| bc.append("::"); |
| } |
| sal_Int32 len = tok.getLength(); |
| sal_Int32 pos = br.getLength(); |
| for (sal_Int32 n = len / 26; n > 0; n /= 26) { |
| br.insert(pos, static_cast< char >('a' + (n % 26))); |
| } |
| br.append(static_cast< char >('A' + (len % 26))); |
| for (sal_Int32 j = 0; j < len; ++j) { |
| sal_Unicode c = tok[j]; |
| OSL_ASSERT( |
| c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || |
| c >= 'a' && c <= 'z'); |
| if (c == 'Q') { |
| br.append("QdD"); |
| } else { |
| br.append(static_cast< char >(c)); |
| } |
| } |
| } |
| br.append('_'); |
| *cppName = bc.makeStringAndClear(); |
| *rttiName = br.makeStringAndClear(); |
| } |
| |
| RttiMap::Data const & RttiMap::get_( |
| typelib_CompoundTypeDescription const * type) |
| { |
| rtl::OUString name(type->aBase.pTypeName); |
| Map::iterator it(m_map->find(name)); |
| if (it == m_map->end()) { |
| it = m_map->insert(std::make_pair(name, Data())).first; |
| Data & data = it->second; |
| rtl::OString rttiName; |
| toCppNames(name, &data.cppName, &rttiName); |
| data.info = new __Crun::static_type_info; |
| data.info->ty_name = data.cppName.getStr() - |
| reinterpret_cast< char * >(&data.info->ty_name); |
| data.info->reserved = 0; |
| NistHash hash(rttiName); |
| data.info->type_hash[0] = hash.hashdata[0]; |
| data.info->type_hash[1] = hash.hashdata[1]; |
| data.info->type_hash[2] = hash.hashdata[2]; |
| data.info->type_hash[3] = hash.hashdata[3]; |
| data.info->flags = 0; |
| data.info->cv_qualifiers = 0; |
| if (type->pBaseTypeDescription != NULL) { |
| data.bases = get_(type->pBaseTypeDescription).bases; |
| OSL_ASSERT(!data.bases.empty()); |
| data.bases.back().offset = 0; |
| } |
| __Crun::class_base_descr last; |
| last.type_hash[0] = data.info->type_hash[0]; |
| last.type_hash[1] = data.info->type_hash[1]; |
| last.type_hash[2] = data.info->type_hash[2]; |
| last.type_hash[3] = data.info->type_hash[3]; |
| last.offset = 0x8000000000000000; |
| data.bases.push_back(last); |
| data.info->base_table = reinterpret_cast< char * >(&data.bases[0]) - |
| reinterpret_cast< char * >(&data.info->base_table); |
| } |
| return it->second; |
| } |
| |
| void deleteException( |
| void * exception, unsigned int * thunk, typelib_TypeDescription * type) |
| { |
| uno_destructData( |
| exception, type, |
| reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); |
| typelib_typedescription_release(type); |
| delete[] thunk; |
| } |
| |
| } |
| |
| namespace bridges { namespace cpp_uno { namespace cc5_solaris_sparc64 { |
| |
| void raiseException(uno_Any * exception, uno_Mapping * unoToCpp) { |
| bridges::cpp_uno::shared::ArrayPointer< unsigned long > thunkPtr( |
| new unsigned long[4]); |
| typelib_TypeDescription * type = NULL; |
| typelib_typedescriptionreference_getDescription(&type, exception->pType); |
| __Crun::static_type_info const * rtti = RttiMap::get( |
| reinterpret_cast< typelib_CompoundTypeDescription * >(type)); |
| void * exc = __Crun::ex_alloc(type->nSize); |
| uno_copyAndConvertData(exc, exception->pData, type, unoToCpp); |
| uno_any_destruct(exception, NULL); |
| unsigned long * thunk = thunkPtr.release(); |
| // 0*4: rd %pc, %o1: |
| // 1*4: ldx %o1, (6-0)*4, %o3: |
| thunk[0] = 0x93414000D65A6018; |
| // 2*4: jmpl %o3, %g0, %g0: |
| // 3*4: ldx %o1, (4-0)*4, %o2: |
| thunk[1] = 0x81C2C000D45A6010; |
| // 4*4: .xword type: |
| thunk[2] = reinterpret_cast< unsigned long >(type); |
| // 6*4: .xword deleteException: |
| thunk[3] = reinterpret_cast< unsigned long >(deleteException); |
| flushCode(thunk, thunk + 4); |
| __Crun::ex_throw(exc, rtti, toFunction(thunk)); |
| } |
| |
| void fillUnoException( |
| void * cppException, char const * cppName, uno_Any * unoException, |
| uno_Mapping * cppToUno) |
| { |
| rtl::OUString name; |
| typelib_TypeDescription * type = NULL; |
| if (toUnoName(cppName, &name)) { |
| typelib_typedescription_getByName(&type, name.pData); |
| } |
| if (type == NULL || type->eTypeClass != typelib_TypeClass_EXCEPTION) { |
| css::uno::RuntimeException exc( |
| (rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM("Not a UNO exception type: ")) + |
| name), |
| css::uno::Reference< css::uno::XInterface >()); |
| uno_type_any_constructAndConvert( |
| unoException, &exc, getCppuType(&exc).getTypeLibType(), cppToUno); |
| } else { |
| uno_any_constructAndConvert(unoException, cppException, type, cppToUno); |
| } |
| if (type != NULL) { |
| typelib_typedescription_release(type); |
| } |
| } |
| |
| } } } |