Bug 928351 - Char16.h and xpcom/strings/public parts r=ehsan,Waldo
authorJacek Caban <jacek@codeweavers.com>
Wed, 27 Nov 2013 14:40:54 +0100
changeset 172443 30fe34b9ebf7292e7ca5333fc70b3ae34c4fc9af
parent 172442 32aa215becb49ba3218a509bd81a38e579fe08df
child 172444 dcdf76f06a1faf8f8e3072c369c3e9f66b0afcc8
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, Waldo
bugs928351
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 928351 - Char16.h and xpcom/strings/public parts r=ehsan,Waldo
mfbt/Char16.h
xpcom/glue/nsStringAPI.h
xpcom/string/public/nsReadableUtils.h
xpcom/string/public/nsString.h
xpcom/string/public/nsTDependentString.h
xpcom/string/public/nsTDependentSubstring.h
xpcom/string/public/nsTString.h
xpcom/string/public/nsTSubstring.h
--- a/mfbt/Char16.h
+++ b/mfbt/Char16.h
@@ -42,32 +42,137 @@
       (__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__))
    /* C++11 has a builtin char16_t type. */
 #  define MOZ_UTF16_HELPER(s) u##s
    /**
     * This macro is used to distinguish when char16_t would be a distinct
     * typedef from wchar_t.
     */
 #  define MOZ_CHAR16_IS_NOT_WCHAR
+#  ifdef WIN32
+#    define MOZ_USE_CHAR16_WRAPPER
+#  endif
 #elif !defined(__cplusplus)
 #  if defined(WIN32)
 #    include <yvals.h>
      typedef wchar_t char16_t;
 #  else
      /**
       * We can't use the stdint.h uint16_t type here because including
       * stdint.h will break building some of our C libraries, such as
       * sqlite.
       */
      typedef unsigned short char16_t;
 #  endif
 #else
 #  error "Char16.h requires C++11 (or something like it) for UTF-16 support."
 #endif
 
