Reimplement rtc::ToString and rtc::FromString without streams.

Bug: webrtc:8982
Change-Id: I3977435b035fdebef449732301d6e77fc899e7ba
Reviewed-on: https://webrtc-review.googlesource.com/86941
Commit-Queue: Jonas Olsson <jonasolsson@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24319}
diff --git a/api/statstypes.cc b/api/statstypes.cc
index ceba28d..ad68894 100644
--- a/api/statstypes.cc
+++ b/api/statstypes.cc
@@ -99,7 +99,7 @@
 
   std::string ToString() const override {
     return std::string(InternalTypeToString(type_)) + kSeparator +
-           rtc::ToString<int>(id_);
+           rtc::ToString(id_);
   }
 
  protected:
@@ -165,7 +165,7 @@
     std::string ret(prefix);
     ret += content_name_;
     ret += '-';
-    ret += rtc::ToString<>(component_);
+    ret += rtc::ToString(component_);
     return ret;
   }
 
@@ -190,7 +190,7 @@
   std::string ToString() const override {
     std::string ret(ComponentId::ToString("Conn-"));
     ret += '-';
-    ret += rtc::ToString<>(index_);
+    ret += rtc::ToString(index_);
     return ret;
   }
 
diff --git a/api/test/fakeconstraints.h b/api/test/fakeconstraints.h
index 429826c..d9c767d 100644
--- a/api/test/fakeconstraints.h
+++ b/api/test/fakeconstraints.h
@@ -30,7 +30,7 @@
 
   template <class T>
   void AddMandatory(const std::string& key, const T& value) {
-    mandatory_.push_back(Constraint(key, rtc::ToString<T>(value)));
+    mandatory_.push_back(Constraint(key, rtc::ToString(value)));
   }
 
   template <class T>
@@ -45,12 +45,12 @@
         }
       }
     }
-    mandatory_.push_back(Constraint(key, rtc::ToString<T>(value)));
+    mandatory_.push_back(Constraint(key, rtc::ToString(value)));
   }
 
   template <class T>
   void AddOptional(const std::string& key, const T& value) {
-    optional_.push_back(Constraint(key, rtc::ToString<T>(value)));
+    optional_.push_back(Constraint(key, rtc::ToString(value)));
   }
 
   void SetMandatoryMinAspectRatio(double ratio) {
diff --git a/examples/peerconnection/server/utils.cc b/examples/peerconnection/server/utils.cc
index 1bcbe6b..dcd1ef7 100644
--- a/examples/peerconnection/server/utils.cc
+++ b/examples/peerconnection/server/utils.cc
@@ -17,9 +17,9 @@
 using rtc::ToString;
 
 std::string int2str(int i) {
-  return ToString<int>(i);
+  return ToString(i);
 }
 
 std::string size_t2str(size_t i) {
-  return ToString<size_t>(i);
+  return ToString(i);
 }
diff --git a/p2p/base/p2ptransportchannel.cc b/p2p/base/p2ptransportchannel.cc
index a2833cd..3fbc90c 100644
--- a/p2p/base/p2ptransportchannel.cc
+++ b/p2p/base/p2ptransportchannel.cc
@@ -867,7 +867,7 @@
     // The foundation of the candidate is set to an arbitrary value, different
     // from the foundation for all other remote candidates.
     remote_candidate.set_foundation(
-        rtc::ToString<uint32_t>(rtc::ComputeCrc32(remote_candidate.id())));
+        rtc::ToString(rtc::ComputeCrc32(remote_candidate.id())));
   }
 
   // RFC5245, the agent constructs a pair whose local candidate is equal to
diff --git a/p2p/base/port.cc b/p2p/base/port.cc
index 81d59ba..8ab33a3 100644
--- a/p2p/base/port.cc
+++ b/p2p/base/port.cc
@@ -208,7 +208,7 @@
                                      const rtc::SocketAddress& base_address) {
   std::ostringstream ost;
   ost << type << base_address.ipaddr().ToString() << protocol << relay_protocol;
-  return rtc::ToString<uint32_t>(rtc::ComputeCrc32(ost.str()));
+  return rtc::ToString(rtc::ComputeCrc32(ost.str()));
 }
 
 CandidateStats::CandidateStats() = default;
