Introduce a variant of rtc::split that returns a vector of string_view

Intended to be compatible with absl::StrSplit, but without the binary
cost of that dependency.

Bug: webrtc:13579
Change-Id: I167726903d74b8d5f299886cfb3e5d60610ddb93
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/247185
Reviewed-by: Ali Tofigh <alito@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35780}
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index f29b558..09d31a5 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -210,6 +210,7 @@
     "../rtc_base:socket_address",
     "../rtc_base/system:rtc_export",
   ]
+  absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
 }
 
 rtc_source_set("rtc_pc") {
diff --git a/pc/sdp_serializer.cc b/pc/sdp_serializer.cc
index 3f46db5..cdd2f2e 100644
--- a/pc/sdp_serializer.cc
+++ b/pc/sdp_serializer.cc
@@ -101,33 +101,33 @@
 // sc-id        = [sc-id-paused] rid-id
 // rid-id       = 1*(alpha-numeric / "-" / "_") ; see: I-D.ietf-mmusic-rid
 RTCErrorOr<SimulcastLayerList> ParseSimulcastLayerList(const std::string& str) {
-  std::vector<std::string> tokens;
-  rtc::split(str, kDelimiterSemicolonChar, &tokens);
+  std::vector<absl::string_view> tokens =
+      rtc::split(str, kDelimiterSemicolonChar);
   if (tokens.empty()) {
     return ParseError("Layer list cannot be empty.");
   }
 
   SimulcastLayerList result;
-  for (const std::string& token : tokens) {
+  for (const absl::string_view& token : tokens) {
     if (token.empty()) {
       return ParseError("Simulcast alternative layer list is empty.");
     }
 
-    std::vector<std::string> rid_tokens;
-    rtc::split(token, kDelimiterCommaChar, &rid_tokens);
+    std::vector<absl::string_view> rid_tokens =
+        rtc::split(token, kDelimiterCommaChar);
 
     if (rid_tokens.empty()) {
       return ParseError("Simulcast alternative layer list is malformed.");
     }
 
     std::vector<SimulcastLayer> layers;
-    for (const std::string& rid_token : rid_tokens) {
+    for (const absl::string_view& rid_token : rid_tokens) {
       if (rid_token.empty() || rid_token == kSimulcastPausedStream) {
         return ParseError("Rid must not be empty.");
       }
 
       bool paused = rid_token[0] == kSimulcastPausedStreamChar;
-      std::string rid = paused ? rid_token.substr(1) : rid_token;
+      absl::string_view rid = paused ? rid_token.substr(1) : rid_token;
       layers.push_back(SimulcastLayer(rid, paused));
     }
 
diff --git a/pc/simulcast_description.cc b/pc/simulcast_description.cc
index 0ae3e20..ec87415 100644
--- a/pc/simulcast_description.cc
+++ b/pc/simulcast_description.cc
@@ -14,7 +14,7 @@
 
 namespace cricket {
 
-SimulcastLayer::SimulcastLayer(const std::string& rid, bool is_paused)
+SimulcastLayer::SimulcastLayer(absl::string_view rid, bool is_paused)
     : rid{rid}, is_paused{is_paused} {
   RTC_DCHECK(!rid.empty());
 }
diff --git a/pc/simulcast_description.h b/pc/simulcast_description.h
index f7ae288..7caf164 100644
--- a/pc/simulcast_description.h
+++ b/pc/simulcast_description.h
@@ -16,6 +16,8 @@
 #include <string>
 #include <vector>
 
+#include "absl/strings/string_view.h"
+
 namespace cricket {
 
 // Describes a Simulcast Layer.
@@ -23,7 +25,7 @@
 // See also: https://tools.ietf.org/html/draft-ietf-mmusic-rid-15 for
 // an explanation about rids.
 struct SimulcastLayer final {
-  SimulcastLayer(const std::string& rid, bool is_paused);
+  SimulcastLayer(absl::string_view rid, bool is_paused);
 
   SimulcastLayer(const SimulcastLayer& other) = default;
   SimulcastLayer& operator=(const SimulcastLayer& other) = default;
diff --git a/rtc_base/string_encode.cc b/rtc_base/string_encode.cc
index 364eaa0..85fb992 100644
--- a/rtc_base/string_encode.cc
+++ b/rtc_base/string_encode.cc
@@ -214,19 +214,27 @@
   return joined_string;
 }
 
+std::vector<absl::string_view> split(absl::string_view source, char delimiter) {
+  std::vector<absl::string_view> fields;
+  size_t last = 0;
+  for (size_t i = 0; i < source.length(); ++i) {
+    if (source[i] == delimiter) {
+      fields.push_back(source.substr(last, i - last));
+      last = i + 1;
+    }
+  }
+  fields.push_back(source.substr(last));
+  return fields;
+}
+
 size_t split(absl::string_view source,
              char delimiter,
              std::vector<std::string>* fields) {
   RTC_DCHECK(fields);
   fields->clear();
-  size_t last = 0;
-  for (size_t i = 0; i < source.length(); ++i) {
-    if (source[i] == delimiter) {
-      fields->emplace_back(source.substr(last, i - last));
-      last = i + 1;
-    }
+  for (const absl::string_view field_view : split(source, delimiter)) {
+    fields->emplace_back(field_view);
   }
-  fields->emplace_back(source.substr(last));
   return fields->size();
 }
 
diff --git a/rtc_base/string_encode.h b/rtc_base/string_encode.h
index 356fdfa..d636f7f 100644
--- a/rtc_base/string_encode.h
+++ b/rtc_base/string_encode.h
@@ -62,7 +62,10 @@
 std::string join(const std::vector<std::string>& source, char delimiter);
 
 // Splits the source string into multiple fields separated by delimiter,
-// with duplicates of delimiter creating empty fields.
+// with duplicates of delimiter creating empty fields. Empty input produces a
+// single, empty, field.
+std::vector<absl::string_view> split(absl::string_view source, char delimiter);
+
 size_t split(absl::string_view source,
              char delimiter,
              std::vector<std::string>* fields);