ipc: Allow all trivially copyable objects to be passed directly into WriteBuffer

With the support of C++20, we can use concepts to deduce if a type is an STL container or not.
This commit is contained in:
David Marcec
2020-08-03 17:44:41 +10:00
parent 0c262f8ac2
commit 31b05ae92b
11 changed files with 46 additions and 27 deletions

View File

@@ -110,6 +110,7 @@ add_library(common STATIC
common_funcs.h
common_paths.h
common_types.h
concepts.h
dynamic_library.cpp
dynamic_library.h
fiber.cpp

18
src/common/concepts.h Normal file
View File

@@ -0,0 +1,18 @@
// Copyright 2020 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <concepts>
// Check if type is like an STL container
template <typename T>
concept IsSTLContainer = requires(T t) {
typename T::value_type;
// TODO(ogniK): Replace below is std::same_as<void> when MSVC supports it.
t.begin();
t.end();
t.data();
t.size();
};

View File

@@ -13,6 +13,7 @@
#include <vector>
#include <boost/container/small_vector.hpp>
#include "common/common_types.h"
#include "common/concepts.h"
#include "common/swap.h"
#include "core/hle/ipc.h"
#include "core/hle/kernel/object.h"
@@ -199,17 +200,18 @@ public:
* @param container The container to write the data of into a buffer.
* @param buffer_index The buffer in particular to write to.
*/
template <typename ContiguousContainer,
typename = std::enable_if_t<!std::is_pointer_v<ContiguousContainer>>>
std::size_t WriteBuffer(const ContiguousContainer& container,
std::size_t buffer_index = 0) const {
using ContiguousType = typename ContiguousContainer::value_type;
static_assert(std::is_trivially_copyable_v<ContiguousType>,
"Container to WriteBuffer must contain trivially copyable objects");
return WriteBuffer(std::data(container), std::size(container) * sizeof(ContiguousType),
buffer_index);
template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>>
std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const {
if constexpr (IsSTLContainer<T>) {
using ContiguousType = typename T::value_type;
static_assert(std::is_trivially_copyable_v<ContiguousType>,
"Container to WriteBuffer must contain trivially copyable objects");
return WriteBuffer(std::data(data), std::size(data) * sizeof(ContiguousType),
buffer_index);
} else {
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
return WriteBuffer(&data, sizeof(T), buffer_index);
}
}
/// Helper function to get the size of the input buffer

View File

@@ -286,9 +286,7 @@ protected:
ProfileBase profile_base{};
ProfileData data{};
if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) {
std::array<u8, sizeof(ProfileData)> raw_data;
std::memcpy(raw_data.data(), &data, sizeof(ProfileData));
ctx.WriteBuffer(raw_data);
ctx.WriteBuffer(data);
IPC::ResponseBuilder rb{ctx, 16};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(profile_base);
@@ -333,7 +331,7 @@ protected:
std::vector<u8> buffer(size);
image.ReadBytes(buffer.data(), buffer.size());
ctx.WriteBuffer(buffer.data(), buffer.size());
ctx.WriteBuffer(buffer);
rb.Push<u32>(size);
}

View File

@@ -92,7 +92,7 @@ private:
if (performance) {
rb.Push<u64>(*performance);
}
ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
ctx.WriteBuffer(samples);
}
bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector<u8>& input,

View File

@@ -112,7 +112,7 @@ private:
void GetImpl(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_BCAT, "called");
ctx.WriteBuffer(&impl, sizeof(DeliveryCacheProgressImpl));
ctx.WriteBuffer(impl);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);

View File

@@ -160,7 +160,7 @@ private:
return;
}
ctx.WriteBuffer(key.data(), key.size());
ctx.WriteBuffer(key);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);

View File

@@ -127,7 +127,7 @@ private:
const u32 array_size = rp.Pop<u32>();
LOG_DEBUG(Service_NFP, "called, array_size={}", array_size);
ctx.WriteBuffer(&device_handle, sizeof(device_handle));
ctx.WriteBuffer(device_handle);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
@@ -220,7 +220,7 @@ private:
tag_info.protocol = 1; // TODO(ogniK): Figure out actual values
tag_info.tag_type = 2;
ctx.WriteBuffer(&tag_info, sizeof(TagInfo));
ctx.WriteBuffer(tag_info);
rb.Push(RESULT_SUCCESS);
}
@@ -237,7 +237,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
auto amiibo = nfp_interface.GetAmiiboBuffer();
ctx.WriteBuffer(&amiibo.model_info, sizeof(amiibo.model_info));
ctx.WriteBuffer(amiibo.model_info);
rb.Push(RESULT_SUCCESS);
}
@@ -283,7 +283,7 @@ private:
CommonInfo common_info{};
common_info.application_area_size = 0;
ctx.WriteBuffer(&common_info, sizeof(CommonInfo));
ctx.WriteBuffer(common_info);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);

View File

@@ -106,7 +106,7 @@ void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
ctx.WriteBuffer(&layout, sizeof(KeyboardLayout));
ctx.WriteBuffer(layout);
}
} // Anonymous namespace

View File

@@ -290,7 +290,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
ctx.WriteBuffer(clock_snapshot);
}
void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) {
@@ -313,7 +313,7 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
ctx.WriteBuffer(clock_snapshot);
}
void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(

View File

@@ -142,7 +142,7 @@ void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(1); // Number of times we're returning
ctx.WriteBuffer(&posix_time, sizeof(s64));
ctx.WriteBuffer(posix_time);
}
void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
@@ -164,7 +164,7 @@ void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(1); // Number of times we're returning
ctx.WriteBuffer(&posix_time, sizeof(s64));
ctx.WriteBuffer(posix_time);
}
} // namespace Service::Time