diff --git a/pc/rtcstatscollector.cc b/pc/rtcstatscollector.cc
index 9b7708e..c7555fd 100644
--- a/pc/rtcstatscollector.cc
+++ b/pc/rtcstatscollector.cc
@@ -995,7 +995,7 @@
        pc_->sctp_data_channels()) {
     std::unique_ptr<RTCDataChannelStats> data_channel_stats(
         new RTCDataChannelStats(
-            "RTCDataChannel_" + rtc::ToString<>(data_channel->id()),
+            "RTCDataChannel_" + rtc::ToString(data_channel->id()),
             timestamp_us));
     data_channel_stats->label = data_channel->label();
     data_channel_stats->protocol = data_channel->protocol();
diff --git a/pc/rtcstatscollector_unittest.cc b/pc/rtcstatscollector_unittest.cc
index 178440b..3ece85f 100644
--- a/pc/rtcstatscollector_unittest.cc
+++ b/pc/rtcstatscollector_unittest.cc
@@ -586,12 +586,12 @@
     graph.sender = stats_->SetupLocalTrackAndSender(
         cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 3, false);
     graph.sender_track_id = "RTCMediaStreamTrack_sender_" +
-                            rtc::ToString<>(graph.sender->AttachmentId());
+                            rtc::ToString(graph.sender->AttachmentId());
     // track (receiver) and stream (remote stream)
     graph.receiver = stats_->SetupRemoteTrackAndReceiver(
         cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 4);
     graph.receiver_track_id = "RTCMediaStreamTrack_receiver_" +
-                              rtc::ToString<>(graph.receiver->AttachmentId());
+                              rtc::ToString(graph.receiver->AttachmentId());
     graph.remote_stream_id = "RTCMediaStream_RemoteStreamId";
     // peer-connection
     graph.peer_connection_id = "RTCPeerConnection";
@@ -1121,7 +1121,7 @@
                                          report->timestamp_us());
   expected_pair.transport_id =
       "RTCTransport_transport_" +
-      rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
+      rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP);
   expected_pair.local_candidate_id = "RTCIceCandidate_" + local_candidate->id();
   expected_pair.remote_candidate_id =
       "RTCIceCandidate_" + remote_candidate->id();
@@ -1853,7 +1853,7 @@
 
   RTCTransportStats expected_rtp_transport(
       "RTCTransport_transport_" +
-          rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP),
+          rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP),
       report->timestamp_us());
   expected_rtp_transport.bytes_sent = 42;
   expected_rtp_transport.bytes_received = 1337;
@@ -1883,7 +1883,7 @@
 
   RTCTransportStats expected_rtcp_transport(
       "RTCTransport_transport_" +
-          rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTCP),
+          rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTCP),
       report->timestamp_us());
   expected_rtcp_transport.bytes_sent = 1337;
   expected_rtcp_transport.bytes_received = 42;
diff --git a/pc/statscollector.cc b/pc/statscollector.cc
index 9a77a21..23a4493 100644
--- a/pc/statscollector.cc
+++ b/pc/statscollector.cc
@@ -582,7 +582,7 @@
   StatsReport::Id id(StatsReport::NewIdWithDirection(
       local ? StatsReport::kStatsReportTypeSsrc
             : StatsReport::kStatsReportTypeRemoteSsrc,
-      rtc::ToString<uint32_t>(ssrc), direction));
+      rtc::ToString(ssrc), direction));
   StatsReport* report = reports_.Find(id);
 
   // Use the ID of the track that is currently mapped to the SSRC, if any.
@@ -1004,8 +1004,8 @@
       continue;
     }
     const StatsReport::Id stats_id = StatsReport::NewIdWithDirection(
-        StatsReport::kStatsReportTypeSsrc,
-        rtc::ToString<uint32_t>(sender->ssrc()), StatsReport::kSend);
+        StatsReport::kStatsReportTypeSsrc, rtc::ToString(sender->ssrc()),
+        StatsReport::kSend);
     StatsReport* report = reports_.FindOrAddNew(stats_id);
     report->AddInt(StatsReport::kStatsValueNameFrameWidthInput,
                    stats.input_width);
