123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842 |
- /*
- * Copyright 2005 - 2016 Zarafa and its licensors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #ifndef convert_INCLUDED
- #define convert_INCLUDED
- #include <kopano/zcdefs.h>
- #include <map>
- #include <set>
- #include <list>
- #include <string>
- #include <stdexcept>
- #include <typeinfo>
- #include <iconv.h>
- #include <kopano/charset/traits.h>
- namespace KC {
- /**
- * @brief Exception class
- */
- class convert_exception : public std::runtime_error {
- public:
- enum exception_type {
- eUnknownCharset,
- eIllegalSequence
- };
- convert_exception(enum exception_type type, const std::string &message);
-
- enum exception_type type() const {
- return m_type;
- }
-
- private:
- enum exception_type m_type;
- };
- /**
- * @brief Unknown charset
- */
- class _kc_export_throw unknown_charset_exception _kc_final :
- public convert_exception {
- public:
- unknown_charset_exception(const std::string &message);
- };
- /**
- * @brief Illegal sequence
- */
- class _kc_export_throw illegal_sequence_exception _kc_final :
- public convert_exception {
- public:
- illegal_sequence_exception(const std::string &message);
- };
- namespace details {
- /**
- * @brief Performs the generic iconv processing.
- */
- class _kc_export iconv_context_base {
- public:
- /**
- * @brief Destructor.
- */
- virtual ~iconv_context_base();
-
- protected:
- /**
- * @brief Constructor.
- *
- * @param[in] tocode The destination charset.
- * @param[out] fromcode The source charset.
- */
- iconv_context_base(const char* tocode, const char* fromcode);
-
- /**
- * @brief Performs the actual conversion.
- *
- * Performs the conversion and stores the result in the output string
- * by calling append, which must be overridden by a derived class.
- * @param[in] lpFrom Pointer to the source data.
- * @param[in] cbFrom Size of the source data in bytes.
- */
- void doconvert(const char *lpFrom, size_t cbFrom);
-
- private:
- /**
- * @brief Appends converted data to the result.
- *
- * @param[in] lpBuf Pointer to the data to be appended.
- * @param[in] cbBuf Size of the data to be appended in bytes.
- */
- _kc_hidden virtual void append(const char *buf, size_t bufsize) = 0;
-
- iconv_t m_cd;
- bool m_bForce;
- bool m_bHTML;
-
- iconv_context_base(const iconv_context_base &) = delete;
- iconv_context_base &operator=(const iconv_context_base &) = delete;
- };
- /**
- * @brief Default converter from one charset to another with string types.
- */
- template <typename _To_Type, typename _From_Type>
- class _kc_export_dycast iconv_context _kc_final :
- public iconv_context_base {
- public:
- /**
- * @brief Contructor.
- *
- * Constructs a iconv_context_base with the right tocode and fromcode based
- * on the _To_Type and _From_Type template parameters.
- */
- iconv_context()
- : iconv_context_base(iconv_charset<_To_Type>::name(), iconv_charset<_From_Type>::name())
- {}
-
- /**
- * @brief Contructor.
- *
- * Constructs a iconv_context_base with the tocode based on the _To_Type
- * and the passed fromcode.
- */
- iconv_context(const char *fromcode)
- : iconv_context_base(iconv_charset<_To_Type>::name(), fromcode)
- {}
-
- /**
- * @brief Contructor.
- *
- * Constructs a iconv_context_base with the tocode based on the _To_Type
- * and the passed fromcode.
- */
- iconv_context(const char *tocode, const char *fromcode)
- : iconv_context_base(tocode, fromcode)
- {}
- /**
- * @brief Performs the conversion.
- *
- * The actual conversion in delegated to iconv_context_base.
- * @param[in] lpRaw Raw pointer to the data to be converted.
- * @param[in] cbRaw The size in bytes of the data to be converted.
- * @return The converted string.
- */
- _To_Type convert(const char *lpRaw, size_t cbRaw) {
- m_to.clear();
- doconvert(lpRaw, cbRaw);
- return m_to;
- }
-
- /**
- * @brief Performs the conversion.
- *
- * The actual conversion in delegated to iconv_context_base.
- * @param[in] _from The string to be converted.
- * @return The converted string.
- */
- _To_Type convert(const _From_Type &_from) {
- return convert(iconv_charset<_From_Type>::rawptr(_from), iconv_charset<_From_Type>::rawsize(_from));
- }
-
- private:
- _kc_hidden void append(const char *lpBuf, size_t cbBuf) _kc_override
- {
- m_to.append(reinterpret_cast<typename _To_Type::const_pointer>(lpBuf), cbBuf / sizeof(typename _To_Type::value_type));
- }
- _To_Type m_to;
- };
- /**
- * @brief Helper class for converting from one charset to another.
- *
- * The converter_helper class detects when the to and from charsets are identical. In
- * that case the string is merely copied.
- */
- template<typename _Type> class convert_helper _kc_final {
- public:
- /**
- * @brief Converts a string to a string with the same charset.
- *
- * Effectively this method does nothing but a copy.
- * @param[in] _from The string to be converted.
- * @return The converted string.
- */
- static _Type convert(const _Type &_from) { return _from; }
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * The string with a charset linked to _Other_Type is converted to a
- * string with a charset linked to _Type.
- * @param[in] _from The string to be converted.
- * @return The converted string.
- */
- template <typename _Other_Type>
- static _Type convert(const _Other_Type &_from) {
- details::iconv_context<_Type, _Other_Type> context;
- return context.convert(_from);
- }
- };
- } // namespace details
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * This is the function to call when a one of conversion from one charset to
- * another is required. The to- and from charsets are implicitly determined by
- * on one side the passed _To_Type and on the other side the _from argument.
- * @tparam _To_Type The type of the destination string.
- * @param[in] _from The string that is to be converted to another charset.
- * @return The converted string.
- *
- * @note Since this method needs to create an iconv object internally
- * it is better to use a convert_context when multiple conversions
- * need to be performed.
- */
- template <typename _To_Type, typename _From_Type>
- inline _To_Type convert_to(const _From_Type &_from)
- {
- return details::convert_helper<_To_Type>::convert(_from);
- }
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * This is the function to call when a one of conversion from one charset to
- * another is required. The to charset is implicitly determined by
- * the passed _To_Type. The from charset is determined by fromcode.
- * @tparam _To_Type The type of the destination string.
- * @param[in] _from The string that is to be converted to another charset.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @return The converted string.
- *
- * @note Since this method needs to create an iconv object internally
- * it is better to use a convert_context when multiple conversions
- * need to be performed.
- */
- template <typename _To_Type, typename _From_Type>
- inline _To_Type convert_to(const _From_Type &_from, size_t cbBytes, const char *fromcode)
- {
- details::iconv_context<_To_Type, _From_Type> context(fromcode);
- return context.convert(iconv_charset<_From_Type>::rawptr(_from), cbBytes);
- }
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * This is the function to call when a one of conversion from one charset to
- * another is required. The to charset is determined by tocode.
- * The from charset is determined by fromcode.
- * @param[in] tocode The destination charset.
- * @param[in] _from The string that is to be converted to another charset.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @return The converted string.
- *
- * @note Since this method needs to create an iconv object internally
- * it is better to use a convert_context when multiple conversions
- * need to be performed.
- */
- template <typename _To_Type, typename _From_Type>
- inline _To_Type convert_to(const char *tocode, const _From_Type &_from, size_t cbBytes, const char *fromcode)
- {
- details::iconv_context<_To_Type, _From_Type> context(tocode, fromcode);
- return context.convert(iconv_charset<_From_Type>::rawptr(_from), cbBytes);
- }
- /**
- * @brief Allows multiple conversions within the same context.
- *
- * The convert_context class is used to perform multiple conversions within the
- * same context. This basically means that the details::iconv_context classes can
- * be reused, removing the need to recreate them for each conversion.
- */
- class _kc_export convert_context _kc_final {
- public:
- /**
- * @brief Constructor.
- */
- convert_context(void) = default;
-
- /**
- * @brief Destructor.
- */
- ~convert_context();
- /**
- * @brief Converts a string to a string wirh a different charset.
- *
- * The to- and from charsets are implicitly determined by on one side the
- * passed _To_Type and on the other side the _from argument.
- * @tparam _To_Type The type of the destination string.
- * @param[in] _from The string that is to be converted to another charset.
- * @return The converted string.
- */
- template <typename _To_Type, typename _From_Type>
- _kc_hidden _To_Type convert_to(const _From_Type &_from)
- {
- return helper<_To_Type>(*this).convert(_from);
- }
-
- /**
- * @brief Converts a string to a string wirh a different charset.
- *
- * The to charset is implicitly determined by the passed _To_Type.
- * The from charset is passed in fromcode.
- * @tparam _To_Type The type of the destination string.
- * @param[in] _from The string that is to be converted to another charset.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @return The converted string.
- */
- template <typename _To_Type, typename _From_Type>
- _kc_hidden _To_Type convert_to(const _From_Type &_from, size_t cbBytes,
- const char *fromcode)
- {
- return helper<_To_Type>(*this).convert(_from, cbBytes, fromcode);
- }
-
- /**
- * @brief Converts a string to a string wirh a different charset.
- *
- * The to charset is passed in tocode.
- * The from charset is passed in fromcode.
- * @param[in] tocode the destination charset.
- * @param[in] _from The string that is to be converted to another charset.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @return The converted string.
- */
- template <typename _To_Type, typename _From_Type>
- _kc_hidden _To_Type convert_to(const char *tocode,
- const _From_Type &_from, size_t cbBytes, const char *fromcode)
- {
- return helper<_To_Type>(*this).convert(tocode, _from, cbBytes, fromcode);
- }
-
- private:
- /**
- * @brief Helper class for converting from one charset to another.
- *
- * The convert_context::helper class detects when the to and from charsets are
- * identical. In that case the string is merely copied.
- */
- template<typename _Type> class _kc_hidden helper _kc_final {
- public:
- /**
- * @brief Constructor.
- */
- helper(convert_context &context)
- : m_context(context)
- {}
- /**
- * @brief Converts a string to a string with the same charset.
- *
- * Effectively this method does nothing but a copy.
- * @param[in] _from The string to be converted.
- * @return The converted string.
- */
- _Type convert(const _Type &_from) {
- return _from;
- }
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * The string with a charset linked to _Other_Type is converted to a
- * string with a charset linked to _Type. The actual conversion is
- * delegated to a iconv_context obtained through get_context().
- * @param[in] _from The string to be converted.
- * @return The converted string.
- */
- template <typename _Other_Type>
- _Type convert(const _Other_Type &_from) {
- return m_context.get_context<_Type, _Other_Type>()->convert(_from);
- }
-
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * The string with a charset specified with fromcode is converted to a
- * string with a charset linked to _Type. The actual conversion is
- * delegated to a iconv_context obtained through get_context().
- * @param[in] _from The string to be converted.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @return The converted string.
- */
- template <typename _Other_Type>
- _Type convert(const _Other_Type &_from, size_t cbBytes, const char *fromcode) {
- return m_context.get_context<_Type, _Other_Type>(fromcode)->convert(iconv_charset<_Other_Type>::rawptr(_from), cbBytes);
- }
-
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * The string with a charset specified with fromcode is converted to a
- * string with a charset specified with tocode. The actual conversion is
- * delegated to a iconv_context obtained through get_context().
- * @param[in] tocode The destination charset.
- * @param[in] _from The string to be converted.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @return The converted string.
- */
- template <typename _Other_Type>
- _Type convert(const char *tocode, const _Other_Type &_from, size_t cbBytes, const char *fromcode) {
- return m_context.get_context<_Type, _Other_Type>(tocode, fromcode)->convert(iconv_charset<_Other_Type>::rawptr(_from), cbBytes);
- }
-
- private:
- convert_context &m_context;
- };
-
- /**
- * @brief Helper class for converting from one charset to another.
- *
- * This specialization is used to convert to pointer types. In that case the
- * result needs to be stores to guarantee storage of the data. Without this
- * the caller will end up with a pointer to non-existing data.
- */
- template<typename _Type> class _kc_hidden helper<_Type *> _kc_final {
- public:
- typedef std::basic_string<_Type> string_type;
-
- /**
- * @brief Constructor.
- */
- helper(convert_context &context)
- : m_context(context)
- , m_helper(context)
- {}
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * The string with a charset linked to _Other_Type is converted to a
- * string with a charset linked to _Type. The actual conversion is
- * delegated to a iconv_context obtained through get_context().
- * @param[in] _from The string to be converted.
- * @return The converted string.
- */
- template <typename _Other_Type>
- _Type* convert(const _Other_Type &_from) {
- string_type s = m_helper.convert(_from);
- return m_context.persist_string(s);
- }
-
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * The string with a charset specified with fromcode is converted to a
- * string with a charset linked to _Type. The actual conversion is
- * delegated to a iconv_context obtained through get_context().
- * @param[in] _from The string to be converted.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @return The converted string.
- */
- template <typename _Other_Type>
- _Type* convert(const _Other_Type &_from, size_t cbBytes, const char *fromcode) {
- string_type s = m_helper.convert(_from, cbBytes, fromcode);
- return m_context.persist_string(s);
- }
-
- /**
- * @brief Converts a string to a string with a different charset.
- *
- * The string with a charset specified with fromcode is converted to a
- * string with a charset specified with tocode. The actual conversion is
- * delegated to a iconv_context obtained through get_context().
- * @param[in] tocode The destination charset.
- * @param[in] _from The string to be converted.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @return The converted string.
- */
- template <typename _Other_Type>
- _Type* convert(const char *tocode, const _Other_Type &_from, size_t cbBytes, const char *fromcode) {
- string_type s = m_helper.convert(tocode, _from, cbBytes, fromcode);
- return m_context.persist_string(s);
- }
-
- private:
- convert_context &m_context;
- helper<string_type> m_helper;
- };
-
- /**
- * @brief Key for the context_map;
- */
- struct context_key {
- const char *totype;
- const char *tocode;
- const char *fromtype;
- const char *fromcode;
- };
- /** Create a context_key based on the to- and from types and optionaly the to- and from codes.
- *
- * @tparam _To_Type
- * The destination type.
- * @tparam _From_Type
- * The source type.
- * @param[in] tocode
- * The destination encoding. NULL for autodetect (based on _To_Type).
- * @param[in] fromcode
- * The source encoding. NULL for autodetect (based on_From_Type).
- *
- * @return The new context_key
- */
- template <typename _To_Type, typename _From_Type>
- _kc_hidden context_key create_key(const char *tocode,
- const char *fromcode)
- {
- context_key key = {
- typeid(_To_Type).name(),
- (tocode ? tocode : iconv_charset<_To_Type>::name()),
- typeid(_From_Type).name(),
- (fromcode ? fromcode : iconv_charset<_From_Type>::name())
- };
- return key;
- }
- /**
- * @brief Sort predicate for the context_map;
- */
- class _kc_hidden context_predicate _kc_final {
- public:
- bool operator()(const context_key &lhs, const context_key &rhs) const {
- int r = strcmp(lhs.fromtype, rhs.fromtype);
- if (r != 0)
- return (r < 0);
- r = strcmp(lhs.totype, rhs.totype);
- if (r != 0)
- return (r < 0);
- r = strcmp(lhs.fromcode, rhs.fromcode);
- if (r != 0)
- return (r < 0);
- return (strcmp(lhs.tocode, rhs.tocode) < 0);
- }
- };
-
- /**
- * @brief Map containing contexts that can be reused.
- */
- typedef std::map<context_key, details::iconv_context_base*, context_predicate> context_map;
- /**
- * @brief Set containing dynamic allocated from- and to codes.
- */
- typedef std::set<const char*> code_set;
-
- /**
- * @brief Obtains an iconv_context object.
- *
- * The correct iconv_context is based on _To_Type and _From_Type and is
- * obtained from the context_map. If the correct iconv_context is not found a new
- * one is created and stored in the context_map;
- * @tparam _To_Type The type of the destination string.
- * @tparam _From_Type The type of the source string.
- * @return A pointer to a iconv_context.
- */
- template <typename _To_Type, typename _From_Type>
- _kc_hidden details::iconv_context<_To_Type, _From_Type> *get_context(void)
- {
- context_key key(create_key<_To_Type, _From_Type>(NULL, NULL));
- context_map::const_iterator iContext = m_contexts.find(key);
- if (iContext == m_contexts.cend()) {
- auto lpContext = new details::iconv_context<_To_Type, _From_Type>();
- iContext = m_contexts.insert(context_map::value_type(key, lpContext)).first;
- }
- return dynamic_cast<details::iconv_context<_To_Type, _From_Type>*>(iContext->second);
- }
-
- /**
- * @brief Obtains an iconv_context object.
- *
- * The correct iconv_context is based on _To_Type and fromcode and is
- * obtained from the context_map. If the correct iconv_context is not found a new
- * one is created and stored in the context_map;
- * @tparam _To_Type The type of the destination string.
- * @param[in] fromcode The source charset.
- * @return A pointer to a iconv_context.
- */
- template <typename _To_Type, typename _From_Type>
- _kc_hidden details::iconv_context<_To_Type, _From_Type> *
- get_context(const char *fromcode)
- {
- context_key key(create_key<_To_Type, _From_Type>(NULL, fromcode));
- context_map::const_iterator iContext = m_contexts.find(key);
- if (iContext == m_contexts.cend()) {
- auto lpContext = new details::iconv_context<_To_Type, _From_Type>(fromcode);
-
- // Before we store it, we need to copy the fromcode as we don't know what the
- // lifetime will be.
- persist_code(key, pfFromCode);
-
- iContext = m_contexts.insert(context_map::value_type(key, lpContext)).first;
- }
- return dynamic_cast<details::iconv_context<_To_Type, _From_Type>*>(iContext->second);
- }
- /**
- * @brief Obtains an iconv_context object.
- *
- * The correct iconv_context is based on tocode and fromcode and is
- * obtained from the context_map. If the correct iconv_context is not found a new
- * one is created and stored in the context_map;
- * @param[in] tocode The destination charset.
- * @param[in] fromcode The source charset.
- * @return A pointer to a iconv_context.
- */
- template <typename _To_Type, typename _From_Type>
- _kc_hidden details::iconv_context<_To_Type, _From_Type> *
- get_context(const char *tocode, const char *fromcode)
- {
- context_key key(create_key<_To_Type, _From_Type>(tocode, fromcode));
- context_map::const_iterator iContext = m_contexts.find(key);
- if (iContext == m_contexts.cend()) {
- auto lpContext = new details::iconv_context<_To_Type, _From_Type>(tocode, fromcode);
-
- // Before we store it, we need to copy the fromcode as we don't know what the
- // lifetime will be.
- persist_code(key, pfToCode|pfFromCode);
-
- iContext = m_contexts.insert(context_map::value_type(key, lpContext)).first;
- }
- return dynamic_cast<details::iconv_context<_To_Type, _From_Type>*>(iContext->second);
- }
- /**
- * @brief Flags that determine which code of a context_key is persisted
- */
- enum {
- pfToCode = 1,
- pfFromCode = 2
- };
- /**
- * @brief Persists the code for the fromcode when it's not certain it won't
- * be destroyed while in use.
- *
- * @param[in,out] key The key for which the second field will be persisted.
- */
- _kc_export void persist_code(context_key &key, unsigned flags);
-
- /**
- * Persist the string so a raw pointer to its content can be used.
- *
- * The pointer that can be used is returned by this function. Using the
- * pointer to the data of the original string will be a recipe to disaster.
- *
- * @param[in] string The string to persist.
- * @return The raw pointer that can be used as long as the convert_context exists.
- */
- char *persist_string(const std::string &);
-
- /**
- * Persist the string so a raw pointer to its content can be used.
- *
- * The pointer that can be used is returned by this function. Using the
- * pointer to the data of the original string will be a recipe to disaster.
- *
- * @param[in] string The string to persist.
- * @return The raw pointer that can be used as long as the convert_context exists.
- */
- wchar_t *persist_string(const std::wstring &wstrValue);
-
- code_set m_codes;
- context_map m_contexts;
- std::list<std::string> m_lstStrings;
- std::list<std::wstring> m_lstWstrings;
-
- // a convert_context is not supposed to be copyable.
- convert_context(const convert_context &) = delete;
- convert_context &operator=(const convert_context &) = delete;
- };
- /** Convert a string to UTF-8.
- *
- * @param[in] _context
- * The convert_context used for the conversion
- * @param[in] _ptr
- * Pointer to the string containing the data to be converted.
- * @param[in] _flags
- * If set to MAPI_UNICODE, the _ptr argument is interpreted as a wide character string. Otherwise
- * the _ptr argument is interpreted as a single byte string encoded in the current locale.
- *
- * @return The converted string.
- */
- #define TO_UTF8(_context, _ptr, _flags) \
- ((_ptr) ? \
- (_context).convert_to<char*>("UTF-8", (_ptr), \
- ((_flags) & MAPI_UNICODE) ? sizeof(wchar_t) * wcslen((wchar_t*)(_ptr)) : strlen((char*)(_ptr)), \
- ((_flags) & MAPI_UNICODE) ? CHARSET_WCHAR : CHARSET_CHAR) \
- : NULL )
- /**
- * Convert a string to UTF-8 with default arguments.
- *
- * This version requeres the convert_context to be named 'converter' and the flags argument 'ulFlags'.
- *
- * @param[in] _ptr
- * Pointer to the string containing the data to be converted.
- *
- * @return The converted string.
- */
- #define TO_UTF8_DEF(_ptr) \
- TO_UTF8(converter, (_ptr), ulFlags)
- namespace details {
- extern _kc_export HRESULT HrFromException(const convert_exception &);
- } // namespace details
- #ifdef MAPIDEFS_H
- /**
- * @brief Converts a string from one charset to another. Failure is indicated
- * through the return code instead of an exception.
- *
- * @param[in] _from The string to be converted.
- * @param[out] _to The converted string.
- * @return HRESULT.
- */
- template <typename _To_Type, typename _From_Type>
- HRESULT TryConvert(const _From_Type &_from, _To_Type &_to) {
- try {
- _to = convert_to<_To_Type>(_from);
- return hrSuccess;
- } catch (const convert_exception &ce) {
- return details::HrFromException(ce);
- }
- }
- /**
- * @brief Converts a string from one charset to another. Failure is indicated
- * through the return code instead of an exception.
- *
- * @param[in] _from The string to be converted.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @param[out] _to The converted string.
- * @return HRESULT.
- */
- template <typename _To_Type, typename _From_Type>
- HRESULT TryConvert(const _From_Type &_from, size_t cbBytes, const char *fromcode, _To_Type &_to) {
- try {
- _to = convert_to<_To_Type>(_from, cbBytes, fromcode);
- return hrSuccess;
- } catch (const convert_exception &ce) {
- return details::HrFromException(ce);
- }
- }
- /**
- * @brief Converts a string from one charset to another. Failure is indicated
- * through the return code instead of an exception.
- *
- * @param[in] context A convert_context to perform the conversion on.
- * @param[in] _from The string to be converted.
- * @param[out] _to The converted string.
- * @return HRESULT.
- */
- template <typename _To_Type, typename _From_Type>
- HRESULT TryConvert(convert_context &context, const _From_Type &_from, _To_Type &_to) {
- try {
- _to = context.convert_to<_To_Type>(_from);
- return hrSuccess;
- } catch (const convert_exception &ce) {
- return details::HrFromException(ce);
- }
- }
- /**
- * @brief Converts a string from one charset to another. Failure is indicated
- * through the return code instead of an exception.
- *
- * @param[in] context A convert_context to perform the conversion on.
- * @param[in] _from The string to be converted.
- * @param[in] cbBytes The size in bytes of the string to convert.
- * @param[in] fromcode The source charset.
- * @param[out] _to The converted string.
- * @return HRESULT.
- */
- template <typename _To_Type, typename _From_Type>
- HRESULT TryConvert(convert_context &context, const _From_Type &_from, size_t cbBytes, const char *fromcode, _To_Type &_to) {
- try {
- _to = context.convert_to<_To_Type>(_from, cbBytes, fromcode);
- return hrSuccess;
- } catch (const convert_exception &ce) {
- return details::HrFromException(ce);
- }
- }
- #endif // MAPIDEFS_H
- } /* namespace */
- #endif // ndef convert_INCLUDED
|