// 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