@@ -1051,9 +1051,8 @@
   for (const auto& it : local_audio_tracks_) {
     AudioTrackInterface* track = it.first;
     uint32_t ssrc = it.second;
-    StatsReport* report =
-        GetReport(StatsReport::kStatsReportTypeSsrc,
-                  rtc::ToString<uint32_t>(ssrc), StatsReport::kSend);
+    StatsReport* report = GetReport(StatsReport::kStatsReportTypeSsrc,
+                                    rtc::ToString(ssrc), StatsReport::kSend);
     if (report == NULL) {
       // This can happen if a local audio track is added to a stream on the
       // fly and the report has not been set up yet. Do nothing in this case.
diff --git a/pc/statscollector_unittest.cc b/pc/statscollector_unittest.cc
index 2a2a2dc..fa4d3db 100644
--- a/pc/statscollector_unittest.cc
+++ b/pc/statscollector_unittest.cc
@@ -283,69 +283,67 @@
   std::string value_in_report;
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAudioOutputLevel,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.audio_level), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.audio_level), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameBytesReceived,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int64_t>(info.bytes_rcvd), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.bytes_rcvd), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.jitter_ms), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.jitter_ms), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterBufferMs,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.jitter_buffer_ms), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.jitter_buffer_ms), value_in_report);
   EXPECT_TRUE(GetValue(report,
                        StatsReport::kStatsValueNamePreferredJitterBufferMs,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.jitter_buffer_preferred_ms),
-            value_in_report);
+  EXPECT_EQ(rtc::ToString(info.jitter_buffer_preferred_ms), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCurrentDelayMs,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.delay_estimate_ms), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.delay_estimate_ms), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameExpandRate,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<float>(info.expand_rate), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.expand_rate), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSpeechExpandRate,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<float>(info.speech_expand_rate), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.speech_expand_rate), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAccelerateRate,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<float>(info.accelerate_rate), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.accelerate_rate), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePreemptiveExpandRate,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<float>(info.preemptive_expand_rate), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.preemptive_expand_rate), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSecondaryDecodedRate,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<float>(info.secondary_decoded_rate), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.secondary_decoded_rate), value_in_report);
   EXPECT_TRUE(GetValue(report,
                        StatsReport::kStatsValueNameSecondaryDiscardedRate,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<float>(info.secondary_discarded_rate),
-            value_in_report);
+  EXPECT_EQ(rtc::ToString(info.secondary_discarded_rate), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsReceived,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.packets_rcvd), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.packets_rcvd), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCTSG,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.decoding_calls_to_silence_generator),
+  EXPECT_EQ(rtc::ToString(info.decoding_calls_to_silence_generator),
             value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCTN,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.decoding_calls_to_neteq), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.decoding_calls_to_neteq), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingNormal,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.decoding_normal), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.decoding_normal), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingPLC,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.decoding_plc), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.decoding_plc), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCNG,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.decoding_cng), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.decoding_cng), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingPLCCNG,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.decoding_plc_cng), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.decoding_plc_cng), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingMutedOutput,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(info.decoding_muted_output), value_in_report);
+  EXPECT_EQ(rtc::ToString(info.decoding_muted_output), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCodecName,
                        &value_in_report));
 }
@@ -358,26 +356,26 @@
   EXPECT_EQ(sinfo.codec_name, value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameBytesSent,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int64_t>(sinfo.bytes_sent), value_in_report);
+  EXPECT_EQ(rtc::ToString(sinfo.bytes_sent), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsSent,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(sinfo.packets_sent), value_in_report);
+  EXPECT_EQ(rtc::ToString(sinfo.packets_sent), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsLost,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(sinfo.packets_lost), value_in_report);
+  EXPECT_EQ(rtc::ToString(sinfo.packets_lost), value_in_report);
   EXPECT_TRUE(
       GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(sinfo.rtt_ms), value_in_report);
+  EXPECT_EQ(rtc::ToString(sinfo.rtt_ms), value_in_report);
   EXPECT_TRUE(
       GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(sinfo.rtt_ms), value_in_report);
+  EXPECT_EQ(rtc::ToString(sinfo.rtt_ms), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(sinfo.jitter_ms), value_in_report);
+  EXPECT_EQ(rtc::ToString(sinfo.jitter_ms), value_in_report);
   if (sinfo.apm_statistics.delay_median_ms) {
     EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
                          &value_in_report));
-    EXPECT_EQ(rtc::ToString<int>(*sinfo.apm_statistics.delay_median_ms),
+    EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.delay_median_ms),
               value_in_report);
   } else {
     EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
@@ -386,9 +384,8 @@
   if (sinfo.apm_statistics.delay_standard_deviation_ms) {
     EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
                          &value_in_report));
-    EXPECT_EQ(
-        rtc::ToString<int>(*sinfo.apm_statistics.delay_standard_deviation_ms),
-        value_in_report);
+    EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.delay_standard_deviation_ms),
+              value_in_report);
   } else {
     EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
                           &value_in_report));
@@ -396,7 +393,7 @@
   if (sinfo.apm_statistics.echo_return_loss) {
     EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoReturnLoss,
                          &value_in_report));