+#ifdef MOZ_USE_CHAR16_WRAPPER
+# include <string>
+  /**
+   * Win32 API extensively uses wchar_t, which is represented by a separated
+   * builtin type than char16_t per spec. It's not the case for MSVC, but GCC
+   * follows the spec. We want to mix wchar_t and char16_t on Windows builds.
+   * This class is supposed to make it easier. It stores char16_t const pointer,
+   * but provides implicit casts for wchar_t as well. On other platforms, we
+   * simply use |typedef const char16_t* char16ptr_t|. Here, we want to make
+   * the class as similar to this typedef, including providing some casts that
+   * are allowed by the typedef.
+   */
+class char16ptr_t
+{
+  private:
+    const char16_t* ptr;
+    static_assert(sizeof(char16_t) == sizeof(wchar_t), "char16_t and wchar_t sizes differ");
+
+  public:
+    char16ptr_t(const char16_t* ptr) : ptr(ptr) {}
+    char16ptr_t(const wchar_t* ptr) : ptr(reinterpret_cast<const char16_t*>(ptr)) {}
+
+    /* Without this, nullptr assignment would be ambiguous. */
+    constexpr char16ptr_t(decltype(nullptr)) : ptr(nullptr) {}
+
+    operator const char16_t*() const {
+      return ptr;
+    }
+    operator const wchar_t*() const {
+      return reinterpret_cast<const wchar_t*>(ptr);
+    }
+    operator const void*() const {
+      return ptr;
+    }
+    operator bool() const {
+      return ptr != nullptr;
+    }
+    operator std::wstring() const {
+      return std::wstring(static_cast<const wchar_t*>(*this));
+    }
+
+    /* Explicit cast operators to allow things like (char16_t*)str. */
+    explicit operator char16_t*() const {
+      return const_cast<char16_t*>(ptr);
+    }
+    explicit operator wchar_t*() const {
+      return const_cast<wchar_t*>(static_cast<const wchar_t*>(*this));
+    }
+
+    /**
+     * Some Windows API calls accept BYTE* but require that data actually be WCHAR*.
+     * Supporting this requires explicit operators to support the requisite explicit
+     * casts.
+     */
+    explicit operator const char*() const {
+      return reinterpret_cast<const char*>(ptr);
+    }
+    explicit operator const unsigned char*() const {
+      return reinterpret_cast<const unsigned char*>(ptr);
+    }
+    explicit operator unsigned char*() const {
+      return const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(ptr));
+    }
+    explicit operator void*() const {
+      return const_cast<char16_t*>(ptr);
+    }
+
+    /* Some operators used on pointers. */
+    char16_t operator[](size_t i) const {
+      return ptr[i];
+    }
+    bool operator==(const char16ptr_t &x) const {
+      return ptr == x.ptr;
+    }
+    bool operator==(decltype(nullptr)) const {
+      return ptr == nullptr;
+    }
+    bool operator!=(const char16ptr_t &x) const {
+      return ptr != x.ptr;
+    }
+    bool operator!=(decltype(nullptr)) const {
+      return ptr != nullptr;
+    }
+    char16ptr_t operator+(size_t add) const {
+      return char16ptr_t(ptr + add);
+    }
+    ptrdiff_t operator-(const char16ptr_t &other) const {
+      return ptr - other.ptr;
+    }
+};
+
+inline decltype((char*)0-(char*)0)
+operator-(const char16_t* x, const char16ptr_t y) {
+  return x - static_cast<const char16_t*>(y);
+}
+
+#else
+
+typedef const char16_t* char16ptr_t;
+
+#endif
+
 /* This is a temporary hack until bug 927728 is fixed. */
 #define __PRUNICHAR__
 typedef char16_t PRUnichar;
 
 /*
  * Macro arguments used in concatenation or stringification won't be expanded.
  * Therefore, in order for |MOZ_UTF16(FOO)| to work as expected (which is to
  * expand |FOO| before doing whatever |MOZ_UTF16| needs to do to it) a helper
--- a/xpcom/glue/nsStringAPI.h
+++ b/xpcom/glue/nsStringAPI.h
@@ -138,16 +138,19 @@ public:
     uint32_t dataLen = NS_StringGetData(readable, &data);
     NS_StringSetDataRange(*this, cutStart, cutLength, data, dataLen);
   }
   NS_HIDDEN_(void) SetCharAt( char_type c, index_type pos )
                       { Replace(pos, 1, &c, 1); }
 
   NS_HIDDEN_(void) Append( char_type c )                                                              { Replace(size_type(-1), 0, c); }
   NS_HIDDEN_(void) Append( const char_type* data, size_type length = size_type(-1) )                  { Replace(size_type(-1), 0, data, length); }
+#ifdef MOZ_USE_CHAR16_WRAPPER
+  NS_HIDDEN_(void) Append( char16ptr_t data, size_type length = size_type(-1) )                       { Append(static_cast<const char16_t*>(data), length); }
+#endif
   NS_HIDDEN_(void) Append( const self_type& readable )                                                { Replace(size_type(-1), 0, readable); }
   NS_HIDDEN_(void) AppendLiteral( const char *aASCIIStr );
   NS_HIDDEN_(void) AppendASCII( const char *aASCIIStr )                                               { AppendLiteral(aASCIIStr); }
 
   NS_HIDDEN_(self_type&) operator+=( char_type c )                                                    { Append(c);        return *this; }
   NS_HIDDEN_(self_type&) operator+=( const char_type* data )                                          { Append(data);     return *this; }
   NS_HIDDEN_(self_type&) operator+=( const self_type& readable )                                      { Append(readable); return *this; }
 
@@ -803,25 +806,31 @@ public:
     NS_StringCopy(*this, aReadable);
   }
 
   explicit
   nsString(const char_type* aData, size_type aLength = UINT32_MAX)
   {
     NS_StringContainerInit2(*this, aData, aLength, 0);
   }
+
+#ifdef MOZ_USE_CHAR16_WRAPPER
+  explicit
+  nsString(char16ptr_t aData, size_type aLength = UINT32_MAX)
+    : nsString(static_cast<const char16_t*>(aData), aLength) {}
+#endif
   
   ~nsString()
   {
     NS_StringContainerFinish(*this);
   }
 
-  const char_type* get() const
+  char16ptr_t get() const
   {
-    return BeginReading();
+    return char16ptr_t(BeginReading());
   }
 
   self_type& operator=(const self_type& aString)              { Assign(aString);   return *this; }
   self_type& operator=(const abstract_string_type& aReadable) { Assign(aReadable); return *this; }
   self_type& operator=(const char_type* aPtr)                 { Assign(aPtr);      return *this; }
   self_type& operator=(char_type aChar)                       { Assign(aChar);     return *this; }
 
   void Adopt(const char_type *aData, size_type aLength = UINT32_MAX)
@@ -912,16 +921,23 @@ public:
 
   nsDependentString() {}
 
   explicit
   nsDependentString(const char_type* aData, size_type aLength = UINT32_MAX)
     : nsString(aData, aLength, NS_CSTRING_CONTAINER_INIT_DEPEND)
   {}
 
+#ifdef MOZ_USE_CHAR16_WRAPPER
+  explicit
+  nsDependentString(char16ptr_t aData, size_type aLength = UINT32_MAX)
+    : nsDependentString(static_cast<const char16_t*>(aData), aLength)
+  {}
+#endif
+
   void Rebind(const char_type* aData, size_type aLength = UINT32_MAX)
   {
     NS_StringContainerFinish(*this);
     NS_StringContainerInit2(*this, aData, aLength,
                             NS_STRING_CONTAINER_INIT_DEPEND);
   }
   
 private:
--- a/xpcom/string/public/nsReadableUtils.h
+++ b/xpcom/string/public/nsReadableUtils.h
@@ -48,16 +48,23 @@ void AppendASCIItoUTF16( const char* aSo
 void AppendUTF16toUTF8( const nsAString& aSource, nsACString& aDest );
 void AppendUTF8toUTF16( const nsACString& aSource, nsAString& aDest );
 bool AppendUTF8toUTF16( const nsACString& aSource, nsAString& aDest,
                         const mozilla::fallible_t& ) NS_WARN_UNUSED_RESULT;
 
 void AppendUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest );
 void AppendUTF8toUTF16( const char* aSource, nsAString& aDest );
 
+#ifdef MOZ_USE_CHAR16_WRAPPER
+inline void AppendUTF16toUTF8( char16ptr_t aSource, nsACString& aDest )
+  {
+    return AppendUTF16toUTF8(static_cast<const char16_t*>(aSource), aDest);
+  }
+#endif
+
   /**
    * Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
    *
    * Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
    * Performs a lossy encoding conversion by chopping 16-bit wide characters down to 8-bits wide while copying |aSource| to your new buffer.
    * This conversion is not well defined; but it reproduces legacy string behavior.
    * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
    *
--- a/xpcom/string/public/nsString.h
+++ b/xpcom/string/public/nsString.h
@@ -69,16 +69,25 @@ class NS_LossyConvertUTF16toASCII : publ
           LossyAppendUTF16toASCII(aString, *this);
         }
 
       NS_LossyConvertUTF16toASCII( const PRUnichar* aString, uint32_t aLength )
         {
           LossyAppendUTF16toASCII(Substring(aString, aLength), *this);
         }
 
+#ifdef MOZ_USE_CHAR16_WRAPPER
+      explicit
+      NS_LossyConvertUTF16toASCII( char16ptr_t aString )
+        : NS_LossyConvertUTF16toASCII(static_cast<const char16_t*>(aString)) {}
+
+      NS_LossyConvertUTF16toASCII( char16ptr_t aString, uint32_t aLength )
+        : NS_LossyConvertUTF16toASCII(static_cast<const char16_t*>(aString), aLength) {}
+#endif
+
       explicit
       NS_LossyConvertUTF16toASCII( const nsAString& aString )
         {
           LossyAppendUTF16toASCII(aString, *this);
         }
 
     private:
         // NOT TO BE IMPLEMENTED
@@ -124,16 +133,23 @@ class NS_ConvertUTF16toUTF8 : public nsA
           AppendUTF16toUTF8(aString, *this);
         }
 
       NS_ConvertUTF16toUTF8( const PRUnichar* aString, uint32_t aLength )
         {
           AppendUTF16toUTF8(Substring(aString, aLength), *this);
         }
 
+#ifdef MOZ_USE_CHAR16_WRAPPER
+      NS_ConvertUTF16toUTF8( char16ptr_t aString ) : NS_ConvertUTF16toUTF8(static_cast<const PRUnichar*>(aString)) {}
+
+      NS_ConvertUTF16toUTF8( char16ptr_t aString, uint32_t aLength )
+        : NS_ConvertUTF16toUTF8(static_cast<const PRUnichar*>(aString), aLength) {}
+#endif
+
       explicit
       NS_ConvertUTF16toUTF8( const nsAString& aString )
         {
           AppendUTF16toUTF8(aString, *this);
         }
 
     private:
         // NOT TO BE IMPLEMENTED
--- a/xpcom/string/public/nsTDependentString.h
+++ b/xpcom/string/public/nsTDependentString.h
@@ -35,23 +35,34 @@ class nsTDependentString_CharT : public 
         }
 
       nsTDependentString_CharT( const char_type* data, uint32_t length )
         : string_type(const_cast<char_type*>(data), length, F_TERMINATED)
         {
           AssertValidDepedentString();
         }
 
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      nsTDependentString_CharT( char16ptr_t data, uint32_t length )
+        : nsTDependentString_CharT(static_cast<const char16_t*>(data), length) {}
+#endif
+
       explicit
       nsTDependentString_CharT( const char_type* data )
         : string_type(const_cast<char_type*>(data), uint32_t(char_traits::length(data)), F_TERMINATED)
         {
           AssertValidDepedentString();
         }
 
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      explicit
+      nsTDependentString_CharT( char16ptr_t data )
+        : nsTDependentString_CharT( static_cast<const char16_t*>(data)) {}
+#endif
+
       nsTDependentString_CharT( const string_type& str, uint32_t startPos )
         : string_type()
         {
           Rebind(str, startPos);
         }
 
       // Create a nsTDependentSubstring to be bound later
       nsTDependentString_CharT()
--- a/xpcom/string/public/nsTDependentSubstring.h
+++ b/xpcom/string/public/nsTDependentSubstring.h
@@ -40,16 +40,24 @@ class nsTDependentSubstring_CharT : publ
         }
 
       nsTDependentSubstring_CharT( const char_type* data, size_type length )
         : substring_type(const_cast<char_type*>(data), length, F_NONE) {}
 
       nsTDependentSubstring_CharT( const char_type* start, const char_type* end )
         : substring_type(const_cast<char_type*>(start), uint32_t(end - start), F_NONE) {}
 
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      nsTDependentSubstring_CharT( char16ptr_t data, size_type length )
+        : nsTDependentSubstring_CharT(static_cast<const char16_t*>(data), length) {}
+
+      nsTDependentSubstring_CharT( char16ptr_t start, char16ptr_t end )
+        : nsTDependentSubstring_CharT(static_cast<const char16_t*>(start), static_cast<const char16_t*>(end)) {}
+#endif
+
       nsTDependentSubstring_CharT( const const_iterator& start, const const_iterator& end )
         : substring_type(const_cast<char_type*>(start.get()), uint32_t(end.get() - start.get()), F_NONE) {}
 
       // Create a nsTDependentSubstring to be bound later
       nsTDependentSubstring_CharT()
         : substring_type() {}
 
       // auto-generated copy-constructor OK (XXX really?? what about base class copy-ctor?)
--- a/xpcom/string/public/nsTString.h
+++ b/xpcom/string/public/nsTString.h
@@ -34,16 +34,25 @@ class nsTString_CharT : public nsTSubstr
 
       explicit
       nsTString_CharT( const char_type* data, size_type length = size_type(-1) )
         : substring_type()
         {
           Assign(data, length);
         }
 
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      explicit
+      nsTString_CharT( char16ptr_t data, size_type length = size_type(-1) )
+        : substring_type()
+        {
+          Assign(static_cast<const char16_t*>(data), length);
+        }
+#endif
+
       nsTString_CharT( const self_type& str )
         : substring_type()
         {
           Assign(str);
         }
 
       nsTString_CharT( const substring_tuple_type& tuple )
         : substring_type()
@@ -58,24 +67,31 @@ class nsTString_CharT : public nsTSubstr
           Assign(readable);
         }
 
 
         // |operator=| does not inherit, so we must define our own
       self_type& operator=( char_type c )                                                       { Assign(c);        return *this; }
       self_type& operator=( const char_type* data )                                             { Assign(data);     return *this; }
       self_type& operator=( const self_type& str )                                              { Assign(str);      return *this; }
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      self_type& operator=( const char16ptr_t data )                                            { Assign(static_cast<const char16_t*>(data));     return *this; }
+#endif
       self_type& operator=( const substring_type& str )                                         { Assign(str);      return *this; }
       self_type& operator=( const substring_tuple_type& tuple )                                 { Assign(tuple);    return *this; }
 
         /**
          * returns the null-terminated string
          */
 
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      char16ptr_t get() const
+#else
       const char_type* get() const
