summaryrefslogtreecommitdiff
path: root/configmgr/source/xml/valueconverter.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'configmgr/source/xml/valueconverter.cxx')
-rw-r--r--configmgr/source/xml/valueconverter.cxx504
1 files changed, 504 insertions, 0 deletions
diff --git a/configmgr/source/xml/valueconverter.cxx b/configmgr/source/xml/valueconverter.cxx
new file mode 100644
index 000000000000..116d70d1852c
--- /dev/null
+++ b/configmgr/source/xml/valueconverter.cxx
@@ -0,0 +1,504 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: valueconverter.cxx,v $
+ * $Revision: 1.23 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_configmgr.hxx"
+
+#include "valuetypeconverter.hxx"
+#include "typeconverter.hxx"
+
+inline sal_Bool rtl_ascii_isWhitespace( sal_Unicode ch )
+{
+ return ch <= 0x20 && ch;
+}
+
+namespace configmgr
+{
+// -----------------------------------------------------------------------------
+static
+void throwConversionError(sal_Char const* pErrorMsg) SAL_THROW((script::CannotConvertException))
+{
+ OSL_ENSURE(false, pErrorMsg);
+
+ script::CannotConvertException error;
+ error.Message = rtl::OUString::createFromAscii(pErrorMsg);
+ throw error;
+}
+// -----------------------------------------------------------------------------
+template <class Char>
+inline
+bool charInRange(Char ch, char from, char to) throw()
+{
+ return Char(from) <= ch && ch <= Char(to);
+}
+
+// -----------------------------------------------------------------------------
+static
+inline
+unsigned makeHexNibble(unsigned char ch) SAL_THROW((script::CannotConvertException))
+{
+ unsigned nRet = 0;
+
+ if (charInRange(ch, '0', '9')) nRet = ch - unsigned('0');
+
+ else if (charInRange(ch, 'a', 'f')) nRet = ch - unsigned('a' - 10u);
+
+ else if (charInRange(ch, 'A', 'F')) nRet = ch - unsigned('A' - 10u);
+
+ else throwConversionError("Invalid Hex Character in binary value");
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------------
+static
+inline
+unsigned readHexNibble(sal_Unicode ch) SAL_THROW((script::CannotConvertException))
+{
+ if (!charInRange(ch, 0, 127)) throwConversionError("Non-Ascii Character in binary value");
+
+ return makeHexNibble(static_cast<unsigned char>(ch));
+}
+
+// -----------------------------------------------------------------------------
+static
+inline
+unsigned int readHexByte(sal_Unicode const*& pStr) SAL_THROW((script::CannotConvertException))
+{
+ register unsigned int nHigh = readHexNibble(*pStr++);
+ register unsigned int nLow = readHexNibble(*pStr++);
+ return (nHigh << 4) | nLow;
+}
+
+// -----------------------------------------------------------------------------
+static
+void parseHexBinary(rtl::OUString const& aHexString_, uno::Sequence<sal_Int8>& rBinarySeq_)
+ SAL_THROW((script::CannotConvertException , com::sun::star::uno::RuntimeException))
+{
+ // PRE: aBinaryString with HexCode
+ // POST: rBinarySeq with the to Hex converted String
+
+ sal_uInt32 nCount = aHexString_.getLength();
+ sal_Unicode const * pHex = aHexString_.getStr();
+
+ if (nCount % 2) throwConversionError("Hex string has odd number of characters");
+ nCount /= 2;
+
+ rBinarySeq_.realloc(nCount);
+ sal_Int8 * pBinary = rBinarySeq_.getArray();
+
+ while (nCount--)
+ {
+ *pBinary++ = static_cast<sal_Int8>(readHexByte(pHex));
+ }
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+uno::Sequence<sal_Int8> ValueConverter::parseBinary(rtl::OUString const& aBinaryString_) const
+ SAL_THROW((script::CannotConvertException, com::sun::star::uno::RuntimeException))
+{
+ uno::Sequence<sal_Int8> aResultSeq;
+
+ parseHexBinary(aBinaryString_,aResultSeq);
+
+ return aResultSeq;
+}
+
+// -----------------------------------------------------------------------------
+static inline
+uno::Type getBinaryType()
+{
+ uno::Sequence<sal_Int8> const * const for_binary = 0;
+ return ::getCppuType(for_binary);
+}
+
+// -----------------------------------------------------------------------------
+bool ValueConverter::isList() const
+{
+ return m_aType.getTypeClass() == uno::TypeClass_SEQUENCE &&
+ m_aType != getBinaryType();
+}
+
+// -----------------------------------------------------------------------------
+uno::Any ValueConverter::convertToAny(rtl::OUString const& aContent) const
+ SAL_THROW((script::CannotConvertException, com::sun::star::uno::RuntimeException))
+{
+ uno::Any aValue;
+
+ if (this->isNull())
+ {
+ OSL_ENSURE(aContent.trim().getLength() == 0, "ValueConverter: Non-empty Null Value - ignoring content");
+ OSL_ASSERT(!aValue.hasValue());
+ }
+
+ else if (this->isList())
+ {
+ std::vector< rtl::OUString > aContentList;
+ splitListData(aContent, aContentList);
+ convertListToAny(aContentList, aValue);
+ }
+
+ else
+ {
+ convertScalarToAny(aContent, aValue);
+ }
+
+ return aValue;
+}
+
+// -----------------------------------------------------------------------------
+bool ValueConverter::convertScalarToAny(rtl::OUString const& aContent, uno::Any& rValue) const
+ SAL_THROW((script::CannotConvertException , com::sun::star::uno::RuntimeException))
+{
+ OSL_PRECOND(!this->isNull(),"ValueConverter::convertScalarToAny - check for NULL before calling");
+ OSL_ENSURE(m_aType.getTypeClass() != uno::TypeClass_ANY,"'Any' values must be NULL");
+
+ // check for Binary
+ if (m_aType == getBinaryType())
+ {
+ com::sun::star::uno::Sequence<sal_Int8> aBinarySeq = parseBinary(aContent);
+ rValue <<= aBinarySeq;
+ }
+
+ else
+ {
+ rValue = toAny(m_xTypeConverter, aContent, m_aType.getTypeClass());
+ }
+
+ return !! rValue.hasValue();
+}
+
+// -----------------------------------------------------------------------------
+template <class T>
+bool convertListToSequence(std::vector< rtl::OUString > const& aStringList, uno::Sequence< T >& rSequence, uno::TypeClass aElementTypeClass, ValueConverter const& rConverter)
+ SAL_THROW((script::CannotConvertException , com::sun::star::uno::RuntimeException))
+{
+ OSL_ASSERT(aElementTypeClass == ::getCppuType(static_cast<T const*>(0)).getTypeClass());
+
+ rSequence.realloc(aStringList.size());
+
+ sal_uInt32 nPos = 0;
+
+ for(std::vector< rtl::OUString >::const_iterator it = aStringList.begin();
+ it != aStringList.end();
+ ++it)
+ {
+ uno::Any aValueAny = toAny(rConverter.getTypeConverter(), *it, aElementTypeClass);
+
+ if (aValueAny >>= rSequence[nPos])
+ ++nPos;
+
+ else if (!aValueAny.hasValue())
+ OSL_ENSURE(false,"UNEXPECTED: Found NULL value in List - ignoring value !");
+
+ else
+ OSL_ENSURE(false,"ERROR: Cannot extract converted value into List - skipping value !");
+ }
+
+ bool bOK = (nPos == aStringList.size());
+
+ if (!bOK)
+ {
+ OSL_ASSERT(nPos < aStringList.size());
+ rSequence.realloc(nPos);
+ }
+ return bOK;
+}
+
+// -----------------------------------------------------------------------------
+// special conversion for string sequence
+
+static
+inline
+void stringListToSequence(uno::Sequence< rtl::OUString > & rSequence, std::vector< rtl::OUString > const & aStringList)
+{
+ rSequence .realloc( aStringList.size() );
+
+ std::copy( aStringList.begin(), aStringList.end(), rSequence.getArray() );
+}
+// -----------------------------------------------------------------------------
+
+static
+inline
+std::vector< rtl::OUString > sequenceToStringList(uno::Sequence< rtl::OUString > const & aSequence)
+{
+ rtl::OUString const * const pBegin = aSequence.getConstArray();
+ rtl::OUString const * const pEnd = pBegin + aSequence.getLength();
+
+ return std::vector< rtl::OUString >(pBegin,pEnd);
+}
+// -----------------------------------------------------------------------------
+
+uno::Sequence< rtl::OUString > ValueConverter::splitStringList(rtl::OUString const& aContent) const
+{
+ std::vector< rtl::OUString > aList;
+ splitListData(aContent, aList);
+
+ uno::Sequence< rtl::OUString > aResult;
+ stringListToSequence(aResult,aList);
+
+ return aResult;
+}
+// -----------------------------------------------------------------------------
+
+uno::Any ValueConverter::convertListToAny(uno::Sequence< rtl::OUString > const& aContentList) const
+ SAL_THROW((script::CannotConvertException , com::sun::star::uno::RuntimeException))
+{
+ uno::Any aResult;
+ std::vector< rtl::OUString > const aStringList = sequenceToStringList(aContentList);
+ convertListToAny(aStringList,aResult);
+ return aResult;
+}
+// -----------------------------------------------------------------------------
+// special overload for binary sequence
+
+// template<> // use an explicit specialization
+bool convertListToSequence(std::vector< rtl::OUString > const& aStringList, uno::Sequence< uno::Sequence<sal_Int8> >& rSequence, uno::TypeClass aElementTypeClass, ValueConverter const& rParser )
+ SAL_THROW((script::CannotConvertException , com::sun::star::uno::RuntimeException))
+{
+ { (void)aElementTypeClass; }
+ OSL_ASSERT(aElementTypeClass == uno::TypeClass_SEQUENCE);
+
+ rSequence.realloc(aStringList.size());
+
+ sal_uInt32 nPos = 0;
+
+ for(std::vector< rtl::OUString >::const_iterator it = aStringList.begin();
+ it != aStringList.end();
+ ++it)
+ {
+ rSequence[nPos++] = rParser.parseBinary(*it);
+ }
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// special overload for string sequence
+
+// template<> // use an explicit specialization
+bool convertListToSequence(std::vector< rtl::OUString > const& aStringList, uno::Sequence< rtl::OUString >& rSequence, uno::TypeClass aElementTypeClass, ValueConverter const& /*rParser*/ )
+ SAL_THROW((script::CannotConvertException , com::sun::star::uno::RuntimeException))
+{
+ { (void)aElementTypeClass; }
+ OSL_ASSERT(aElementTypeClass == uno::TypeClass_STRING);
+
+ stringListToSequence(rSequence, aStringList);
+
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+#define MAYBE_EXTRACT_SEQUENCE( type ) \
+ if (aElementType == ::getCppuType( (type const *)0)) \
+ { \
+ com::sun::star::uno::Sequence< type > aSequence; \
+ convertListToSequence(aContentList,aSequence,aElementTypeClass, *this); \
+ rValue <<= aSequence; \
+ }
+
+bool ValueConverter::convertListToAny(std::vector< rtl::OUString > const& aContentList, uno::Any& rValue) const
+ SAL_THROW((script::CannotConvertException , com::sun::star::uno::RuntimeException))
+{
+ OSL_PRECOND(!this->isNull(),"ValueConverter::convertListToAny - check for NULL before calling");
+ OSL_ENSURE(m_aType.getTypeClass() == uno::TypeClass_SEQUENCE,"'Any' not allowed for lists");
+
+ uno::Type aElementType = getSequenceElementType(m_aType);
+ uno::TypeClass aElementTypeClass = aElementType.getTypeClass();
+
+ OSL_ENSURE(aElementTypeClass != uno::TypeClass_ANY,"'Any' not allowed for list elements");
+
+ MAYBE_EXTRACT_SEQUENCE( rtl::OUString )
+ else
+ MAYBE_EXTRACT_SEQUENCE( sal_Bool )
+ else
+ MAYBE_EXTRACT_SEQUENCE( sal_Int16 )
+ else
+ MAYBE_EXTRACT_SEQUENCE( sal_Int32 )
+ else
+ MAYBE_EXTRACT_SEQUENCE( sal_Int64 )
+ else
+ MAYBE_EXTRACT_SEQUENCE( double )
+ else
+ MAYBE_EXTRACT_SEQUENCE( com::sun::star::uno::Sequence<sal_Int8> )
+ else
+ {
+ OSL_ENSURE(false, "Unknown element type in list");
+ throwConversionError("Invalid value-type found in list value");
+ }
+
+ return !! rValue.hasValue();
+}
+#undef MAYBE_EXTRACT_SEQUENCE
+
+// -----------------------------------------------------------------------------
+namespace
+{
+ sal_Int32 const NO_MORE_TOKENS = -1;
+ struct OTokenizeByWhitespace
+ {
+
+ static inline bool isWhitespace(sal_Unicode ch)
+ {
+ // note: for definition of whitescape see also
+ // canUseWhitespace(rtl::OUString const&)
+ // in xmlformater.cxx
+ // -----------------------------------------------------------------------------
+ return rtl_ascii_isWhitespace(ch) ? true : false;
+ }
+
+ sal_Int32 findFirstTokenStart(rtl::OUString const& sText) const SAL_THROW(())
+ {
+ return findNextTokenStart(sText,0);
+ }
+
+ sal_Int32 findNextTokenStart(rtl::OUString const& sText, sal_Int32 nPrevTokenEnd) const SAL_THROW(())
+ {
+ sal_Int32 const nEnd = sText.getLength();
+ sal_Int32 nPos = nPrevTokenEnd;
+
+ OSL_PRECOND( nPos == 0 || (0 < nPos && nPos < nEnd && isWhitespace(sText[nPos])) || nPos == nEnd,
+ "Invalid nPrevTokenEnd");
+
+ while (nPos < nEnd && isWhitespace(sText[nPos]))
+ {
+ ++nPos;
+ }
+
+ if (nPos < nEnd)
+ return nPos;
+ else
+ return NO_MORE_TOKENS;
+ }
+
+ sal_Int32 findTokenEnd(rtl::OUString const& sText, sal_Int32 nTokenStart) const SAL_THROW(())
+ {
+ sal_Int32 const nEnd = sText.getLength();
+ sal_Int32 nPos = nTokenStart;
+
+ OSL_PRECOND( 0 <= nPos && nPos < nEnd && !isWhitespace(sText[nPos]),
+ "Invalid nTokenStart");
+
+ while (nPos < nEnd && !isWhitespace(sText[nPos]))
+ {
+ ++nPos;
+ }
+
+ return nPos;
+ }
+ };
+// -----------------------------------------------------------------------------
+ struct OTokenizeBySeparator
+ {
+ rtl::OUString const sSeparator;
+ OTokenizeBySeparator(rtl::OUString const& _sSeparator) SAL_THROW(())
+ : sSeparator(_sSeparator)
+ {
+ OSL_PRECOND(sSeparator.trim().getLength() > 0, "Invalid empty separator string");
+ }
+
+ sal_Int32 findFirstTokenStart(rtl::OUString const& /*sText*/) const SAL_THROW(())
+ {
+ return 0;
+ }
+ sal_Int32 findNextTokenStart(rtl::OUString const& sText, sal_Int32 nPrevTokenEnd) const SAL_THROW(())
+ {
+ sal_Int32 const nEnd = sText.getLength();
+ sal_Int32 nPos = nPrevTokenEnd;
+ OSL_PRECOND( nPos == nEnd || (0 <= nPos && nPos < nEnd && sText.indexOf(sSeparator, nPos) == nPos),
+ "Invalid nPrevTokenEnd");
+
+ if (nPos < nEnd)
+ return nPos + sSeparator.getLength();
+ else
+ return NO_MORE_TOKENS;
+ }
+ sal_Int32 findTokenEnd(rtl::OUString const& sText, sal_Int32 nTokenStart) const SAL_THROW(())
+ {
+ sal_Int32 const nEnd = sText.getLength();
+ OSL_PRECOND( 0 <= nTokenStart && nTokenStart <= nEnd ,
+ "Invalid nTokenStart");
+
+ sal_Int32 nPos = sText.indexOf(sSeparator,nTokenStart);
+
+ if (nPos >= 0)
+ return nPos;
+ else
+ return nEnd;
+ }
+ };
+// -----------------------------------------------------------------------------
+ template <class Tokenizer>
+ void tokenizeListData(Tokenizer const& aTokenizer, rtl::OUString const& aContent, std::vector< rtl::OUString >& rContentList)
+ SAL_THROW(())
+ {
+ sal_Int32 nTokenPos = aTokenizer.findFirstTokenStart(aContent);
+
+ while(nTokenPos != NO_MORE_TOKENS)
+ {
+ sal_Int32 nTokenEnd = aTokenizer.findTokenEnd(aContent, nTokenPos);
+
+ // this is what the tokenizer must provide
+ OSL_ASSERT(0 <= nTokenPos && nTokenPos <= nTokenEnd && nTokenEnd <= aContent.getLength());
+
+ rContentList.push_back( aContent.copy(nTokenPos, nTokenEnd-nTokenPos) );
+
+ nTokenPos= aTokenizer.findNextTokenStart(aContent, nTokenEnd);
+ }
+ }
+// -----------------------------------------------------------------------------
+}
+// -----------------------------------------------------------------------------
+void ValueConverter::splitListData(rtl::OUString const& aContent, std::vector< rtl::OUString >& rContentList) const
+ SAL_THROW(())
+{
+ rtl::OUString sSeparator = m_sSeparator;
+
+ bool bSeparateByWhitespace = (sSeparator.trim().getLength() == 0);
+
+ if (bSeparateByWhitespace)
+ {
+ OSL_ENSURE( sSeparator.getLength()==0 || sSeparator.equalsAscii(" "),
+ "Unexpected whitespace-only separator");
+
+ tokenizeListData( OTokenizeByWhitespace(), aContent, rContentList );
+ }
+ else
+ {
+ OSL_ENSURE( sSeparator.trim()==sSeparator,
+ "Unexpected whitespace in separator");
+
+ tokenizeListData( OTokenizeBySeparator(sSeparator), aContent, rContentList );
+ }
+}
+// -----------------------------------------------------------------------------
+
+} // namespace