Removed noexcept as I don't feel I sufficiently understand the implications of its use. Modified Store with a CRTP tag to prevent base clase pointer misuse.

This commit is contained in:
2022-11-20 11:26:34 +11:00
parent e3c1389791
commit e7c5ae0beb
5 changed files with 74 additions and 46 deletions

26
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,26 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "msbuild",
"args": [
// Ask msbuild to generate full paths for file names.
"/property:GenerateFullPaths=true",
"/t:build",
// Do not generate summary otherwise it leads to duplicate errors in Problems panel
"/consoleloggerparameters:NoSummary"
],
"group": "build",
"presentation": {
// Reveal the output only if unrecognized errors occur.
"reveal": "silent"
},
// Use the standard MS compiler pattern to detect errors, warnings and infos
"problemMatcher": "$msCompile"
}
]
}

View File

@@ -9,42 +9,42 @@ Node read_unknown_record(std::istream &in);
return read_header_impl<directly_readable>(in); return read_header_impl<directly_readable>(in);
} }
[[nodiscard]] std::size_t data_size(const RecordHeader& header) noexcept [[nodiscard]] std::size_t data_size(const RecordHeader& header)
{ {
return header.size; return header.size;
} }
[[nodiscard]] std::size_t data_size(const GroupHeader& header) noexcept [[nodiscard]] std::size_t data_size(const GroupHeader& header)
{ {
return header.size - header_size; return header.size - header_size;
} }
[[nodiscard]] std::streamsize data_ssize(const RecordHeader& header) noexcept [[nodiscard]] std::streamsize data_ssize(const RecordHeader& header)
{ {
return static_cast<std::streamsize>(data_size(header)); return static_cast<std::streamsize>(data_size(header));
} }
[[nodiscard]] std::streamsize data_ssize(const GroupHeader& header) noexcept [[nodiscard]] std::streamsize data_ssize(const GroupHeader& header)
{ {
return static_cast<std::streamsize>(data_size(header)); return static_cast<std::streamsize>(data_size(header));
} }
[[nodiscard]] std::size_t node_size(const RecordNode& node) noexcept [[nodiscard]] std::size_t node_size(const RecordNode& node)
{ {
return node.header.size + header_size; return node.header.size + header_size;
} }
[[nodiscard]] std::size_t node_size(const GroupNode& node) noexcept [[nodiscard]] std::size_t node_size(const GroupNode& node)
{ {
return node.header.size; return node.header.size;
} }
[[nodiscard]] std::streamsize node_ssize(const RecordNode& node) noexcept [[nodiscard]] std::streamsize node_ssize(const RecordNode& node)
{ {
return static_cast<std::streamsize>(node_size(node)); return static_cast<std::streamsize>(node_size(node));
} }
[[nodiscard]] std::streamsize node_ssize(const GroupNode& node) noexcept [[nodiscard]] std::streamsize node_ssize(const GroupNode& node)
{ {
return static_cast<std::streamsize>(node_size(node)); return static_cast<std::streamsize>(node_size(node));
} }

View File

