|  | // Copyright 2024 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "quiche/common/vectorized_io_utils.h" | 
|  |  | 
|  | #include <algorithm> | 
|  | #include <cstddef> | 
|  | #include <cstring> | 
|  |  | 
|  | #include "absl/base/optimization.h" | 
|  | #include "absl/base/prefetch.h" | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "absl/types/span.h" | 
|  |  | 
|  | namespace quiche { | 
|  |  | 
|  | size_t TotalStringViewSpanSize(absl::Span<const absl::string_view> span) { | 
|  | size_t total = 0; | 
|  | for (absl::string_view view : span) { | 
|  | total += view.size(); | 
|  | } | 
|  | return total; | 
|  | } | 
|  |  | 
|  | size_t GatherStringViewSpan(absl::Span<const absl::string_view> inputs, | 
|  | absl::Span<char> output) { | 
|  | size_t bytes_copied = 0; | 
|  | for (size_t i = 0; i < inputs.size(); ++i) { | 
|  | if (inputs[i].empty()) { | 
|  | continue; | 
|  | } | 
|  | const size_t bytes_to_copy = std::min(inputs[i].size(), output.size()); | 
|  | if (bytes_to_copy == 0) { | 
|  | break; | 
|  | } | 
|  | const absl::Span<char> next_output = output.subspan(bytes_to_copy); | 
|  |  | 
|  | // Prefetch the first two lines of the next input; the hardware prefetcher | 
|  | // is expected to take care of the rest. | 
|  | if (!next_output.empty() && (i + 1) < inputs.size() && | 
|  | !inputs[i + 1].empty()) { | 
|  | absl::PrefetchToLocalCache(&inputs[i + 1][0]); | 
|  | if (inputs[i + 1].size() > ABSL_CACHELINE_SIZE) { | 
|  | absl::PrefetchToLocalCache(&inputs[i + 1][ABSL_CACHELINE_SIZE]); | 
|  | } | 
|  | } | 
|  |  | 
|  | memcpy(output.data(), inputs[i].data(), bytes_to_copy); | 
|  | bytes_copied += bytes_to_copy; | 
|  | output = next_output; | 
|  | } | 
|  | return bytes_copied; | 
|  | } | 
|  |  | 
|  | }  // namespace quiche |