Bug 1673670 - Add vprintf style ctor for nsPrintfCString + tests. r=xpcom-reviewers,sg
☠☠ backed out by 6fac49a5bfab ☠ ☠
authorBryce Seager van Dyk <bvandyk@mozilla.com>
Tue, 27 Oct 2020 18:12:37 +0000
changeset 554767 9bc0aec298c2afa12122b7c562d62ef474802ee5
parent 554766 c398f8d814b6b31a38cb3537c785096879b92777
child 554768 ddfb6f0d4fc5a5334f348f3115b14c23c94c0b4b
push id37898
push userabutkovits@mozilla.com
push dateWed, 28 Oct 2020 09:24:21 +0000
treeherdermozilla-central@83bf4fd3b1fb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxpcom-reviewers, sg
bugs1673670
milestone84.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 1673670 - Add vprintf style ctor for nsPrintfCString + tests. r=xpcom-reviewers,sg Differential Revision: https://phabricator.services.mozilla.com/D94851
xpcom/string/nsPrintfCString.h
xpcom/tests/gtest/TestStrings.cpp
--- a/xpcom/string/nsPrintfCString.h
+++ b/xpcom/string/nsPrintfCString.h
@@ -10,27 +10,44 @@
 #include "nsString.h"
 
 /**
  * nsPrintfCString lets you create a nsCString using a printf-style format
  * string.  For example:
  *
  *   NS_WARNING(nsPrintfCString("Unexpected value: %f", 13.917).get());
  *
+ * nsPrintfCString also allows for vprintf like calling. This is useful for
+ * functions that have already received variadic arguments and want to create
+ * a nsPrintfCString. For example:
+ *
+ * void LogToSeveralLocations(const char* aFormat,...) {
+ *   va_list ap;
+ *   va_start(ap, aFormat);
+ *   nsPrintfCString logString(aFormat, ap);
+ *   va_end(ap);
+ *   // Use logString
+ *  }
+ *
  * nsPrintfCString has a small built-in auto-buffer.  For larger strings, it
  * will allocate on the heap.
  *
  * See also nsCString::AppendPrintf().
  */
 class nsPrintfCString : public nsAutoCStringN<16> {
   typedef nsCString string_type;
 
  public:
   explicit nsPrintfCString(const char_type* aFormat, ...)
       MOZ_FORMAT_PRINTF(2, 3) {
     va_list ap;
     va_start(ap, aFormat);
     AppendPrintf(aFormat, ap);
     va_end(ap);
   }
+
+  nsPrintfCString(const char_type* aFormat, va_list aArgs)
+      MOZ_FORMAT_PRINTF(2, 0) {
+    AppendPrintf(aFormat, aArgs);
+  }
 };
 
 #endif  // !defined(nsPrintfCString_h___)
--- a/xpcom/tests/gtest/TestStrings.cpp
+++ b/xpcom/tests/gtest/TestStrings.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "nsASCIIMask.h"
+#include "nsPrintfCString.h"
 #include "nsString.h"
 #include "nsStringBuffer.h"
 #include "nsReadableUtils.h"
 #include "nsCRTGlue.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/TextUtils.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Utf8.h"
@@ -1963,16 +1964,79 @@ TEST_F(Strings, ConvertToSpan) {
 
   // from non-const string
   {
     auto span = Span{cstring};
     static_assert(std::is_same_v<decltype(span), Span<char>>);
   }
 }
 
+TEST_F(Strings, printf_string) {
+  auto getStringViaVprintfCtor = [](const char* aFormat, ...) {
+    // Ensures creation of an nsPrintfCString via the vprintf style ctor.
+    va_list ap;
+    va_start(ap, aFormat);
+    const nsPrintfCString string(aFormat, ap);
+    va_end(ap);
+    return string;
+  };
+
+  {
+    const char* format = "Characters %c %%";
+    const char* expectedOutput = "Characters B %";
+    const nsPrintfCString printfString(format, 'B');
+    const nsPrintfCString vprintfString(getStringViaVprintfCtor(format, 'B'));
+    EXPECT_TRUE(printfString.Equals(vprintfString))
+        << printfString.get() << " != " << vprintfString.get();
+    EXPECT_TRUE(printfString.EqualsASCII(expectedOutput))
+        << printfString.get() << " != " << expectedOutput;
+  }
+
+  {
+    const char* format = "Strings %s %s";
+    const char* expectedOutput = "Strings foo bar";
+    const nsPrintfCString printfString(format, "foo", "bar");
+    const nsPrintfCString vprintfString(
+        getStringViaVprintfCtor(format, "foo", "bar"));
+    EXPECT_TRUE(printfString.Equals(vprintfString))
+        << printfString.get() << " != " << vprintfString.get();
+    EXPECT_TRUE(printfString.EqualsASCII(expectedOutput))
+        << printfString.get() << " != " << expectedOutput;
+  }
+
+  {
+    const int signedThree = 3;
+    const unsigned int unsignedTen = 10;
+    const char* format = "Integers %i %.3d %.2u %o %x %X";
+    const char* expectedOutput = "Integers 3 003 10 12 a A";
+    const nsPrintfCString printfString(format, signedThree, signedThree,
+                                       unsignedTen, unsignedTen, unsignedTen,
+                                       unsignedTen);
+    const nsPrintfCString vprintfString(
+        getStringViaVprintfCtor(format, signedThree, signedThree, unsignedTen,
+                                unsignedTen, unsignedTen, unsignedTen));
+    EXPECT_TRUE(printfString.Equals(vprintfString))
+        << printfString.get() << " != " << vprintfString.get();
+    EXPECT_TRUE(printfString.EqualsASCII(expectedOutput))
+        << printfString.get() << " != " << expectedOutput;
+  }
+
+  {
+    const char* format = "Floats %f %.0f %e %.2E";
+    const char* expectedOutput = "Floats 1.500000 2 1.500000e+00 1.50E+00";
+    const nsPrintfCString printfString(format, 1.5, 1.5, 1.5, 1.5);
+    const nsPrintfCString vprintfString(
+        getStringViaVprintfCtor(format, 1.5, 1.5, 1.5, 1.5));
+    EXPECT_TRUE(printfString.Equals(vprintfString))
+        << printfString.get() << " != " << vprintfString.get();
+    EXPECT_TRUE(printfString.EqualsASCII(expectedOutput))
+        << printfString.get() << " != " << expectedOutput;
+  }
+}
+
 // Note the five calls in the loop, so divide by 100k
 MOZ_GTEST_BENCH_F(Strings, PerfStripWhitespace, [this] {
   nsCString test1(mExample1Utf8);
   nsCString test2(mExample2Utf8);
   nsCString test3(mExample3Utf8);
   nsCString test4(mExample4Utf8);
   nsCString test5(mExample5Utf8);
   for (int i = 0; i < 20000; i++) {