@@ -58,21 +58,21 @@ enum class RecordType {
// Aggregate types // Aggregate types
// //
struct FourCC : utility::Store<uint32_t> { }; struct FourCC : utility::Store<FourCC, uint32_t> { };
struct FormID : utility::Store<uint32_t> { }; struct FormID : utility::Store<FormID, uint32_t> { };
struct Timestamp : utility::Store<uint16_t> { }; struct Timestamp : utility::Store<Timestamp, uint16_t> { };
struct VCInfo : utility::Store<uint16_t> { }; struct VCInfo : utility::Store<VCInfo, uint16_t> { };
struct Flag { struct Flag {
RecordType type; RecordType type;
unsigned bit; unsigned bit;
friend constexpr auto operator<=>(const Flag &, const Flag &) noexcept = default; friend constexpr auto operator<=>(const Flag &, const Flag &) = default;
}; };
struct RefrFlag { struct RefrFlag {
RecordType refr_type; RecordType refr_type;
unsigned bit; unsigned bit;
friend constexpr auto operator<=>(const RefrFlag &, const RefrFlag &) noexcept = default; friend constexpr auto operator<=>(const RefrFlag &, const RefrFlag &) = default;
}; };
struct UnknownHeader { struct UnknownHeader {
@@ -85,14 +85,14 @@ struct GroupHeader {
int16_t y, x; int16_t y, x;
}; };
struct TopType : utility::Store<FourCC> { }; struct TopType : utility::Store<TopType, FourCC> { };
struct ParentWorld : utility::Store<FormID> { }; struct ParentWorld : utility::Store<ParentWorld, FormID> { };
struct BlockNumber : utility::Store<int32_t> { }; struct BlockNumber : utility::Store<BlockNumber, int32_t> { };
struct SubBlockNumber : utility::Store<int32_t> { }; struct SubBlockNumber : utility::Store<SubBlockNumber, int32_t> { };
struct BlockCoord : utility::Store<Coord> { }; struct BlockCoord : utility::Store<BlockCoord, Coord> { };
struct SubBlockCoord : utility::Store<Coord> { }; struct SubBlockCoord : utility::Store<SubBlockCoord, Coord> { };
struct ParentCell : utility::Store<FormID> { }; struct ParentCell : utility::Store<ParentCell, FormID> { };
struct ParentDialogue : utility::Store<FormID> { }; struct ParentDialogue : utility::Store<ParentDialogue, FormID> { };
union GroupLabel { union GroupLabel {
TopType top_type; TopType top_type;
@@ -115,8 +115,8 @@ struct GroupHeader {
}; };
struct RecordHeader { struct RecordHeader {
struct Flags : utility::Store<uint32_t> { }; struct Flags : utility::Store<Flags, uint32_t> { };
struct Version : utility::Store<uint16_t> { }; struct Version : utility::Store<Version, uint16_t> { };
FourCC type; FourCC type;
uint32_t size; uint32_t size;
@@ -153,18 +153,18 @@ struct RecordNode {
// Free functions // Free functions
// //
[[nodiscard]] std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept; [[nodiscard]] std::optional<std::string_view> group_type_to_name(GroupType group_type);
[[nodiscard]] std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept; [[nodiscard]] std::optional<FourCC> record_type_to_fourcc(RecordType record_type);
[[nodiscard]] std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept; [[nodiscard]] std::optional<RecordType> fourcc_to_record_type(FourCC fourcc);
[[nodiscard]] std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept; [[nodiscard]] std::optional<std::string_view> record_type_to_name(RecordType record_type);
[[nodiscard]] std::optional<std::string_view> flag_to_description(Flag flag) noexcept; [[nodiscard]] std::optional<std::string_view> flag_to_description(Flag flag);
[[nodiscard]] std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept; [[nodiscard]] std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag);
[[nodiscard]] Header read_header(std::istream &in); [[nodiscard]] Header read_header(std::istream &in);
[[nodiscard]] RootNode read_esx(std::istream &in, std::size_t file_size); [[nodiscard]] RootNode read_esx(std::istream &in, std::size_t file_size);
// Convert a compatible C string to a FourCC (e.g. "LITR") // Convert a compatible C string to a FourCC (e.g. "LITR")
static consteval FourCC fourcc_from_cstr(const char(&a)[5]) noexcept static consteval FourCC fourcc_from_cstr(const char(&a)[5])
{ {
char temp[4] = { a[0], a[1], a[2], a[3] }; char temp[4] = { a[0], a[1], a[2], a[3] };
return std::bit_cast<FourCC, char[4]>(temp); return std::bit_cast<FourCC, char[4]>(temp);

View File

@@ -658,31 +658,31 @@ static constexpr auto flag_description_map = utility::map_to_soa(flag_descriptio
static constexpr auto refr_flag_description_map_std = utility::array_builtin_to_std(refr_flag_description_map_builtin); static constexpr auto refr_flag_description_map_std = utility::array_builtin_to_std(refr_flag_description_map_builtin);
static constexpr auto refr_flag_description_map = utility::map_to_soa(refr_flag_description_map_std); static constexpr auto refr_flag_description_map = utility::map_to_soa(refr_flag_description_map_std);
[[nodiscard]] std::optional<std::string_view> esxr::group_type_to_name(GroupType group_type) noexcept [[nodiscard]] std::optional<std::string_view> esxr::group_type_to_name(GroupType group_type)
{ {
return utility::soa_first_to_second(group_type_name_map, group_type); return utility::soa_first_to_second(group_type_name_map, group_type);
} }
[[nodiscard]] std::optional<FourCC> esxr::record_type_to_fourcc(RecordType record_type) noexcept [[nodiscard]] std::optional<FourCC> esxr::record_type_to_fourcc(RecordType record_type)
{ {
return utility::soa_first_to_second(record_type_fourcc_map, record_type); return utility::soa_first_to_second(record_type_fourcc_map, record_type);
} }
[[nodiscard]] std::optional<RecordType> esxr::fourcc_to_record_type(FourCC fourcc) noexcept [[nodiscard]] std::optional<RecordType> esxr::fourcc_to_record_type(FourCC fourcc)
{ {
return utility::soa_second_to_first(record_type_fourcc_map, fourcc); return utility::soa_second_to_first(record_type_fourcc_map, fourcc);
} }
[[nodiscard]] std::optional<std::string_view> esxr::record_type_to_name(RecordType record_type) noexcept [[nodiscard]] std::optional<std::string_view> esxr::record_type_to_name(RecordType record_type)
{ {
return utility::soa_first_to_second(record_type_name_map, record_type); return utility::soa_first_to_second(record_type_name_map, record_type);
} }
[[nodiscard]] std::optional<std::string_view> esxr::flag_to_description(Flag flag) noexcept [[nodiscard]] std::optional<std::string_view> esxr::flag_to_description(Flag flag)
{ {
return utility::soa_first_to_second(flag_description_map, flag); return utility::soa_first_to_second(flag_description_map, flag);
} }
[[nodiscard]] std::optional<std::string_view> esxr::refr_flag_to_description(RefrFlag refr_flag) noexcept [[nodiscard]] std::optional<std::string_view> esxr::refr_flag_to_description(RefrFlag refr_flag)
{ {
return utility::soa_first_to_second(refr_flag_description_map, refr_flag); return utility::soa_first_to_second(refr_flag_description_map, refr_flag);
} }

View File

@@ -16,17 +16,19 @@ T::size_type index_of(const T &container, typename T::const_iterator &iter)
} }
// This is a base class for a generic store for some value that can be represented by // This is a base class for a generic store for some value that can be represented by
// type T but should not be type checked as type T, but rather some more constrained class. // type Type but should not be type checked as type Type, but rather some more constrained class.
template <class T> // CRTP is the derived class, and is used as a tag to prevent having Store as a base class to
// multiple derived types.
template <typename CRTP, typename Type>
struct Store { struct Store {
static_assert(std::is_trivial_v<T>); static_assert(std::is_trivial_v<Type>);
T value; Type value;
friend constexpr auto operator<=>(const Store &, const Store &) noexcept = default; friend constexpr auto operator<=>(const Store &, const Store &) = default;
}; };
// Convert a builtin array to a std::array // Convert a builtin array to a std::array
template <typename T, std::size_t N> template <typename T, std::size_t N>
constexpr std::array<T, N> array_builtin_to_std(const T(&builtin)[N]) noexcept constexpr std::array<T, N> array_builtin_to_std(const T(&builtin)[N])
{ {
std::array<T, N> array; std::array<T, N> array;
std::copy(std::cbegin(builtin), std::cend(builtin), array.begin()); std::copy(std::cbegin(builtin), std::cend(builtin), array.begin());
@@ -35,7 +37,7 @@ constexpr std::array<T, N> array_builtin_to_std(const T(&builtin)[N]) noexcept
// Convert a std::array of std::pairs to a std::pair of std::arrays // Convert a std::array of std::pairs to a std::pair of std::arrays
template <typename First, typename Second, std::size_t N> template <typename First, typename Second, std::size_t N>
constexpr std::pair<std::array<First, N>, std::array<Second, N>> map_to_soa(std::array<std::pair<First, Second>, N> map) noexcept constexpr std::pair<std::array<First, N>, std::array<Second, N>> map_to_soa(std::array<std::pair<First, Second>, N> map)
{ {
std::array<First, N> first; std::array<First, N> first;
std::array<Second, N> second; std::array<Second, N> second;
@@ -47,7 +49,7 @@ constexpr std::pair<std::array<First, N>, std::array<Second, N>> map_to_soa(std:
} }
template <typename First, typename Second, std::size_t N> template <typename First, typename Second, std::size_t N>
constexpr std::optional<Second> soa_first_to_second(const std::pair<std::array<First, N>, std::array<Second, N>> &soa, const First &first) noexcept constexpr std::optional<Second> soa_first_to_second(const std::pair<std::array<First, N>, std::array<Second, N>> &soa, const First &first)
{ {
auto lhs = std::find(soa.first.cbegin(), soa.first.cend(), first); auto lhs = std::find(soa.first.cbegin(), soa.first.cend(), first);
if (lhs == soa.first.cend()) if (lhs == soa.first.cend())
@@ -57,7 +59,7 @@ constexpr std::optional<Second> soa_first_to_second(const std::pair<std::array<F
} }
template <typename First, typename Second, std::size_t N> template <typename First, typename Second, std::size_t N>
constexpr std::optional<First> soa_second_to_first(const std::pair<std::array<First, N>, std::array<Second, N>> &soa, const Second &second) noexcept constexpr std::optional<First> soa_second_to_first(const std::pair<std::array<First, N>, std::array<Second, N>> &soa, const Second &second)
{ {
auto lhs = std::find(soa.second.cbegin(), soa.second.cend(), second); auto lhs = std::find(soa.second.cbegin(), soa.second.cend(), second);
if (lhs == soa.second.cend()) if (lhs == soa.second.cend())