-    EXPECT_EQ(rtc::ToString<int>(*sinfo.apm_statistics.echo_return_loss),
+    EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.echo_return_loss),
               value_in_report);
   } else {
     EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoReturnLoss,
@@ -406,9 +403,8 @@
     EXPECT_TRUE(GetValue(report,
                          StatsReport::kStatsValueNameEchoReturnLossEnhancement,
                          &value_in_report));
-    EXPECT_EQ(
-        rtc::ToString<int>(*sinfo.apm_statistics.echo_return_loss_enhancement),
-        value_in_report);
+    EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.echo_return_loss_enhancement),
+              value_in_report);
   } else {
     EXPECT_FALSE(GetValue(report,
                           StatsReport::kStatsValueNameEchoReturnLossEnhancement,
@@ -418,9 +414,8 @@
     EXPECT_TRUE(GetValue(report,
                          StatsReport::kStatsValueNameResidualEchoLikelihood,
                          &value_in_report));
-    EXPECT_EQ(
-        rtc::ToString<float>(*sinfo.apm_statistics.residual_echo_likelihood),
-        value_in_report);
+    EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.residual_echo_likelihood),
+              value_in_report);
   } else {
     EXPECT_FALSE(GetValue(report,
                           StatsReport::kStatsValueNameResidualEchoLikelihood,
@@ -430,7 +425,7 @@
     EXPECT_TRUE(GetValue(
         report, StatsReport::kStatsValueNameResidualEchoLikelihoodRecentMax,
         &value_in_report));
-    EXPECT_EQ(rtc::ToString<float>(
+    EXPECT_EQ(rtc::ToString(
                   *sinfo.apm_statistics.residual_echo_likelihood_recent_max),
               value_in_report);
   } else {
@@ -440,7 +435,7 @@
   }
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAudioInputLevel,
                        &value_in_report));
-  EXPECT_EQ(rtc::ToString<int>(sinfo.audio_level), value_in_report);
+  EXPECT_EQ(rtc::ToString(sinfo.audio_level), value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameTypingNoiseState,
                        &value_in_report));
   std::string typing_detected = sinfo.typing_noise_detected ? "true" : "false";
@@ -449,47 +444,42 @@
                        StatsReport::kStatsValueNameAnaBitrateActionCounter,
                        &value_in_report));
   ASSERT_TRUE(sinfo.ana_statistics.bitrate_action_counter);
-  EXPECT_EQ(
-      rtc::ToString<uint32_t>(*sinfo.ana_statistics.bitrate_action_counter),
-      value_in_report);
+  EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.bitrate_action_counter),
+            value_in_report);
   EXPECT_TRUE(GetValue(report,
                        StatsReport::kStatsValueNameAnaChannelActionCounter,
                        &value_in_report));
   ASSERT_TRUE(sinfo.ana_statistics.channel_action_counter);
-  EXPECT_EQ(
-      rtc::ToString<uint32_t>(*sinfo.ana_statistics.channel_action_counter),
-      value_in_report);
+  EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.channel_action_counter),
+            value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaDtxActionCounter,
                        &value_in_report));
   ASSERT_TRUE(sinfo.ana_statistics.dtx_action_counter);
-  EXPECT_EQ(rtc::ToString<uint32_t>(*sinfo.ana_statistics.dtx_action_counter),
+  EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.dtx_action_counter),
             value_in_report);
   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaFecActionCounter,
                        &value_in_report));
   ASSERT_TRUE(sinfo.ana_statistics.fec_action_counter);
-  EXPECT_EQ(rtc::ToString<uint32_t>(*sinfo.ana_statistics.fec_action_counter),
+  EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.fec_action_counter),
             value_in_report);
   EXPECT_TRUE(GetValue(
       report, StatsReport::kStatsValueNameAnaFrameLengthIncreaseCounter,
       &value_in_report));
   ASSERT_TRUE(sinfo.ana_statistics.frame_length_increase_counter);
-  EXPECT_EQ(rtc::ToString<uint32_t>(
-                *sinfo.ana_statistics.frame_length_increase_counter),
+  EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.frame_length_increase_counter),
             value_in_report);
   EXPECT_TRUE(GetValue(
       report, StatsReport::kStatsValueNameAnaFrameLengthDecreaseCounter,
       &value_in_report));
   ASSERT_TRUE(sinfo.ana_statistics.frame_length_decrease_counter);
-  EXPECT_EQ(rtc::ToString<uint32_t>(
-                *sinfo.ana_statistics.frame_length_decrease_counter),
+  EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.frame_length_decrease_counter),
             value_in_report);
   EXPECT_TRUE(GetValue(report,
                        StatsReport::kStatsValueNameAnaUplinkPacketLossFraction,
                        &value_in_report));
   ASSERT_TRUE(sinfo.ana_statistics.uplink_packet_loss_fraction);
-  EXPECT_EQ(
-      rtc::ToString<float>(*sinfo.ana_statistics.uplink_packet_loss_fraction),
-      value_in_report);
+  EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.uplink_packet_loss_fraction),
+            value_in_report);
 }
 
 // Helper methods to avoid duplication of code.
@@ -591,7 +581,7 @@
     EXPECT_EQ(audio_track->id(), track_id);
     std::string ssrc_id =
         ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameSsrc);
-    EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id);
+    EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
 
     std::string media_type =
         ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameMediaType);
@@ -617,7 +607,7 @@
     EXPECT_EQ(audio_track->id(), track_id);
     ssrc_id =
         ExtractSsrcStatsValue(track_reports, StatsReport::kStatsValueNameSsrc);