+#endif
         {
           return mData;
         }
 
 
         /**
          * returns character at specified index.
          *         
@@ -110,16 +126,22 @@ class nsTString_CharT : public nsTSubstr
          */
 
       int32_t Find( const nsCString& aString, bool aIgnoreCase=false, int32_t aOffset=0, int32_t aCount=-1 ) const;
       int32_t Find( const char* aString, bool aIgnoreCase=false, int32_t aOffset=0, int32_t aCount=-1 ) const;
 
 #ifdef CharT_is_PRUnichar
       int32_t Find( const nsAFlatString& aString, int32_t aOffset=0, int32_t aCount=-1 ) const;
       int32_t Find( const PRUnichar* aString, int32_t aOffset=0, int32_t aCount=-1 ) const;
+#ifdef MOZ_USE_CHAR16_WRAPPER
+      int32_t Find( char16ptr_t aString, int32_t aOffset=0, int32_t aCount=-1 ) const
+        {
+          return Find(static_cast<const char16_t*>(aString), aOffset, aCount);
+        }
+#endif
 #endif
 
         
         /**
          * This methods scans the string backwards, looking for the given string
          *
          * @param   aString is substring to be sought in this
          * @param   aIgnoreCase tells us whether or not to do caseless compare
@@ -469,16 +491,23 @@ class nsTAutoString_CharT : public nsTFi
 
       explicit
       nsTAutoString_CharT( const char_type* data, size_type length = size_type(-1) )
         : fixed_string_type(mStorage, kDefaultStorageSize, 0)
         {
           Assign(data, length);
         }
 
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      explicit
+      nsTAutoString_CharT( char16ptr_t data, size_type length = size_type(-1) )
+        : nsTAutoString_CharT(static_cast<const char16_t*>(data), length)
+        {}
+#endif
+
       nsTAutoString_CharT( const self_type& str )
         : fixed_string_type(mStorage, kDefaultStorageSize, 0)
         {
           Assign(str);
         }
 
       explicit
       nsTAutoString_CharT( const substring_type& str )
@@ -491,16 +520,19 @@ class nsTAutoString_CharT : public nsTFi
         : fixed_string_type(mStorage, kDefaultStorageSize, 0)
         {
           Assign(tuple);
         }
 
         // |operator=| does not inherit, so we must define our own
       self_type& operator=( char_type c )                                                       { Assign(c);        return *this; }
       self_type& operator=( const char_type* data )                                             { Assign(data);     return *this; }
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      self_type& operator=( char16ptr_t data )                                                  { Assign(data);     return *this; }
+#endif
       self_type& operator=( const self_type& str )                                              { Assign(str);      return *this; }
       self_type& operator=( const substring_type& str )                                         { Assign(str);      return *this; }
       self_type& operator=( const substring_tuple_type& tuple )                                 { Assign(tuple);    return *this; }
 
       enum { kDefaultStorageSize = 64 };
 
     private:
 
@@ -562,17 +594,21 @@ class nsTXPIDLString_CharT : public nsTS
         // copy-constructor required to avoid default
       nsTXPIDLString_CharT( const self_type& str )
         : string_type(char_traits::sEmptyBuffer, 0, F_TERMINATED | F_VOIDED)
         {
           Assign(str);
         }
 
         // return nullptr if we are voided
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      char16ptr_t get() const
+#else
       const char_type* get() const
+#endif
         {
           return (mFlags & F_VOIDED) ? nullptr : mData;
         }
 
         // this case operator is the reason why this class cannot just be a
         // typedef for nsTString
       operator const char_type*() const
         {
--- a/xpcom/string/public/nsTSubstring.h
+++ b/xpcom/string/public/nsTSubstring.h
@@ -195,17 +195,21 @@ class nsTSubstring_CharT
           return iter;
         }
 
         /**
          * accessors
          */
 
         // returns pointer to string data (not necessarily null-terminated)
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      char16ptr_t Data() const
+#else
       const char_type *Data() const
