Add support to TextStream for dumping HashMap<> and HashSet<>
https://bugs.webkit.org/show_bug.cgi?id=202969

Reviewed by Dean Jackson.

Make it possible to output HashMap<> and HashSet<> to TextStream,
so long as key and value types are streamable. Also implement operator<<(char)
so that chars show as ASCII, rather than numbers.

* wtf/text/TextStream.cpp:
(WTF::TextStream::operator<<):
* wtf/text/TextStream.h:
(WTF::operator<<):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251325 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog
index 86faa0d..6fa40cc 100644
--- a/Source/WTF/ChangeLog
+++ b/Source/WTF/ChangeLog
@@ -1,3 +1,19 @@
+2019-10-19  Simon Fraser  <simon.fraser@apple.com>
+
+        Add support to TextStream for dumping HashMap<> and HashSet<>
+        https://bugs.webkit.org/show_bug.cgi?id=202969
+
+        Reviewed by Dean Jackson.
+        
+        Make it possible to output HashMap<> and HashSet<> to TextStream,
+        so long as key and value types are streamable. Also implement operator<<(char)
+        so that chars show as ASCII, rather than numbers.
+
+        * wtf/text/TextStream.cpp:
+        (WTF::TextStream::operator<<):
+        * wtf/text/TextStream.h:
+        (WTF::operator<<):
+
 2019-10-18  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] Make ConcurrentJSLock Lock even if ENABLE_CONCURRENT_JS=OFF
diff --git a/Source/WTF/wtf/text/TextStream.cpp b/Source/WTF/wtf/text/TextStream.cpp
index 5af9462..f9f4cfe 100644
--- a/Source/WTF/wtf/text/TextStream.cpp
+++ b/Source/WTF/wtf/text/TextStream.cpp
@@ -46,6 +46,12 @@
     return *this << (b ? "1" : "0");
 }
 
+TextStream& TextStream::operator<<(char c)
+{
+    m_text.append(c);
+    return *this;
+}
+
 TextStream& TextStream::operator<<(int i)
 {
     m_text.appendNumber(i);
diff --git a/Source/WTF/wtf/text/TextStream.h b/Source/WTF/wtf/text/TextStream.h
index abc6824..316e561 100644
--- a/Source/WTF/wtf/text/TextStream.h
+++ b/Source/WTF/wtf/text/TextStream.h
@@ -57,6 +57,7 @@
     }
 
     WTF_EXPORT_PRIVATE TextStream& operator<<(bool);
+    WTF_EXPORT_PRIVATE TextStream& operator<<(char);
     WTF_EXPORT_PRIVATE TextStream& operator<<(int);
     WTF_EXPORT_PRIVATE TextStream& operator<<(unsigned);
     WTF_EXPORT_PRIVATE TextStream& operator<<(long);
@@ -174,6 +175,15 @@
 }
 
 template<typename Item>
+TextStream& operator<<(TextStream& ts, const Optional<Item>& item)
+{
+    if (item)
+        return ts << item.value();
+    
+    return ts << "nullopt";
+}
+
+template<typename Item>
 TextStream& operator<<(TextStream& ts, const Vector<Item>& vector)
 {
     ts << "[";
@@ -188,6 +198,38 @@
     return ts << "]";
 }
 
+template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
+TextStream& operator<<(TextStream& ts, const HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>& map)
+{
+    ts << "{";
+
+    bool first = true;
+    for (const auto& keyValuePair : map) {
+        ts << keyValuePair.key << ": " << keyValuePair.value;
+        if (!first)
+            ts << ", ";
+        first = false;
+    }
+
+    return ts << "}";
+}
+
+template<typename ValueArg, typename HashArg, typename TraitsArg>
+TextStream& operator<<(TextStream& ts, const HashSet<ValueArg, HashArg, TraitsArg>& set)
+{
+    ts << "[";
+
+    bool first = true;
+    for (const auto& item : set) {
+        ts << item;
+        if (!first)
+            ts << ", ";
+        first = false;
+    }
+
+    return ts << "]";
+}
+
 template<typename Option>
 TextStream& operator<<(TextStream& ts, const OptionSet<Option>& options)
 {