Bug 380783 - nsStringAPI.h: no equivalent of IsVoid (tell if string is null), patch by Mook <mook.moz+mozbz@gmail.com>, r=bsmedberg/dbaron, sr=dbaron, a1.9=bz
authorphilringnalda@gmail.com
Fri, 17 Aug 2007 20:48:16 -0700
changeset 4782 4cda155bcb307ebdac1d103ee3cefe9440e8a3f1
parent 4781 ffc4b809db3beb2618e57d6307ed74e143f2a859
child 4783 63e8513c41e2b9402f54725de8bc48cbcfa46fb4
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg, dbaron, dbaron
bugs380783
milestone1.9a8pre
Bug 380783 - nsStringAPI.h: no equivalent of IsVoid (tell if string is null), patch by Mook <mook.moz+mozbz@gmail.com>, r=bsmedberg/dbaron, sr=dbaron, a1.9=bz
xpcom/build/nsXPCOMPrivate.h
xpcom/build/nsXPCOMStrings.cpp
xpcom/glue/nsStringAPI.h
xpcom/glue/standalone/nsXPCOMGlue.cpp
xpcom/string/public/nsXPCOMStrings.h
xpcom/stub/nsXPComStub.cpp
xpcom/tests/Makefile.in
xpcom/tests/TestStringAPI.cpp
--- a/xpcom/build/nsXPCOMPrivate.h
+++ b/xpcom/build/nsXPCOMPrivate.h
@@ -78,26 +78,30 @@ typedef nsresult   (* StringContainerIni
 typedef nsresult   (* StringContainerInit2Func)(nsStringContainer&, const PRUnichar *, PRUint32, PRUint32);
 typedef void       (* StringContainerFinishFunc)(nsStringContainer&);
 typedef PRUint32   (* StringGetDataFunc)(const nsAString&, const PRUnichar**, PRBool*);
 typedef PRUint32   (* StringGetMutableDataFunc)(nsAString&, PRUint32, PRUnichar**);
 typedef PRUnichar* (* StringCloneDataFunc)(const nsAString&);
 typedef nsresult   (* StringSetDataFunc)(nsAString&, const PRUnichar*, PRUint32);
 typedef nsresult   (* StringSetDataRangeFunc)(nsAString&, PRUint32, PRUint32, const PRUnichar*, PRUint32);
 typedef nsresult   (* StringCopyFunc)(nsAString &, const nsAString &);
+typedef void       (* StringSetIsVoidFunc)(nsAString &, const PRBool);
+typedef PRBool     (* StringGetIsVoidFunc)(const nsAString &);
 
 typedef nsresult   (* CStringContainerInitFunc)(nsCStringContainer&);
 typedef nsresult   (* CStringContainerInit2Func)(nsCStringContainer&, const char *, PRUint32, PRUint32);
 typedef void       (* CStringContainerFinishFunc)(nsCStringContainer&);
 typedef PRUint32   (* CStringGetDataFunc)(const nsACString&, const char**, PRBool*);
 typedef PRUint32   (* CStringGetMutableDataFunc)(nsACString&, PRUint32, char**);
 typedef char*      (* CStringCloneDataFunc)(const nsACString&);
 typedef nsresult   (* CStringSetDataFunc)(nsACString&, const char*, PRUint32);
 typedef nsresult   (* CStringSetDataRangeFunc)(nsACString&, PRUint32, PRUint32, const char*, PRUint32);
 typedef nsresult   (* CStringCopyFunc)(nsACString &, const nsACString &);
+typedef void       (* CStringSetIsVoidFunc)(nsACString &, const PRBool);
+typedef PRBool     (* CStringGetIsVoidFunc)(const nsACString &);
 
 typedef nsresult   (* CStringToUTF16)(const nsACString &, nsCStringEncoding, nsAString &);
 typedef nsresult   (* UTF16ToCString)(const nsAString &, nsCStringEncoding, nsACString &);
 
 typedef void*      (* AllocFunc)(PRSize size);
 typedef void*      (* ReallocFunc)(void* ptr, PRSize size);
 typedef void       (* FreeFunc)(void* ptr);
 
@@ -180,16 +184,20 @@ typedef struct XPCOMFunctions{
     LogCtorFunc logDtorFunc;
     LogCOMPtrFunc logCOMPtrAddRefFunc;
     LogCOMPtrFunc logCOMPtrReleaseFunc;
     GetXPTCallStubFunc getXPTCallStubFunc;
     DestroyXPTCallStubFunc destroyXPTCallStubFunc;
     InvokeByIndexFunc invokeByIndexFunc;
     CycleCollectorFunc cycleSuspectFunc;
     CycleCollectorFunc cycleForgetFunc;
+    StringSetIsVoidFunc stringSetIsVoid;
+    StringGetIsVoidFunc stringGetIsVoid;
+    CStringSetIsVoidFunc cstringSetIsVoid;
+    CStringGetIsVoidFunc cstringGetIsVoid;
 
 } XPCOMFunctions;
 
 typedef nsresult (PR_CALLBACK *GetFrozenFunctionsFunc)(XPCOMFunctions *entryPoints, const char* libraryPath);
 XPCOM_API(nsresult)
 NS_GetFrozenFunctions(XPCOMFunctions *entryPoints, const char* libraryPath);
 
 // think hard before changing this
--- a/xpcom/build/nsXPCOMStrings.cpp
+++ b/xpcom/build/nsXPCOMStrings.cpp
@@ -184,16 +184,28 @@ NS_StringSetDataRange(nsAString &aStr,
 
 XPCOM_API(nsresult)
 NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
 {
   aDest.Assign(aSrc);
   return NS_OK; // XXX report errors
 }
 
+XPCOM_API(void)
+NS_StringSetIsVoid(nsAString &aStr, const PRBool aIsVoid)
+{
+  aStr.SetIsVoid(aIsVoid);
+}
+
+XPCOM_API(PRBool)
+NS_StringGetIsVoid(const nsAString &aStr)
+{
+  return aStr.IsVoid();
+}
+
 /* ------------------------------------------------------------------------- */
 
 XPCOM_API(nsresult)
 NS_CStringContainerInit(nsCStringContainer &aContainer)
 {
   NS_ASSERTION(sizeof(nsStringContainer_base) >= sizeof(nsCString),
       "nsCStringContainer is not large enough");
 
@@ -331,16 +343,28 @@ NS_CStringSetDataRange(nsACString &aStr,
 
 XPCOM_API(nsresult)
 NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
 {
   aDest.Assign(aSrc);
   return NS_OK; // XXX report errors
 }
 
+XPCOM_API(void)
+NS_CStringSetIsVoid(nsACString &aStr, const PRBool aIsVoid)
+{
+  aStr.SetIsVoid(aIsVoid);
+}
+
+XPCOM_API(PRBool)
+NS_CStringGetIsVoid(const nsACString &aStr)
+{
+  return aStr.IsVoid();
+}
+
 /* ------------------------------------------------------------------------- */
 
 XPCOM_API(nsresult)
 NS_CStringToUTF16(const nsACString &aSrc,
                   nsCStringEncoding aSrcEncoding,
                   nsAString &aDest)
 {
   switch (aSrcEncoding)
--- a/xpcom/glue/nsStringAPI.h
+++ b/xpcom/glue/nsStringAPI.h
@@ -107,16 +107,25 @@ public:
     return NS_StringGetData(*this, &data);
   }
 
   NS_HIDDEN_(PRBool) IsEmpty() const
   {
     return Length() == 0;
   }
 
+  NS_HIDDEN_(void) SetIsVoid(PRBool val)
+  {
+    NS_StringSetIsVoid(*this, val);
+  }
+  NS_HIDDEN_(PRBool) IsVoid() const
+  {
+    return NS_StringGetIsVoid(*this);
+  }
+
   NS_HIDDEN_(void) Assign(const self_type& aString)
   {
     NS_StringCopy(*this, aString);
   }
   NS_HIDDEN_(void) Assign(const char_type* aData, size_type aLength = PR_UINT32_MAX)
   {
     NS_StringSetData(*this, aData, aLength);
   }
@@ -382,16 +391,25 @@ public:
     return NS_CStringGetData(*this, &data);
   }
 
   NS_HIDDEN_(PRBool) IsEmpty() const
   {
     return Length() == 0;
   }
 
+  NS_HIDDEN_(void) SetIsVoid(PRBool val)
+  {
+    NS_CStringSetIsVoid(*this, val);
+  }
+  NS_HIDDEN_(PRBool) IsVoid() const
+  {
+    return NS_CStringGetIsVoid(*this);
+  }
+
   NS_HIDDEN_(void) Assign(const self_type& aString)
   {
     NS_CStringCopy(*this, aString);
   }
   NS_HIDDEN_(void) Assign(const char_type* aData, size_type aLength = PR_UINT32_MAX)
   {
     NS_CStringSetData(*this, aData, aLength);
   }
--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
+++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -300,16 +300,30 @@ NS_StringSetDataRange(nsAString &aStr, P
 XPCOM_API(nsresult)
 NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
 {
     if (!xpcomFunctions.stringCopy)
         return NS_ERROR_NOT_INITIALIZED;
     return xpcomFunctions.stringCopy(aDest, aSrc);
 }
 
+XPCOM_API(void)
+NS_StringSetIsVoid(nsAString &aStr, const PRBool aIsVoid)
+{
+    if (xpcomFunctions.stringSetIsVoid)
+        xpcomFunctions.stringSetIsVoid(aStr, aIsVoid);
+}
+
+XPCOM_API(PRBool)
+NS_StringGetIsVoid(const nsAString &aStr)
+{
+    if (!xpcomFunctions.stringGetIsVoid)
+        return PR_FALSE;
+    return xpcomFunctions.stringGetIsVoid(aStr);
+}
 
 XPCOM_API(nsresult)
 NS_CStringContainerInit(nsCStringContainer &aStr)
 {
     if (!xpcomFunctions.cstringContainerInit)
         return NS_ERROR_NOT_INITIALIZED;
     return xpcomFunctions.cstringContainerInit(aStr);
 }
@@ -380,16 +394,31 @@ NS_CStringSetDataRange(nsACString &aStr,
 XPCOM_API(nsresult)
 NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
 {
     if (!xpcomFunctions.cstringCopy)
         return NS_ERROR_NOT_INITIALIZED;
     return xpcomFunctions.cstringCopy(aDest, aSrc);
 }
 
+XPCOM_API(void)
+NS_CStringSetIsVoid(nsACString &aStr, const PRBool aIsVoid)
+{
+    if (xpcomFunctions.cstringSetIsVoid)
+        xpcomFunctions.cstringSetIsVoid(aStr, aIsVoid);
+}
+
+XPCOM_API(PRBool)
+NS_CStringGetIsVoid(const nsACString &aStr)
+{
+    if (!xpcomFunctions.cstringGetIsVoid)
+        return PR_FALSE;
+    return xpcomFunctions.cstringGetIsVoid(aStr);
+}
+
 XPCOM_API(nsresult)
 NS_CStringToUTF16(const nsACString &aSrc, nsCStringEncoding aSrcEncoding, nsAString &aDest)
 {
     if (!xpcomFunctions.cstringToUTF16)
         return NS_ERROR_NOT_INITIALIZED;
     return xpcomFunctions.cstringToUTF16(aSrc, aSrcEncoding, aDest);
 }
 
--- a/xpcom/string/public/nsXPCOMStrings.h
+++ b/xpcom/string/public/nsXPCOMStrings.h
@@ -55,25 +55,29 @@
 # define NS_StringContainerInit2          NS_StringContainerInit2_P
 # define NS_StringContainerFinish         NS_StringContainerFinish_P
 # define NS_StringGetData                 NS_StringGetData_P
 # define NS_StringGetMutableData          NS_StringGetMutableData_P
 # define NS_StringCloneData               NS_StringCloneData_P
 # define NS_StringSetData                 NS_StringSetData_P
 # define NS_StringSetDataRange            NS_StringSetDataRange_P
 # define NS_StringCopy                    NS_StringCopy_P
+# define NS_StringSetIsVoid               NS_StringSetIsVoid_P
+# define NS_StringGetIsVoid               NS_StringGetIsVoid_P
 # define NS_CStringContainerInit          NS_CStringContainerInit_P
 # define NS_CStringContainerInit2         NS_CStringContainerInit2_P
 # define NS_CStringContainerFinish        NS_CStringContainerFinish_P
 # define NS_CStringGetData                NS_CStringGetData_P
 # define NS_CStringGetMutableData         NS_CStringGetMutableData_P
 # define NS_CStringCloneData              NS_CStringCloneData_P
 # define NS_CStringSetData                NS_CStringSetData_P
 # define NS_CStringSetDataRange           NS_CStringSetDataRange_P
 # define NS_CStringCopy                   NS_CStringCopy_P
+# define NS_CStringSetIsVoid              NS_CStringSetIsVoid_P
+# define NS_CStringGetIsVoid              NS_CStringGetIsVoid_P
 # define NS_CStringToUTF16                NS_CStringToUTF16_P
 # define NS_UTF16ToCString                NS_UTF16ToCString_P
 #endif
 
 #include "nscore.h"
 
 /* The base string types */
 class nsAString;
@@ -439,16 +443,34 @@ NS_StringInsertData(nsAString &aStr, PRU
  * @return              NS_OK if function succeeded
  */
 inline NS_HIDDEN_(nsresult)
 NS_StringCutData(nsAString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength)
 {
   return NS_StringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0);
 }
 
+/**
+ * NS_StringSetIsVoid
+ *
+ * This function marks a string as being a "void string".  Any data in the
+ * string will be lost.
+ */
+XPCOM_API(void)
+NS_StringSetIsVoid(nsAString& aStr, const PRBool aIsVoid);
+
+/**
+ * NS_StringGetIsVoid
+ *
+ * This function provides a way to test if a string is a "void string", as
+ * marked by NS_StringSetIsVoid.
+ */
+XPCOM_API(PRBool)
+NS_StringGetIsVoid(const nsAString& aStr);
+
 /* ------------------------------------------------------------------------- */
 
 /**
  * nsCStringContainer
  *
  * This is an opaque data type that is large enough to hold the canonical
  * implementation of nsACString.  The binary structure of this class is an
  * implementation detail.
@@ -744,16 +766,34 @@ NS_CStringInsertData(nsACString &aStr, P
  * @return              NS_OK if function succeeded
  */
 inline NS_HIDDEN_(nsresult)
 NS_CStringCutData(nsACString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength)
 {
   return NS_CStringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0);
 }
 
+/**
+ * NS_CStringSetIsVoid
+ *
+ * This function marks a string as being a "void string".  Any data in the
+ * string will be lost.
+ */
+XPCOM_API(void)
+NS_CStringSetIsVoid(nsACString& aStr, const PRBool aIsVoid);
+
+/**
+ * NS_CStringGetIsVoid
+ *
+ * This function provides a way to test if a string is a "void string", as
+ * marked by NS_CStringSetIsVoid.
+ */
+XPCOM_API(PRBool)
+NS_CStringGetIsVoid(const nsACString& aStr);
+
 /* ------------------------------------------------------------------------- */
 
 /**
  * Encodings that can be used with the following conversion routines.
  */
 enum nsCStringEncoding {
   /* Conversion between ASCII and UTF-16 assumes that all bytes in the source
    * string are 7-bit ASCII and can be inflated to UTF-16 by inserting null
--- a/xpcom/stub/nsXPComStub.cpp
+++ b/xpcom/stub/nsXPComStub.cpp
@@ -111,17 +111,21 @@ static const XPCOMFunctions kFrozenFunct
     &NS_LogCtor_P,
     &NS_LogDtor_P,
     &NS_LogCOMPtrAddRef_P,
     &NS_LogCOMPtrRelease_P,
     &NS_GetXPTCallStub_P,
     &NS_DestroyXPTCallStub_P,
     &NS_InvokeByIndex_P,
     &NS_CycleCollectorSuspect_P,
-    &NS_CycleCollectorForget_P
+    &NS_CycleCollectorForget_P,
+    &NS_StringSetIsVoid_P,
+    &NS_StringGetIsVoid_P,
+    &NS_CStringSetIsVoid_P,
+    &NS_CStringGetIsVoid_P
 };
 
 EXPORT_XPCOM_API(nsresult)
 NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* /* libraryPath */)
 {
     if (!functions)
         return NS_ERROR_OUT_OF_MEMORY;
 
@@ -422,16 +426,30 @@ NS_StringSetDataRange(nsAString &aStr, P
 
 #undef NS_StringCopy
 EXPORT_XPCOM_API(nsresult)
 NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
 {
   return NS_StringCopy_P(aDest, aSrc);
 }
 
+#undef NS_StringSetIsVoid
+EXPORT_XPCOM_API(void)
+NS_StringSetIsVoid(nsAString &aStr, const PRBool aIsVoid)
+{
+  NS_StringSetIsVoid_P(aStr, aIsVoid);
+}
+
+#undef NS_StringGetIsVoid
+EXPORT_XPCOM_API(PRBool)
+NS_StringGetIsVoid(const nsAString &aStr)
+{
+  return NS_StringGetIsVoid_P(aStr);
+}
+
 #undef NS_CStringContainerInit
 EXPORT_XPCOM_API(nsresult)
 NS_CStringContainerInit(nsCStringContainer &aStr)
 {
   return NS_CStringContainerInit_P(aStr);
 }
 
 #undef NS_CStringContainerInit2
@@ -489,16 +507,30 @@ NS_CStringSetDataRange(nsACString &aStr,
 
 #undef NS_CStringCopy
 EXPORT_XPCOM_API(nsresult)
 NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
 {
   return NS_CStringCopy_P(aDest, aSrc);
 }
 
+#undef NS_CStringSetIsVoid
+EXPORT_XPCOM_API(void)
+NS_CStringSetIsVoid(nsACString &aStr, const PRBool aIsVoid)
+{
+  NS_CStringSetIsVoid_P(aStr, aIsVoid);
+}
+
+#undef NS_CStringGetIsVoid
+EXPORT_XPCOM_API(PRBool)
+NS_CStringGetIsVoid(const nsACString &aStr)
+{
+  return NS_CStringGetIsVoid_P(aStr);
+}
+
 #undef NS_CStringToUTF16
 EXPORT_XPCOM_API(nsresult)
 NS_CStringToUTF16(const nsACString &aSrc, nsCStringEncoding aSrcEncoding, nsAString &aDest)
 {
   return NS_CStringToUTF16_P(aSrc, aSrcEncoding, aDest);
 }
 
 #undef NS_UTF16ToCString
--- a/xpcom/tests/Makefile.in
+++ b/xpcom/tests/Makefile.in
@@ -87,16 +87,22 @@ CPPSRCS += \
 		TestXPIDLString.cpp \
 		TestDeque.cpp \
 		TestStrings.cpp \
 		TestStorageStream.cpp \
 		TestExpirationTracker.cpp \
 		$(NULL)
 endif
 
+ifndef MOZILLA_INTERNAL_API
+CPPSRCS += \
+		TestStringAPI.cpp \
+		$(NULL)
+endif
+
 #CPPSRCS		+= TimerTest.cpp
 
 SIMPLE_PROGRAMS	= $(CPPSRCS:.cpp=$(BIN_SUFFIX))
 
 include $(topsrcdir)/config/config.mk
 
 ifndef MOZILLA_INTERNAL_API
 LIBS +=	$(DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX)
new file mode 100644
--- /dev/null
+++ b/xpcom/tests/TestStringAPI.cpp
@@ -0,0 +1,134 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM external strings test.
+ *
+ * The Initial Developer of the Original Code is
+ * Mook <mook.moz@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <cstdio>
+#include "nsStringAPI.h"
+
+#define CHECK(x) \
+  _doCheck(x, #x, __LINE__)
+
+int _doCheck(bool cond, const char* msg, int line) {
+  if (cond) return 0;
+  fprintf(stderr, "FAIL: line %d: %s\n", line, msg);
+  return 1;
+}
+
+int testEmpty() {
+  nsString s;
+  return CHECK(0 == s.Length()) +
+         CHECK(s.IsEmpty());
+}
+
+int testAccess() {
+  nsString s;
+  s.Assign(NS_LITERAL_STRING("hello"));
+  int res = CHECK(5 == s.Length()) +
+            CHECK(s.EqualsLiteral("hello"));
+  const PRUnichar *it, *end;
+  int len = s.BeginReading(&it, &end);
+  res += CHECK(5 == len);
+  res += CHECK(PRUnichar('h') == it[0]) +
+         CHECK(PRUnichar('e') == it[1]) +
+         CHECK(PRUnichar('l') == it[2]) +
+         CHECK(PRUnichar('l') == it[3]) +
+         CHECK(PRUnichar('o') == it[4]) +
+         CHECK(it + len == end);
+  res += CHECK(s[0] == s.First());
+  for (int i = 0; i < len; ++i) {
+    res += CHECK(s[i] == it[i]);
+    res += CHECK(s[i] == s.CharAt(i));
+  }
+  res += CHECK(it == s.BeginReading());
+  res += CHECK(end == s.EndReading());
+  return res;
+}
+
+int testWrite() {
+  nsString s(NS_LITERAL_STRING("xyzz"));
+  PRUnichar *begin, *end;
+  int res = CHECK(4 == s.Length());
+  PRUint32 len = s.BeginWriting(&begin, &end, 5);
+  res += CHECK(5 == s.Length()) +
+         CHECK(5 == len) +
+         CHECK(end == begin + 5) +
+         CHECK(begin == s.BeginWriting()) +
+         CHECK(end == s.EndWriting());
+  begin[4] = PRUnichar('y');
+  res += CHECK(s.Equals(NS_LITERAL_STRING("xyzzy")));
+  s.SetLength(4);
+  res += CHECK(4 == s.Length()) +
+         CHECK(s.Equals(NS_LITERAL_STRING("xyzz"))) +
+         CHECK(!s.Equals(NS_LITERAL_STRING("xyzzy"))) +
+         CHECK(!s.IsEmpty());
+  s.Truncate();
+  res += CHECK(0 == s.Length()) +
+         CHECK(s.IsEmpty());
+  const PRUnichar sample[] = { 's', 'a', 'm', 'p', 'l', 'e', '\0' };
+  s.Assign(sample);
+  res += CHECK(s.EqualsLiteral("sample"));
+  s.Assign(sample, 4);
+  res += CHECK(s.EqualsLiteral("samp"));
+  s.Assign(PRUnichar('q'));
+  res += CHECK(s.EqualsLiteral("q"));
+  return res;
+}
+
+int testVoid() {
+  nsString s;
+  int ret = CHECK(!s.IsVoid());
+  s.SetIsVoid(PR_FALSE);
+  ret += CHECK(!s.IsVoid());
+  s.SetIsVoid(PR_TRUE);
+  ret += CHECK(s.IsVoid());
+  s.SetIsVoid(PR_FALSE);
+  ret += CHECK(!s.IsVoid());
+  s.SetIsVoid(PR_TRUE);
+  s.AssignLiteral("hello");
+  ret += CHECK(!s.IsVoid());
+  return ret;
+}
+
+int main() {
+  int rv = 0;
+  rv += testEmpty();
+  rv += testAccess();
+  rv += testWrite();
+  rv += testVoid();
+  if (0 == rv) {
+    fprintf(stderr, "PASS: StringAPI tests\n");
+  }
+  return rv;
+}