-    EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id);
+    EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
     if (!voice_info.senders.empty()) {
       VerifyVoiceSenderInfoReport(track_report, voice_info.senders[0]);
     }
@@ -823,7 +813,7 @@
   EXPECT_EQ(kDataChannelLabel,
             ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
                               StatsReport::kStatsValueNameLabel));
-  EXPECT_EQ(rtc::ToString<int64_t>(kDataChannelId),
+  EXPECT_EQ(rtc::ToString(kDataChannelId),
             ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
                               StatsReport::kStatsValueNameDataChannelId));
   EXPECT_EQ(kConnectingString,
@@ -1054,7 +1044,7 @@
 
   std::string ssrc_id =
       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
-  EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id);
+  EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
 
   std::string track_id =
       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
@@ -1190,7 +1180,7 @@
 
   std::string ssrc_id =
       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
-  EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id);
+  EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
 
   std::string track_id =
       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
@@ -1573,7 +1563,7 @@
   EXPECT_EQ(kLocalTrackId, track_id);
   std::string ssrc_id =
       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
-  EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id);
+  EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
 
   // Verifies the values in the track report, no value will be changed by the
   // AudioTrackInterface::GetSignalValue() and
diff --git a/pc/videocapturertracksource_unittest.cc b/pc/videocapturertracksource_unittest.cc
index 1ddfc6f..d2b8e15 100644
--- a/pc/videocapturertracksource_unittest.cc
+++ b/pc/videocapturertracksource_unittest.cc
@@ -449,7 +449,7 @@
 
 TEST_F(VideoCapturerTrackSourceTest, MandatorySubOneFpsConstraints) {
   FakeConstraints constraints;
-  constraints.AddMandatory(MediaConstraintsInterface::kMaxFrameRate, 0.5);
+  constraints.AddMandatory(MediaConstraintsInterface::kMaxFrameRate, 0);
 
   CreateVideoCapturerSource(&constraints);
   EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
@@ -459,7 +459,7 @@
 
 TEST_F(VideoCapturerTrackSourceTest, OptionalSubOneFpsConstraints) {
   FakeConstraints constraints;
-  constraints.AddOptional(MediaConstraintsInterface::kMaxFrameRate, 0.5);
+  constraints.AddOptional(MediaConstraintsInterface::kMaxFrameRate, 0);
 
   CreateVideoCapturerSource(&constraints);
   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
diff --git a/pc/webrtcsdp.cc b/pc/webrtcsdp.cc
index 9cb9e06..73df354 100644
--- a/pc/webrtcsdp.cc
+++ b/pc/webrtcsdp.cc
@@ -1282,7 +1282,7 @@
              video_desc->codecs().begin();
          it != video_desc->codecs().end(); ++it) {
       fmt.append(" ");
-      fmt.append(rtc::ToString<int>(it->id));
+      fmt.append(rtc::ToString(it->id));
     }
   } else if (media_type == cricket::MEDIA_TYPE_AUDIO) {
     const AudioContentDescription* audio_desc = media_desc->as_audio();
@@ -1290,7 +1290,7 @@
              audio_desc->codecs().begin();
          it != audio_desc->codecs().end(); ++it) {
       fmt.append(" ");
-      fmt.append(rtc::ToString<int>(it->id));
+      fmt.append(rtc::ToString(it->id));
     }
   } else if (media_type == cricket::MEDIA_TYPE_DATA) {
     const DataContentDescription* data_desc = media_desc->as_data();
@@ -1308,7 +1308,7 @@
           }
         }
 
-        fmt.append(rtc::ToString<int>(sctp_port));
+        fmt.append(rtc::ToString(sctp_port));
       } else {
         fmt.append(kDefaultSctpmapProtocol);
       }
@@ -1317,7 +1317,7 @@
                data_desc->codecs().begin();
            it != data_desc->codecs().end(); ++it) {
         fmt.append(" ");
-        fmt.append(rtc::ToString<int>(it->id));
+        fmt.append(rtc::ToString(it->id));
       }
     }
   }
@@ -1596,7 +1596,7 @@
       std::vector<uint32_t>::const_iterator ssrc =
           track->ssrc_groups[i].ssrcs.begin();
       for (; ssrc != track->ssrc_groups[i].ssrcs.end(); ++ssrc) {
-        os << kSdpDelimiterSpace << rtc::ToString<uint32_t>(*ssrc);
+        os << kSdpDelimiterSpace << rtc::ToString(*ssrc);
       }
       AddLine(os.str(), message);
     }
