From cfc34dd41d63f45b0587d089b8ec7fc2ed27c04e Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Sun, 18 Dec 2022 18:08:20 -0500
Subject: [PATCH] common: Add ScratchBuffer class

This class creates a default initialized heap allocated buffer for cases where value initializing members during allocation or resize
is redundant.
---
 src/common/CMakeLists.txt   |  1 +
 src/common/scratch_buffer.h | 74 +++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)
 create mode 100644 src/common/scratch_buffer.h

diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index f558f5a585..eb05e46a86 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -102,6 +102,7 @@ add_library(common STATIC
     ${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp
     scm_rev.h
     scope_exit.h
+    scratch_buffer.h
     settings.cpp
     settings.h
     settings_input.cpp
diff --git a/src/common/scratch_buffer.h b/src/common/scratch_buffer.h
new file mode 100644
index 0000000000..afbe2eee13
--- /dev/null
+++ b/src/common/scratch_buffer.h
@@ -0,0 +1,74 @@
+// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/make_unique_for_overwrite.h"
+
+namespace Common {
+
+/**
+ * ScratchBuffer class
+ * This class creates a default initialized heap allocated buffer for cases such as intermediate
+ * buffers being copied into entirely, where value initializing members during allocation or resize
+ * is redundant.
+ */
+template <typename T>
+class ScratchBuffer {
+public:
+    ScratchBuffer() = default;
+
+    explicit ScratchBuffer(size_t initial_capacity)
+        : last_requested_size{initial_capacity}, capacity{initial_capacity},
+          buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {}
+
+    ~ScratchBuffer() = default;
+
+    /// This will only grow the buffer's capacity if size is greater than the current capacity.
+    void resize(size_t size) {
+        if (size > capacity) {
+            capacity = size;
+            buffer = Common::make_unique_for_overwrite<T[]>(capacity);
+        }
+        last_requested_size = size;
+    }
+
+    [[nodiscard]] T* data() noexcept {
+        return buffer.get();
+    }
+
+    [[nodiscard]] const T* data() const noexcept {
+        return buffer.get();
+    }
+
+    [[nodiscard]] T* begin() noexcept {
+        return data();
+    }
+
+    [[nodiscard]] const T* begin() const noexcept {
+        return data();
+    }
+
+    [[nodiscard]] T* end() noexcept {
+        return data() + last_requested_size;
+    }
+
+    [[nodiscard]] const T* end() const noexcept {
+        return data() + last_requested_size;
+    }
+
+    [[nodiscard]] T& operator[](size_t i) {
+        return buffer[i];
+    }
+
+    [[nodiscard]] size_t size() const noexcept {
+        return last_requested_size;
+    }
+
+private:
+    size_t last_requested_size{};
+    size_t capacity{};
+    std::unique_ptr<T[]> buffer{};
+};
+
+} // namespace Common