Start de-duplicating the regular and wide printf implementations.

This patch switches to C++ (in anticipation of needing it later), removes
a little duplication (via a macro for now), and ensures uniform support
for %C/%lc and %S/%ls between regular and wide (with new tests).

Since it's so hard to debug problems in printf (as the time I've wasted
already today will testify), that's all I want to do in this change. The
other 500 lines of diff can wait...

(Also merge "floatio.h" into "local.h" now all the users are in forked
code.)

Bug: http://b/67371539
Test: ran tests
Change-Id: I083353d89c32b9302d759ca6967cc6d8a62cd8a5
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 97b222c..e07980e 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -302,6 +302,13 @@
   EXPECT_STREQ("<a>", buf);
 }
 
+TEST(STDIO_TEST, snprintf_C) { // Synonym for %lc.
+  char buf[BUFSIZ];
+  wchar_t wc = L'a';
+  EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%C>", wc));
+  EXPECT_STREQ("<a>", buf);
+}
+
 TEST(STDIO_TEST, snprintf_ls) {
   char buf[BUFSIZ];
   wchar_t* ws = NULL;
@@ -314,6 +321,18 @@
   EXPECT_STREQ("<hi>", buf);
 }
 
+TEST(STDIO_TEST, snprintf_S) { // Synonym for %ls.
+  char buf[BUFSIZ];
+  wchar_t* ws = NULL;
+  EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%S>", ws));
+  EXPECT_STREQ("<(null)>", buf);
+
+  wchar_t chars[] = { L'h', L'i', 0 };
+  ws = chars;
+  EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%S>", ws));
+  EXPECT_STREQ("<hi>", buf);
+}
+
 TEST(STDIO_TEST, snprintf_n) {
 #if defined(__BIONIC__)
   // http://b/14492135
@@ -584,6 +603,24 @@
   ASSERT_EQ(std::wstring(L"0x1.921fb54411744p+1"), buf);
 }
 
+TEST(STDIO_TEST, swprintf_lc) {
+  constexpr size_t nchars = 32;
+  wchar_t buf[nchars];
+
+  wint_t wc = L'a';
+  EXPECT_EQ(3, swprintf(buf, nchars, L"<%lc>", wc));
+  EXPECT_EQ(std::wstring(L"<a>"), buf);
+}
+
+TEST(STDIO_TEST, swprintf_C) { // Synonym for %lc.
+  constexpr size_t nchars = 32;
+  wchar_t buf[nchars];
+
+  wint_t wc = L'a';
+  EXPECT_EQ(3, swprintf(buf, nchars, L"<%C>", wc));
+  EXPECT_EQ(std::wstring(L"<a>"), buf);
+}
+
 TEST(STDIO_TEST, swprintf_ls) {
   constexpr size_t nchars = 32;
   wchar_t buf[nchars];
@@ -595,6 +632,17 @@
   ASSERT_EQ(std::wstring(kWideString), buf);
 }
 
+TEST(STDIO_TEST, swprintf_S) { // Synonym for %ls.
+  constexpr size_t nchars = 32;
+  wchar_t buf[nchars];
+
+  static const wchar_t kWideString[] = L"Hello\uff41 World";
+  ASSERT_EQ(12, swprintf(buf, nchars, L"%S", kWideString));
+  ASSERT_EQ(std::wstring(kWideString), buf);
+  ASSERT_EQ(12, swprintf(buf, 13, L"%S", kWideString));
+  ASSERT_EQ(std::wstring(kWideString), buf);
+}
+
 TEST(STDIO_TEST, snprintf_d_INT_MAX) {
   char buf[BUFSIZ];
   snprintf(buf, sizeof(buf), "%d", INT_MAX);
@@ -639,6 +687,30 @@
   EXPECT_STREQ("-9223372036854775808", buf);
 }
 
+TEST(STDIO_TEST, snprintf_o_UINT_MAX) {
+  char buf[BUFSIZ];
+  snprintf(buf, sizeof(buf), "%o", UINT_MAX);
+  EXPECT_STREQ("37777777777", buf);
+}
+
+TEST(STDIO_TEST, snprintf_u_UINT_MAX) {
+  char buf[BUFSIZ];
+  snprintf(buf, sizeof(buf), "%u", UINT_MAX);
+  EXPECT_STREQ("4294967295", buf);
+}
+
+TEST(STDIO_TEST, snprintf_x_UINT_MAX) {
+  char buf[BUFSIZ];
+  snprintf(buf, sizeof(buf), "%x", UINT_MAX);
+  EXPECT_STREQ("ffffffff", buf);
+}
+
+TEST(STDIO_TEST, snprintf_X_UINT_MAX) {
+  char buf[BUFSIZ];
+  snprintf(buf, sizeof(buf), "%X", UINT_MAX);
+  EXPECT_STREQ("FFFFFFFF", buf);
+}
+
 TEST(STDIO_TEST, snprintf_e) {
   char buf[BUFSIZ];