diff --git a/pc/webrtcsdp_unittest.cc b/pc/webrtcsdp_unittest.cc
index b2dc47a..bfae1b9 100644
--- a/pc/webrtcsdp_unittest.cc
+++ b/pc/webrtcsdp_unittest.cc
@@ -1713,7 +1713,7 @@
                             int expected_value) {
     cricket::CodecParameterMap::const_iterator found = params.find(name);
     ASSERT_TRUE(found != params.end());
-    EXPECT_EQ(found->second, rtc::ToString<int>(expected_value));
+    EXPECT_EQ(found->second, rtc::ToString(expected_value));
   }
 
   void TestDeserializeCodecParams(const CodecParams& params,
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index c076b21..6b34ade 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -314,6 +314,8 @@
 
 rtc_source_set("stringutils") {
   sources = [
+    "string_to_number.cc",
+    "string_to_number.h",
     "stringencode.cc",
     "stringencode.h",
     "strings/string_builder.cc",
@@ -323,8 +325,10 @@
   ]
   deps = [
     ":checks",
+    ":macromagic",
     ":safe_minmax",
     "../api:array_view",
+    "//third_party/abseil-cpp/absl/types:optional",
   ]
 }
 
@@ -428,8 +432,6 @@
     "rate_statistics.h",
     "ratetracker.cc",
     "ratetracker.h",
-    "string_to_number.cc",
-    "string_to_number.h",
     "swap_queue.h",
     "template_util.h",
     "timestampaligner.cc",
diff --git a/rtc_base/optionsfile.cc b/rtc_base/optionsfile.cc
index 8d2d2e0..535859b 100644
--- a/rtc_base/optionsfile.cc
+++ b/rtc_base/optionsfile.cc
@@ -165,7 +165,8 @@
   if (!IsLegalName(option)) {
     return false;
   }
-  return ToString(value, &options_[option]);
+  options_[option] = ToString(value);
+  return true;
 }
 
 bool OptionsFile::RemoveValue(const std::string& option) {
diff --git a/rtc_base/string_to_number.cc b/rtc_base/string_to_number.cc
index 06ac9e9..9201242 100644
--- a/rtc_base/string_to_number.cc
+++ b/rtc_base/string_to_number.cc
@@ -48,5 +48,41 @@
   return absl::nullopt;
 }
 
+template <typename T>
+T StrToT(const char* str, char** str_end);
+
+template <>
+inline float StrToT(const char* str, char** str_end) {
+  return std::strtof(str, str_end);
+}
+
+template <>
+inline double StrToT(const char* str, char** str_end) {
+  return std::strtod(str, str_end);
+}
+
+template <>
+inline long double StrToT(const char* str, char** str_end) {
+  return std::strtold(str, str_end);
+}
+
+template <typename T>
+absl::optional<T> ParseFloatingPoint(const char* str) {
+  RTC_DCHECK(str);
+  if (*str == '\0')
+    return absl::nullopt;
+  char* end = nullptr;
+  errno = 0;
+  const T value = StrToT<T>(str, &end);
+  if (end && *end == '\0' && errno == 0) {
+    return value;
+  }
+  return absl::nullopt;
+}
+
+template absl::optional<float> ParseFloatingPoint(const char* str);
+template absl::optional<double> ParseFloatingPoint(const char* str);
+template absl::optional<long double> ParseFloatingPoint(const char* str);
+
 }  // namespace string_to_number_internal
 }  // namespace rtc
diff --git a/rtc_base/string_to_number.h b/rtc_base/string_to_number.h
index 9b4fa67..7ea9f25 100644
--- a/rtc_base/string_to_number.h
+++ b/rtc_base/string_to_number.h
@@ -48,6 +48,9 @@
 
 absl::optional<signed_type> ParseSigned(const char* str, int base);
 absl::optional<unsigned_type> ParseUnsigned(const char* str, int base);
+
+template <typename T>
+absl::optional<T> ParseFloatingPoint(const char* str);
 }  // namespace string_to_number_internal
 
 template <typename T>
@@ -88,6 +91,17 @@
   return absl::nullopt;
 }
 
+template <typename T>
+typename std::enable_if<std::is_floating_point<T>::value,
+                        absl::optional<T>>::type
+StringToNumber(const char* str, int base = 10) {
+  static_assert(
+      std::numeric_limits<T>::max() <= std::numeric_limits<long double>::max(),
+      "StringToNumber only supports floating-point numbers as large "
+      "as long double");
+  return string_to_number_internal::ParseFloatingPoint<T>(str);
+}
+
 // The std::string overloads only exists if there is a matching const char*
 // version.
 template <typename T>
diff --git a/rtc_base/stringencode.cc b/rtc_base/stringencode.cc
index 8e7c6d7..b410477 100644
--- a/rtc_base/stringencode.cc
+++ b/rtc_base/stringencode.cc
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/stringutils.h"
 
@@ -410,4 +411,90 @@
   return fields->size();
 }
 