+#endif
         {
           return mData;
         }
 
       size_type Length() const
         {
           return mLength;
         }
@@ -258,16 +262,27 @@ class nsTSubstring_CharT
          */
 
       bool NS_FASTCALL Equals( const self_type& ) const;
       bool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const;
 
       bool NS_FASTCALL Equals( const char_type* data ) const;
       bool NS_FASTCALL Equals( const char_type* data, const comparator_type& comp ) const;
 
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      bool NS_FASTCALL Equals( char16ptr_t data ) const
+        {
+          return Equals(static_cast<const char16_t*>(data));
+        }
+      bool NS_FASTCALL Equals( char16ptr_t data, const comparator_type& comp ) const
+        {
+          return Equals(static_cast<const char16_t*>(data), comp);
+        }
+#endif
+
         /**
          * An efficient comparison with ASCII that can be used even
          * for wide strings. Call this version when you know the
          * length of 'data'.
          */
       bool NS_FASTCALL EqualsASCII( const char* data, size_type len ) const;
         /**
          * An efficient comparison with ASCII that can be used even
@@ -346,16 +361,38 @@ class nsTSubstring_CharT
       bool NS_FASTCALL Assign( const char_type* data, size_type length, const fallible_t& ) NS_WARN_UNUSED_RESULT;
 
       void NS_FASTCALL Assign( const self_type& );
       bool NS_FASTCALL Assign( const self_type&, const fallible_t& ) NS_WARN_UNUSED_RESULT;
 
       void NS_FASTCALL Assign( const substring_tuple_type& );
       bool NS_FASTCALL Assign( const substring_tuple_type&, const fallible_t& ) NS_WARN_UNUSED_RESULT;
 
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      void Assign (char16ptr_t data)
+        {
+          Assign(static_cast<const char16_t*>(data));
+        }
+
+      bool Assign(char16ptr_t data, const fallible_t&) NS_WARN_UNUSED_RESULT
+        {
+          return Assign(static_cast<const char16_t*>(data), fallible_t());
+        }
+
+      void Assign (char16ptr_t data, size_type length)
+        {
+          Assign(static_cast<const char16_t*>(data), length);
+        }
+
+      bool Assign(char16ptr_t data, size_type length, const fallible_t&) NS_WARN_UNUSED_RESULT
+        {
+          return Assign(static_cast<const char16_t*>(data), length, fallible_t());
+        }
+#endif
+
       void NS_FASTCALL AssignASCII( const char* data, size_type length );
       bool NS_FASTCALL AssignASCII( const char* data, size_type length, const fallible_t& ) NS_WARN_UNUSED_RESULT;
 
       void NS_FASTCALL AssignASCII( const char* data )
         {
           AssignASCII(data, strlen(data));
         }
       bool NS_FASTCALL AssignASCII( const char* data, const fallible_t& ) NS_WARN_UNUSED_RESULT
@@ -378,16 +415,19 @@ class nsTSubstring_CharT
                   { AssignASCII(str, N-1); }
       template<int N>
       void AssignLiteral( char (&str)[N] )
                   { AssignASCII(str, N-1); }
 #endif
 
       self_type& operator=( char_type c )                                                       { Assign(c);        return *this; }
       self_type& operator=( const char_type* data )                                             { Assign(data);     return *this; }
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      self_type& operator=( char16ptr_t data )                                                  { Assign(data);     return *this; }
+#endif
       self_type& operator=( const self_type& str )                                              { Assign(str);      return *this; }
       self_type& operator=( const substring_tuple_type& tuple )                                 { Assign(tuple);    return *this; }
 
       void NS_FASTCALL Adopt( char_type* data, size_type length = size_type(-1) );
 
 
         /**
          * buffer manipulation
@@ -397,16 +437,21 @@ class nsTSubstring_CharT
       void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) );
       void Replace( index_type cutStart, size_type cutLength, const self_type& str )      { Replace(cutStart, cutLength, str.Data(), str.Length()); }
       void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple );
 
       void NS_FASTCALL ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length = size_type(-1) );
 
       void Append( char_type c )                                                                 { Replace(mLength, 0, c); }
       void Append( const char_type* data, size_type length = size_type(-1) )                     { Replace(mLength, 0, data, length); }
+
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+    void Append( char16ptr_t data, size_type length = size_type(-1) )                            { Append(static_cast<const char16_t*>(data), length); }
+#endif
+
       void Append( const self_type& str )                                                        { Replace(mLength, 0, str); }
       void Append( const substring_tuple_type& tuple )                                           { Replace(mLength, 0, tuple); }
 
       void AppendASCII( const char* data, size_type length = size_type(-1) )                     { ReplaceASCII(mLength, 0, data, length); }
 
       /**
        * Append a formatted string to the current string. Uses the format
        * codes documented in prprf.h
@@ -461,21 +506,28 @@ class nsTSubstring_CharT
                   { AppendASCII(str, N-1); }
       template<int N>
       void AppendLiteral( char (&str)[N] )
                   { AppendASCII(str, N-1); }
 #endif
 
       self_type& operator+=( char_type c )                                                       { Append(c);        return *this; }
       self_type& operator+=( const char_type* data )                                             { Append(data);     return *this; }
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      self_type& operator+=( char16ptr_t data )                                                  { Append(data);     return *this; }
+#endif
       self_type& operator+=( const self_type& str )                                              { Append(str);      return *this; }
       self_type& operator+=( const substring_tuple_type& tuple )                                 { Append(tuple);    return *this; }
 
       void Insert( char_type c, index_type pos )                                                 { Replace(pos, 0, c); }
       void Insert( const char_type* data, index_type pos, size_type length = size_type(-1) )     { Replace(pos, 0, data, length); }
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      void Insert( char16ptr_t data, index_type pos, size_type length = size_type(-1) )
+        { Insert(static_cast<const char16_t*>(data), pos, length); }
+#endif
       void Insert( const self_type& str, index_type pos )                                        { Replace(pos, 0, str); }
       void Insert( const substring_tuple_type& tuple, index_type pos )                           { Replace(pos, 0, tuple); }
 
       void Cut( index_type cutStart, size_type cutLength )                                       { Replace(cutStart, cutLength, char_traits::sEmptyBuffer, 0); }
 
 
         /**
          * buffer sizing
@@ -544,16 +596,28 @@ class nsTSubstring_CharT
               *data = nullptr;
               return 0;
             }
 
           *data = mData;
           return mLength;
         }
 
+#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
+      size_type GetMutableData( wchar_t** data, size_type newLen = size_type(-1) )
+        {
+          return GetMutableData(reinterpret_cast<char16_t**>(data), newLen);
+        }
+
+      size_type GetMutableData( wchar_t** data, size_type newLen, const fallible_t& )
+        {
+    return GetMutableData(reinterpret_cast<char16_t**>(data), newLen, fallible_t());
+        }
+#endif
+
 
         /**
          * string data is never null, but can be marked void.  if true, the
          * string will be truncated.  @see nsTSubstring::IsVoid
          */
 
       void NS_FASTCALL SetIsVoid( bool );