about summary refs log tree commit diff
path: root/absl/strings
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings')
-rw-r--r--absl/strings/escaping.cc110
-rw-r--r--absl/strings/escaping.h2
-rw-r--r--absl/strings/internal/str_join_internal.h57
-rw-r--r--absl/strings/numbers.cc14
-rw-r--r--absl/strings/numbers_test.cc14
5 files changed, 110 insertions, 87 deletions
diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc
index abe9e0aaacd9..fbc9f756315f 100644
--- a/absl/strings/escaping.cc
+++ b/absl/strings/escaping.cc
@@ -366,31 +366,31 @@ std::string CEscapeInternal(absl::string_view src, bool use_hex, bool utf8_safe)
   return dest;
 }
 
+/* clang-format off */
+constexpr char c_escaped_len[256] = {
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4,  // \t, \n, \r
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,  // ", '
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // '0'..'9'
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'A'..'O'
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,  // 'P'..'Z', '\'
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'a'..'o'
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,  // 'p'..'z', DEL
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+};
+/* clang-format on */
+
 // Calculates the length of the C-style escaped version of 'src'.
 // Assumes that non-printable characters are escaped using octal sequences, and
 // that UTF-8 bytes are not handled specially.
 inline size_t CEscapedLength(absl::string_view src) {
-  /* clang-format off */
-  constexpr char c_escaped_len[256] = {
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4,  // \t, \n, \r
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-      1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,  // ", '
-      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // '0'..'9'
-      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'A'..'O'
-      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,  // 'P'..'Z', '\'
-      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'a'..'o'
-      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,  // 'p'..'z', DEL
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-  };
-  /* clang-format on */
-
   size_t escaped_len = 0;
   for (unsigned char c : src) escaped_len += c_escaped_len[c];
   return escaped_len;
@@ -409,41 +409,41 @@ void CEscapeAndAppendInternal(absl::string_view src, std::string* dest) {
   char* append_ptr = &(*dest)[cur_dest_len];
 
   for (unsigned char c : src) {
-    switch (c) {
-      case '\n':
-        *append_ptr++ = '\\';
-        *append_ptr++ = 'n';
-        break;
-      case '\r':
-        *append_ptr++ = '\\';
-        *append_ptr++ = 'r';
-        break;
-      case '\t':
-        *append_ptr++ = '\\';
-        *append_ptr++ = 't';
-        break;
-      case '\"':
-        *append_ptr++ = '\\';
-        *append_ptr++ = '\"';
-        break;
-      case '\'':
-        *append_ptr++ = '\\';
-        *append_ptr++ = '\'';
-        break;
-      case '\\':
-        *append_ptr++ = '\\';
-        *append_ptr++ = '\\';
-        break;
-      default:
-        if (!absl::ascii_isprint(c)) {
+    int char_len = c_escaped_len[c];
+    if (char_len == 1) {
+      *append_ptr++ = c;
+    } else if (char_len == 2) {
+      switch (c) {
+        case '\n':
           *append_ptr++ = '\\';
-          *append_ptr++ = '0' + c / 64;
-          *append_ptr++ = '0' + (c % 64) / 8;
-          *append_ptr++ = '0' + c % 8;
-        } else {
-          *append_ptr++ = c;
-        }
-        break;
+          *append_ptr++ = 'n';
+          break;
+        case '\r':
+          *append_ptr++ = '\\';
+          *append_ptr++ = 'r';
+          break;
+        case '\t':
+          *append_ptr++ = '\\';
+          *append_ptr++ = 't';
+          break;
+        case '\"':
+          *append_ptr++ = '\\';
+          *append_ptr++ = '\"';
+          break;
+        case '\'':
+          *append_ptr++ = '\\';
+          *append_ptr++ = '\'';
+          break;
+        case '\\':
+          *append_ptr++ = '\\';
+          *append_ptr++ = '\\';
+          break;
+      }
+    } else {
+      *append_ptr++ = '\\';
+      *append_ptr++ = '0' + c / 64;
+      *append_ptr++ = '0' + (c % 64) / 8;
+      *append_ptr++ = '0' + c % 8;
     }
   }
 }
diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h
index 23444a987495..86f63aad7dc0 100644
--- a/absl/strings/escaping.h
+++ b/absl/strings/escaping.h
@@ -113,7 +113,7 @@ std::string Utf8SafeCEscape(absl::string_view src);
 // Utf8SafeCHexEscape()
 //
 // Escapes a 'src' std::string using C-style escape sequences, escaping bytes as
-// hexidecimal sequences, and passing through UTF-8 characters without
+// hexadecimal sequences, and passing through UTF-8 characters without
 // conversion.
 std::string Utf8SafeCHexEscape(absl::string_view src);
 
diff --git a/absl/strings/internal/str_join_internal.h b/absl/strings/internal/str_join_internal.h
index e73f1dde403d..c5fdc287cbab 100644
--- a/absl/strings/internal/str_join_internal.h
+++ b/absl/strings/internal/str_join_internal.h
@@ -31,13 +31,15 @@
 #ifndef ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
 #define ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
 
-#include <cassert>
+#include <cstring>
 #include <iterator>
 #include <memory>
 #include <string>
+#include <type_traits>
 #include <utility>
 
 #include "absl/strings/internal/ostringstream.h"
+#include "absl/strings/internal/resize_uninitialized.h"
 #include "absl/strings/str_cat.h"
 
 namespace absl {
@@ -202,28 +204,9 @@ std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
   return result;
 }
 
-// No-op placeholder for input iterators which can not be iterated over.
-template <typename Iterator>
-size_t GetResultSize(Iterator, Iterator, size_t, std::input_iterator_tag) {
-  return 0;
-}
-
-// Calculates space to reserve, if the iterator supports multiple passes.
-template <typename Iterator>
-size_t GetResultSize(Iterator it, Iterator end, size_t separator_size,
-                     std::forward_iterator_tag) {
-  assert(it != end);
-  size_t length = it->size();
-  while (++it != end) {
-    length += separator_size;
-    length += it->size();
-  }
-  return length;
-}
-
-// A joining algorithm that's optimized for an iterator range of std::string-like
-// objects that do not need any additional formatting. This is to optimize the
-// common case of joining, say, a std::vector<std::string> or a
+// A joining algorithm that's optimized for a forward iterator range of
+// std::string-like objects that do not need any additional formatting. This is to
+// optimize the common case of joining, say, a std::vector<std::string> or a
 // std::vector<absl::string_view>.
 //
 // This is an overload of the previous JoinAlgorithm() function. Here the
@@ -236,20 +219,32 @@ size_t GetResultSize(Iterator it, Iterator end, size_t separator_size,
 // std::string to avoid the need to resize while appending. To do this, the iterator
 // range will be traversed twice: once to calculate the total needed size, and
 // then again to copy the elements and delimiters to the output std::string.
-template <typename Iterator>
+template <typename Iterator,
+          typename = typename std::enable_if<std::is_convertible<
+              typename std::iterator_traits<Iterator>::iterator_category,
+              std::forward_iterator_tag>::value>::type>
 std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
                      NoFormatter) {
   std::string result;
   if (start != end) {
-    typename std::iterator_traits<Iterator>::iterator_category iterator_tag;
-    result.reserve(GetResultSize(start, end, s.size(), iterator_tag));
+    // Sums size
+    size_t result_size = start->size();
+    for (Iterator it = start; ++it != end;) {
+      result_size += s.size();
+      result_size += it->size();
+    }
+
+    STLStringResizeUninitialized(&result, result_size);
 
     // Joins strings
-    absl::string_view sep("", 0);
-    for (Iterator it = start; it != end; ++it) {
-      result.append(sep.data(), sep.size());
-      result.append(it->data(), it->size());
-      sep = s;
+    char* result_buf = &*result.begin();
+    memcpy(result_buf, start->data(), start->size());
+    result_buf += start->size();
+    for (Iterator it = start; ++it != end;) {
+      memcpy(result_buf, s.data(), s.size());
+      result_buf += s.size();
+      memcpy(result_buf, it->data(), it->size());
+      result_buf += it->size();
     }
   }
 
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index 31f07c72c949..b4140b3605bc 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -1,3 +1,17 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 // This file contains std::string processing functions related to
 // numeric values.
 
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index a705255c706d..5bb39ca9b5a9 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 // This file tests std::string processing functions related to numeric values.
 
 #include "absl/strings/numbers.h"