+std::string ToString(const bool b) {
+  return b ? "true" : "false";
+}
+
+std::string ToString(const char* const s) {
+  return std::string(s);
+}
+std::string ToString(const std::string s) {
+  return s;
+}
+
+std::string ToString(const short s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%hd", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const unsigned short s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%hu", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%d", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const unsigned int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%u", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const long int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%ld", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const unsigned long int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%lu", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const long long int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%lld", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const unsigned long long int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%llu", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+
+std::string ToString(const double d) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%g", d);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+
+std::string ToString(const void* const p) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%p", p);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+
+bool FromString(const std::string& s, bool* b) {
+  if (s == "false") {
+    *b = false;
+    return true;
+  }
+  if (s == "true") {
+    *b = true;
+    return true;
+  }
+  return false;
+}
+
 }  // namespace rtc
diff --git a/rtc_base/stringencode.h b/rtc_base/stringencode.h
index 7042c4a..830ea77 100644
--- a/rtc_base/stringencode.h
+++ b/rtc_base/stringencode.h
@@ -16,6 +16,7 @@
 #include <vector>
 
 #include "rtc_base/checks.h"
+#include "rtc_base/string_to_number.h"
 
 namespace rtc {
 
@@ -147,32 +148,40 @@
                     std::string* rest);
 
 // Convert arbitrary values to/from a string.
+// TODO(jonasolsson): Remove these when absl::StrCat becomes available.
+std::string ToString(bool b);
 
-template <class T>
-static bool ToString(const T& t, std::string* s) {
-  RTC_DCHECK(s);
-  std::ostringstream oss;
-  oss << std::boolalpha << t;
-  *s = oss.str();
-  return !oss.fail();
-}
+std::string ToString(const char* s);
+std::string ToString(std::string t);
 
-template <class T>
+std::string ToString(short s);
+std::string ToString(unsigned short s);
+std::string ToString(int s);
+std::string ToString(unsigned int s);
+std::string ToString(long int s);
+std::string ToString(unsigned long int s);
+std::string ToString(long long int s);
+std::string ToString(unsigned long long int s);
+
+std::string ToString(double t);
+
+std::string ToString(const void* p);
+
+template <typename T,
+          typename std::enable_if<std::is_arithmetic<T>::value &&
+                                      !std::is_same<T, bool>::value,
+                                  int>::type = 0>
 static bool FromString(const std::string& s, T* t) {
   RTC_DCHECK(t);
-  std::istringstream iss(s);
-  iss >> std::boolalpha >> *t;
-  return !iss.fail();
+  absl::optional<T> result = StringToNumber<T>(s);
+
+  if (result)
+    *t = *result;
+
+  return result.has_value();
 }
 
-// Inline versions of the string conversion routines.
-
-template <typename T>
-static inline std::string ToString(const T& val) {
-  std::string str;
-  ToString(val, &str);
-  return str;
-}
+bool FromString(const std::string& s, bool* b);
 
 template <typename T>
 static inline T FromString(const std::string& str) {
@@ -181,13 +190,6 @@
   return val;
 }
 
-template <typename T>
-static inline T FromString(const T& defaultValue, const std::string& str) {
-  T val(defaultValue);
-  FromString(str, &val);
-  return val;
-}
-
 //////////////////////////////////////////////////////////////////////
 
 }  // namespace rtc
diff --git a/rtc_base/stringencode_unittest.cc b/rtc_base/stringencode_unittest.cc
index ffb90b2..9bdc592 100644
--- a/rtc_base/stringencode_unittest.cc
+++ b/rtc_base/stringencode_unittest.cc
@@ -13,6 +13,8 @@
 #include "rtc_base/gunit.h"
 #include "rtc_base/stringutils.h"
 
