// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the name Chromium Embedded // Framework nor the names of its contributors may be used to endorse // or promote products derived from this software without specific prior // written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef CEF_INCLUDE_INTERNAL_CEF_STRING_WRAPPERS_H_ #define CEF_INCLUDE_INTERNAL_CEF_STRING_WRAPPERS_H_ #pragma once #include #include #include "include/internal/cef_string_types.h" #if defined(USING_CHROMIUM_INCLUDES) #include "base/files/file_path.h" #endif /// /// Traits implementation for wide character strings. /// struct CefStringTraitsWide { typedef wchar_t char_type; typedef cef_string_wide_t struct_type; typedef cef_string_userfree_wide_t userfree_struct_type; static inline void clear(struct_type* s) { cef_string_wide_clear(s); } static inline int set(const char_type* src, size_t src_size, struct_type* output, int copy) { return cef_string_wide_set(src, src_size, output, copy); } static inline int compare(const struct_type* s1, const struct_type* s2) { return cef_string_wide_cmp(s1, s2); } static inline userfree_struct_type userfree_alloc() { return cef_string_userfree_wide_alloc(); } static inline void userfree_free(userfree_struct_type ufs) { return cef_string_userfree_wide_free(ufs); } // Conversion methods. static inline bool from_ascii(const char* str, size_t len, struct_type* s) { return cef_string_ascii_to_wide(str, len, s) ? true : false; } static inline std::string to_string(const struct_type* s) { cef_string_utf8_t cstr; memset(&cstr, 0, sizeof(cstr)); cef_string_wide_to_utf8(s->str, s->length, &cstr); std::string str; if (cstr.length > 0) { str = std::string(cstr.str, cstr.length); } cef_string_utf8_clear(&cstr); return str; } static inline bool from_string(const std::string::value_type* data, size_t length, struct_type* s) { return cef_string_utf8_to_wide(data, length, s) ? true : false; } static inline bool from_string(const std::string& str, struct_type* s) { return from_string(str.data(), str.length(), s); } static inline std::wstring to_wstring(const struct_type* s) { return std::wstring(s->str, s->length); } static inline bool from_wstring(const std::wstring::value_type* data, size_t length, struct_type* s) { return cef_string_wide_set(data, length, s, true) ? true : false; } static inline bool from_wstring(const std::wstring& str, struct_type* s) { return from_wstring(str.data(), str.length(), s); } #if defined(WCHAR_T_IS_UTF32) static inline std::u16string to_string16(const struct_type* s) { cef_string_utf16_t cstr; memset(&cstr, 0, sizeof(cstr)); cef_string_wide_to_utf16(s->str, s->length, &cstr); std::u16string str; if (cstr.length > 0) { str = std::u16string( reinterpret_cast(cstr.str), cstr.length); } cef_string_utf16_clear(&cstr); return str; } static inline bool from_string16(const std::u16string::value_type* data, size_t length, struct_type* s) { return cef_string_utf16_to_wide(reinterpret_cast(data), length, s) ? true : false; } #else // WCHAR_T_IS_UTF32 static inline std::u16string to_string16(const struct_type* s) { return std::u16string( reinterpret_cast(s->str), s->length); } static inline bool from_string16(const std::u16string::value_type* data, size_t length, struct_type* s) { return cef_string_wide_set(reinterpret_cast(data), length, s, true) ? true : false; } #endif // WCHAR_T_IS_UTF32 static inline bool from_string16(const std::u16string& str, struct_type* s) { return from_string16(str.data(), str.length(), s); } }; /// /// Traits implementation for utf8 character strings. /// struct CefStringTraitsUTF8 { typedef char char_type; typedef cef_string_utf8_t struct_type; typedef cef_string_userfree_utf8_t userfree_struct_type; static inline void clear(struct_type* s) { cef_string_utf8_clear(s); } static inline int set(const char_type* src, size_t src_size, struct_type* output, int copy) { return cef_string_utf8_set(src, src_size, output, copy); } static inline int compare(const struct_type* s1, const struct_type* s2) { return cef_string_utf8_cmp(s1, s2); } static inline userfree_struct_type userfree_alloc() { return cef_string_userfree_utf8_alloc(); } static inline void userfree_free(userfree_struct_type ufs) { return cef_string_userfree_utf8_free(ufs); } // Conversion methods. static inline bool from_ascii(const char* str, size_t len, struct_type* s) { return cef_string_utf8_copy(str, len, s) ? true : false; } static inline std::string to_string(const struct_type* s) { return std::string(s->str, s->length); } static inline bool from_string(const std::string::value_type* data, size_t length, struct_type* s) { return cef_string_utf8_copy(data, length, s) ? true : false; } static inline bool from_string(const std::string& str, struct_type* s) { return from_string(str.c_str(), str.length(), s); } static inline std::wstring to_wstring(const struct_type* s) { cef_string_wide_t cstr; memset(&cstr, 0, sizeof(cstr)); cef_string_utf8_to_wide(s->str, s->length, &cstr); std::wstring str; if (cstr.length > 0) { str = std::wstring(cstr.str, cstr.length); } cef_string_wide_clear(&cstr); return str; } static inline bool from_wstring(const std::wstring::value_type* data, size_t length, struct_type* s) { return cef_string_wide_to_utf8(data, length, s) ? true : false; } static inline bool from_wstring(const std::wstring& str, struct_type* s) { return from_wstring(str.data(), str.length(), s); } static inline std::u16string to_string16(const struct_type* s) { cef_string_utf16_t cstr; memset(&cstr, 0, sizeof(cstr)); cef_string_utf8_to_utf16(s->str, s->length, &cstr); std::u16string str; if (cstr.length > 0) { str = std::u16string( reinterpret_cast(cstr.str), cstr.length); } cef_string_utf16_clear(&cstr); return str; } static inline bool from_string16(const std::u16string::value_type* data, size_t length, struct_type* s) { return cef_string_utf16_to_utf8(reinterpret_cast(data), length, s) ? true : false; } static inline bool from_string16(const std::u16string& str, struct_type* s) { return from_string16(str.data(), str.length(), s); } }; /// /// Traits implementation for utf16 character strings. /// struct CefStringTraitsUTF16 { typedef char16_t char_type; typedef cef_string_utf16_t struct_type; typedef cef_string_userfree_utf16_t userfree_struct_type; static inline void clear(struct_type* s) { cef_string_utf16_clear(s); } static inline int set(const char_type* src, size_t src_size, struct_type* output, int copy) { return cef_string_utf16_set(src, src_size, output, copy); } static inline int compare(const struct_type* s1, const struct_type* s2) { return cef_string_utf16_cmp(s1, s2); } static inline userfree_struct_type userfree_alloc() { return cef_string_userfree_utf16_alloc(); } static inline void userfree_free(userfree_struct_type ufs) { return cef_string_userfree_utf16_free(ufs); } // Conversion methods. static inline bool from_ascii(const char* str, size_t len, struct_type* s) { return cef_string_ascii_to_utf16(str, len, s) ? true : false; } static inline std::string to_string(const struct_type* s) { cef_string_utf8_t cstr; memset(&cstr, 0, sizeof(cstr)); cef_string_utf16_to_utf8(s->str, s->length, &cstr); std::string str; if (cstr.length > 0) { str = std::string(cstr.str, cstr.length); } cef_string_utf8_clear(&cstr); return str; } static inline bool from_string(const std::string::value_type* data, size_t length, struct_type* s) { return cef_string_utf8_to_utf16(data, length, s) ? true : false; } static inline bool from_string(const std::string& str, struct_type* s) { return from_string(str.data(), str.length(), s); } #if defined(WCHAR_T_IS_UTF32) static inline std::wstring to_wstring(const struct_type* s) { cef_string_wide_t cstr; memset(&cstr, 0, sizeof(cstr)); cef_string_utf16_to_wide(s->str, s->length, &cstr); std::wstring str; if (cstr.length > 0) { str = std::wstring(cstr.str, cstr.length); } cef_string_wide_clear(&cstr); return str; } static inline bool from_wstring(const std::wstring::value_type* data, size_t length, struct_type* s) { return cef_string_wide_to_utf16(data, length, s) ? true : false; } #else // WCHAR_T_IS_UTF32 static inline std::wstring to_wstring(const struct_type* s) { return std::wstring(reinterpret_cast(s->str), s->length); } static inline bool from_wstring(const std::wstring::value_type* data, size_t length, struct_type* s) { return cef_string_utf16_set(reinterpret_cast(data), length, s, true) ? true : false; } #endif // WCHAR_T_IS_UTF32 static inline bool from_wstring(const std::wstring& str, struct_type* s) { return from_wstring(str.data(), str.length(), s); } static inline std::u16string to_string16(const struct_type* s) { return std::u16string( reinterpret_cast(s->str), s->length); } static inline bool from_string16(const std::u16string::value_type* data, size_t length, struct_type* s) { return cef_string_utf16_set(reinterpret_cast(data), length, s, true) ? true : false; } static inline bool from_string16(const std::u16string& str, struct_type* s) { return from_string16(str.data(), str.length(), s); } }; /// /// CEF string classes can convert between all supported string types. For /// example, the CefStringWide class uses wchar_t as the underlying character /// type and provides two approaches for converting data to/from a UTF8 string /// (std::string). /// /// 1. Implicit conversion using the assignment operator overload. ///
///   CefStringWide aCefString;
///   std::string aUTF8String;
///   aCefString = aUTF8String; // Assign std::string to CefStringWide
///   aUTF8String = aCefString; // Assign CefStringWide to std::string
/// 
/// /// 2. Explicit conversion using the FromString/ToString methods. ///
///   CefStringWide aCefString;
///   std::string aUTF8String;
///   aCefString.FromString(aUTF8String); // Assign std::string to CefStringWide
///   aUTF8String = aCefString.ToString(); // Assign CefStringWide to
///   std::string
/// 
/// /// Conversion will only occur if the assigned value is a different string type. /// Assigning a std::string to a CefStringUTF8, for example, will copy the data /// without performing a conversion. /// /// CEF string classes are safe for reading from multiple threads but not for /// modification. It is the user's responsibility to provide synchronization if /// modifying CEF strings from multiple threads. /// template class CefStringBase final { public: typedef typename traits::char_type char_type; typedef typename traits::struct_type struct_type; typedef typename traits::userfree_struct_type userfree_struct_type; /// /// Default constructor. /// CefStringBase() : string_(NULL), owner_(false) {} /// /// Create a new string from an existing string. Data will always be copied. /// CefStringBase(const CefStringBase& str) : string_(NULL), owner_(false) { FromString(str.c_str(), str.length(), true); } /// /// Create a new string from an existing std::string. Data will be always /// copied. Translation will occur if necessary based on the underlying string /// type. /// CefStringBase(const std::string& src) : string_(NULL), owner_(false) { FromString(src); } CefStringBase(const char* src, size_t length = 0) : string_(NULL), owner_(false) { if (src) { FromString(src, length); } } /// /// Create a new string from an existing std::wstring. Data will be always /// copied. Translation will occur if necessary based on the underlying string /// type. /// CefStringBase(const std::wstring& src) : string_(NULL), owner_(false) { FromWString(src); } CefStringBase(const wchar_t* src, size_t length = 0) : string_(NULL), owner_(false) { if (src) { FromWString(src, length); } } /// /// Create a new string from an existing string16. Data will be always /// copied. Translation will occur if necessary based on the underlying string /// type. /// CefStringBase(const std::u16string& src) : string_(NULL), owner_(false) { FromString16(src); } CefStringBase(const std::u16string::value_type* src, size_t length = 0) : string_(NULL), owner_(false) { if (src) { FromString16(src, length); } } /// /// Create a new string from an existing character array. If |copy| is true /// this class will copy the data. Otherwise, this class will reference the /// existing data. Referenced data must exist for the lifetime of this class /// and will not be freed by this class. /// CefStringBase(const char_type* src, size_t src_len, bool copy) : string_(NULL), owner_(false) { if (src && src_len > 0) { FromString(src, src_len, copy); } } /// /// Create a new string referencing an existing string structure without /// taking ownership. Referenced structures must exist for the lifetime of /// this class and will not be freed by this class. /// CefStringBase(const struct_type* src) : string_(NULL), owner_(false) { if (!src) { return; } // Reference the existing structure without taking ownership. Attach(const_cast(src), false); } ~CefStringBase() { ClearAndFree(); } /// The following methods are named for compatibility with the standard /// library string template types. /// /// Return a read-only pointer to the string data. /// const char_type* c_str() const { return (string_ ? string_->str : NULL); } /// /// Return the length of the string data. /// size_t length() const { return (string_ ? string_->length : 0); } /// /// Return the length of the string data. /// inline size_t size() const { return length(); } /// /// Returns true if the string is empty. /// bool empty() const { return (string_ == NULL || string_->length == 0); } /// /// Compare this string to the specified string. /// int compare(const CefStringBase& str) const { if (empty() && str.empty()) { return 0; } if (empty()) { return -1; } if (str.empty()) { return 1; } return traits::compare(string_, str.GetStruct()); } /// /// Clear the string data. /// void clear() { if (string_) { traits::clear(string_); } } /// /// Swap this string's contents with the specified string. /// void swap(CefStringBase& str) { struct_type* tmp_string = string_; bool tmp_owner = owner_; string_ = str.string_; owner_ = str.owner_; str.string_ = tmp_string; str.owner_ = tmp_owner; } // The following methods are unique to CEF string template types. /// /// Returns true if this class owns the underlying string structure. /// bool IsOwner() const { return owner_; } /// /// Returns a read-only pointer to the underlying string structure. May return /// NULL if no structure is currently allocated. /// const struct_type* GetStruct() const { return string_; } /// /// Returns a writable pointer to the underlying string structure. Will never /// return NULL. /// struct_type* GetWritableStruct() { AllocIfNeeded(); return string_; } /// /// Clear the state of this class. The underlying string structure and data /// will be freed if this class owns the structure. /// void ClearAndFree() { if (!string_) { return; } if (owner_) { clear(); delete string_; } string_ = NULL; owner_ = false; } /// /// Attach to the specified string structure. If |owner| is true this class /// will take ownership of the structure. /// void Attach(struct_type* str, bool owner) { // Free the previous structure and data, if any. ClearAndFree(); string_ = str; owner_ = owner; } /// /// Take ownership of the specified userfree structure's string data. The /// userfree structure itself will be freed. Only use this method with /// userfree structures. /// void AttachToUserFree(userfree_struct_type str) { // Free the previous structure and data, if any. ClearAndFree(); if (!str) { return; } AllocIfNeeded(); owner_ = true; memcpy(string_, str, sizeof(struct_type)); /// Free the |str| structure but not the data. memset(str, 0, sizeof(struct_type)); traits::userfree_free(str); } /// /// Detach from the underlying string structure. To avoid memory leaks only /// use this method if you already hold a pointer to the underlying string /// structure. /// void Detach() { string_ = NULL; owner_ = false; } /// /// Create a userfree structure and give it ownership of this class' string /// data. This class will be disassociated from the data. May return NULL if /// this string class currently contains no data. /// userfree_struct_type DetachToUserFree() { if (empty()) { return NULL; } userfree_struct_type str = traits::userfree_alloc(); if (owner_) { // Transfer ownership of the data to |str|. memcpy(str, string_, sizeof(struct_type)); // Free this class' structure but not the data. memset(string_, 0, sizeof(struct_type)); } else { // Copy the data to |str|. traits::set(string_->str, string_->length, str, /*copy=*/true); } ClearAndFree(); return str; } /// /// Set this string's data to the specified character array. If |copy| is true /// this class will copy the data. Otherwise, this class will reference the /// existing data. Referenced data must exist for the lifetime of this class /// and will not be freed by this class. /// bool FromString(const char_type* src, size_t src_len, bool copy) { if (src == NULL || src_len == 0) { clear(); return true; } AllocIfNeeded(); return traits::set(src, src_len, string_, copy) ? true : false; } /// /// Set this string's data from an existing ASCII string. Data will be always /// copied. Translation will occur if necessary based on the underlying string /// type. /// bool FromASCII(const char* str) { size_t len = str ? strlen(str) : 0; if (len == 0) { clear(); return true; } AllocIfNeeded(); return traits::from_ascii(str, len, string_); } /// /// Return this string's data as a std::string. Translation will occur if /// necessary based on the underlying string type. /// std::string ToString() const { if (empty()) { return std::string(); } return traits::to_string(string_); } /// /// Set this string's data from an existing std::string. Data will be always /// copied. Translation will occur if necessary based on the underlying string /// type. /// bool FromString(const std::string& str) { if (str.empty()) { clear(); return true; } AllocIfNeeded(); return traits::from_string(str, string_); } /// /// Set this string's data from existing |data| and optional |length|. Data /// will be always copied. Translation will occur if necessary based on the /// underlying string type. /// bool FromString(const std::string::value_type* data, size_t length = 0) { if (data && length == 0) { length = std::char_traits::length(data); } if (!data || length == 0) { clear(); return true; } AllocIfNeeded(); return traits::from_string(data, length, string_); } /// /// Return this string's data as a std::wstring. Translation will occur if /// necessary based on the underlying string type. /// std::wstring ToWString() const { if (empty()) { return std::wstring(); } return traits::to_wstring(string_); } /// /// Set this string's data from an existing std::wstring. Data will be always /// copied. Translation will occur if necessary based on the underlying string /// type. /// bool FromWString(const std::wstring& str) { if (str.empty()) { clear(); return true; } AllocIfNeeded(); return traits::from_wstring(str, string_); } /// /// Set this string's data from existing |data| and optional |length|. Data /// will be always copied. Translation will occur if necessary based on the /// underlying string type. /// bool FromWString(const std::wstring::value_type* data, size_t length = 0) { if (data && length == 0) { length = std::char_traits::length(data); } if (!data || length == 0) { clear(); return true; } AllocIfNeeded(); return traits::from_wstring(data, length, string_); } /// /// Return this string's data as a string16. Translation will occur if /// necessary based on the underlying string type. /// std::u16string ToString16() const { if (empty()) { return std::u16string(); } return traits::to_string16(string_); } /// /// Set this string's data from an existing string16. Data will be always /// copied. Translation will occur if necessary based on the underlying string /// type. /// bool FromString16(const std::u16string& str) { if (str.empty()) { clear(); return true; } AllocIfNeeded(); return traits::from_string16(str, string_); } /// /// Set this string's data from existing |data| and optional |length|. Data /// will be always copied. Translation will occur if necessary based on the /// underlying string type. /// bool FromString16(const std::u16string::value_type* data, size_t length = 0) { if (data && length == 0) { length = std::char_traits::length(data); } if (!data || length == 0) { clear(); return true; } AllocIfNeeded(); return traits::from_string16(data, length, string_); } /// /// Comparison operator overloads. /// bool operator<(const CefStringBase& str) const { return (compare(str) < 0); } bool operator<=(const CefStringBase& str) const { return (compare(str) <= 0); } bool operator>(const CefStringBase& str) const { return (compare(str) > 0); } bool operator>=(const CefStringBase& str) const { return (compare(str) >= 0); } bool operator==(const CefStringBase& str) const { return (compare(str) == 0); } bool operator!=(const CefStringBase& str) const { return (compare(str) != 0); } /// /// Assignment operator overloads. /// CefStringBase& operator=(const CefStringBase& str) { FromString(str.c_str(), str.length(), true); return *this; } operator std::string() const { return ToString(); } CefStringBase& operator=(const std::string& str) { FromString(str); return *this; } CefStringBase& operator=(const std::string::value_type* str) { FromString(str); return *this; } operator std::wstring() const { return ToWString(); } CefStringBase& operator=(const std::wstring& str) { FromWString(str); return *this; } CefStringBase& operator=(const std::wstring::value_type* str) { FromWString(str); return *this; } operator std::u16string() const { return ToString16(); } CefStringBase& operator=(const std::u16string& str) { FromString16(str); return *this; } CefStringBase& operator=(const std::u16string::value_type* str) { FromString16(str); return *this; } #if defined(USING_CHROMIUM_INCLUDES) // The base::FilePath constructor is marked as explicit so provide the // conversion here for convenience. operator base::FilePath() const { #if defined(OS_WIN) return base::FilePath(ToWString()); #else return base::FilePath(ToString()); #endif } #endif // USING_CHROMIUM_INCLUDES private: /// Allocate the string structure if it doesn't already exist. void AllocIfNeeded() { if (string_ == NULL) { string_ = new struct_type; memset(string_, 0, sizeof(struct_type)); owner_ = true; } } struct_type* string_; bool owner_; }; typedef CefStringBase CefStringWide; typedef CefStringBase CefStringUTF8; typedef CefStringBase CefStringUTF16; #endif // CEF_INCLUDE_INTERNAL_CEF_STRING_WRAPPERS_H_