+#include <sstream>  // no-presubmit-check TODO(webrtc:8982)
+
 namespace rtc {
 
 class HexEncodeTest : public testing::Test {
@@ -351,53 +353,79 @@
   ASSERT_STREQ("", fields.at(0).c_str());
 }
 
-TEST(BoolTest, DecodeValid) {
-  bool value;
-  EXPECT_TRUE(FromString("true", &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString("true,", &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString("true , true", &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString("true ,\n false", &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString("  true  \n", &value));
-  EXPECT_TRUE(value);
+TEST(ToString, SanityCheck) {
+  EXPECT_EQ(ToString(true), "true");
+  EXPECT_EQ(ToString(false), "false");
 
-  EXPECT_TRUE(FromString("false", &value));
-  EXPECT_FALSE(value);
-  EXPECT_TRUE(FromString("  false ", &value));
-  EXPECT_FALSE(value);
-  EXPECT_TRUE(FromString("  false, ", &value));
-  EXPECT_FALSE(value);
+  const char* c = "message";
+  EXPECT_EQ(ToString(c), c);
+  EXPECT_EQ(ToString(std::string(c)), c);
 
-  EXPECT_TRUE(FromString<bool>("true\n"));
-  EXPECT_FALSE(FromString<bool>("false\n"));
+  EXPECT_EQ(ToString(short{-123}), "-123");
+  EXPECT_EQ(ToString((unsigned short)123), "123");
+  EXPECT_EQ(ToString(int{-123}), "-123");
+  EXPECT_EQ(ToString((unsigned int)123), "123");
+  EXPECT_EQ(ToString((long int)-123), "-123");
+  EXPECT_EQ(ToString((unsigned long int)123), "123");
+  EXPECT_EQ(ToString((long long int)-123), "-123");
+  EXPECT_EQ(ToString((unsigned long long int)123), "123");
+
+  int i = 10;
+  int* p = &i;
+  std::ostringstream s;  // no-presubmit-check TODO(webrtc:8982)
+  s << p;
+  EXPECT_EQ(s.str(), ToString(p));
+
+  EXPECT_EQ(ToString(0.5), "0.5");
 }
 
-TEST(BoolTest, DecodeInvalid) {
-  bool value;
-  EXPECT_FALSE(FromString("True", &value));
-  EXPECT_FALSE(FromString("TRUE", &value));
-  EXPECT_FALSE(FromString("False", &value));
-  EXPECT_FALSE(FromString("FALSE", &value));
-  EXPECT_FALSE(FromString("0", &value));
-  EXPECT_FALSE(FromString("1", &value));
-  EXPECT_FALSE(FromString("0,", &value));
-  EXPECT_FALSE(FromString("1,", &value));
-  EXPECT_FALSE(FromString("1,0", &value));
-  EXPECT_FALSE(FromString("1.", &value));
-  EXPECT_FALSE(FromString("1.0", &value));
-  EXPECT_FALSE(FromString("", &value));
-  EXPECT_FALSE(FromString<bool>("false\nfalse"));
+template <typename T>
+void ParsesTo(std::string s, T t) {
+  T value;
+  EXPECT_TRUE(FromString(s, &value));
+  EXPECT_EQ(value, t);
 }
 
-TEST(BoolTest, RoundTrip) {
-  bool value;
-  EXPECT_TRUE(FromString(ToString(true), &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString(ToString(false), &value));
-  EXPECT_FALSE(value);
+TEST(FromString, DecodeValid) {
+  ParsesTo("true", true);
+  ParsesTo("false", false);
+
+  ParsesTo("105", 105);
+  ParsesTo("0.25", 0.25);
+}
+
+template <typename T>
+void FailsToParse(std::string s) {
+  T value;
+  EXPECT_FALSE(FromString(s, &value)) << "[" << s << "]";
+}
+
+TEST(FromString, DecodeInvalid) {
+  FailsToParse<bool>("True");
+  FailsToParse<bool>("0");
+  FailsToParse<bool>("yes");
+
+  FailsToParse<int>("0.5");
+  FailsToParse<int>("XIV");
+  FailsToParse<double>("");
+  FailsToParse<double>("  ");
+  FailsToParse<int>("1 2");
+}
+
+template <typename T>
+void RoundTrip(T t) {
+  std::string s = ToString(t);
+  T value;
+  EXPECT_TRUE(FromString(s, &value));
+  EXPECT_EQ(value, t);
+}
+
+TEST(FromString, RoundTrip) {
+  RoundTrip<int>(123);
+  RoundTrip(false);
+  RoundTrip(true);
+  RoundTrip(0.5);
+  RoundTrip(-15l);
 }
 
 }  // namespace rtc
diff --git a/stats/rtcstats.cc b/stats/rtcstats.cc
index 0a348e9..a274660 100644
--- a/stats/rtcstats.cc
+++ b/stats/rtcstats.cc
@@ -26,9 +26,9 @@
   if (vector.empty())
     return "[]";
   std::ostringstream oss;
-  oss << "[" << rtc::ToString<T>(vector[0]);
+  oss << "[" << rtc::ToString(vector[0]);
   for (size_t i = 1; i < vector.size(); ++i) {
-    oss << "," << rtc::ToString<T>(vector[i]);
+    oss << "," << rtc::ToString(vector[i]);
   }
   oss << "]";
   return oss.str();
@@ -41,9 +41,9 @@
   if (strings.empty())
     return "[]";
   std::ostringstream oss;
-  oss << "[\"" << rtc::ToString<T>(strings[0]) << '\"';
+  oss << "[\"" << rtc::ToString(strings[0]) << '\"';
   for (size_t i = 1; i < strings.size(); ++i) {
-    oss << ",\"" << rtc::ToString<T>(strings[i]) << '\"';
+    oss << ",\"" << rtc::ToString(strings[i]) << '\"';
   }
   oss << "]";
   return oss.str();