diff options
Diffstat (limited to 'serialize')
-rw-r--r-- | serialize/anim.cpp | 5 | ||||
-rw-r--r-- | serialize/atlas-type.hpp | 2 | ||||
-rw-r--r-- | serialize/old-savegame.cpp | 27 | ||||
-rw-r--r-- | serialize/savegame.cpp | 36 | ||||
-rw-r--r-- | serialize/scenery.cpp | 6 |
5 files changed, 42 insertions, 34 deletions
diff --git a/serialize/anim.cpp b/serialize/anim.cpp index cd1f5e5c..5e2ed388 100644 --- a/serialize/anim.cpp +++ b/serialize/anim.cpp @@ -133,10 +133,11 @@ namespace nlohmann { void adl_serializer<floormat::anim_scale>::to_json(json& j, const anim_scale val) { + if (val.type >= anim_scale_type::COUNT) [[unlikely]] + fm_throw("invalid anim_scale_type '{}"_cf, (unsigned)val.type); switch (val.type) { - default: - fm_throw("invalid anim_scale_type '{}"_cf, (unsigned)val.type); + case anim_scale_type::COUNT: std::unreachable(); case anim_scale_type::invalid: fm_throw("anim_scale is invalid"_cf); case anim_scale_type::fixed: diff --git a/serialize/atlas-type.hpp b/serialize/atlas-type.hpp index 1d3ea5aa..ef8bf440 100644 --- a/serialize/atlas-type.hpp +++ b/serialize/atlas-type.hpp @@ -3,6 +3,6 @@ namespace floormat::Serialize { enum class atlas_type : uint8_t { - none, ground, wall, anim, vobj, + none, ground, wall, anim, vobj, COUNT, }; } // namespace floormat::Serialize diff --git a/serialize/old-savegame.cpp b/serialize/old-savegame.cpp index 111d29f3..46b83590 100644 --- a/serialize/old-savegame.cpp +++ b/serialize/old-savegame.cpp @@ -309,11 +309,11 @@ void reader_state::read_chunks(reader_t& s) tile_ref t = c[i]; using uchar = uint8_t; const auto make_atlas = [&]<typename T>() -> image_proto_<T> { - atlasid id; + atlasid atlas_id; if (PROTO < 8) [[unlikely]] - id = flags & meta_short_atlasid_ ? atlasid{s.read<uchar>()} : s.read<atlasid>(); + atlas_id = flags & meta_short_atlasid_ ? atlasid{s.read<uchar>()} : s.read<atlasid>(); else - id << s; + atlas_id << s; uint8_t v; if (PROTO >= 2) [[likely]] v << s; @@ -321,20 +321,24 @@ void reader_state::read_chunks(reader_t& s) v = flags & meta_short_variant_ ? s.read<uint8_t>() : uint8_t(s.read<uint16_t>()); - auto name = lookup_atlas(id); + auto name = lookup_atlas(atlas_id); if constexpr(std::is_same_v<ground_atlas, T>) { auto atlas = loader.ground_atlas(name, asset_policy); fm_soft_assert(v < atlas->num_tiles()); return { atlas, v }; } - else if (std::is_same_v<wall_atlas, T>) + else if constexpr(std::is_same_v<wall_atlas, T>) { auto atlas = loader.wall_atlas(name, asset_policy); return { atlas, v }; } else + { + static_assert(sizeof T{} != (size_t)-1); + static_assert(sizeof T{} == (size_t)-1); std::unreachable(); + } }; SET_CHUNK_SIZE(); //t.passability() = pass_mode(flags & pass_mask); @@ -364,7 +368,6 @@ void reader_state::read_chunks(reader_t& s) oid << s; fm_soft_assert((oid & lowbits<collision_data_BITS, object_id>) == oid); type = object_type(s.read<std::underlying_type_t<object_type>>()); - fm_soft_assert(type < object_type::COUNT); } else { @@ -373,6 +376,9 @@ void reader_state::read_chunks(reader_t& s) fm_soft_assert(oid != 0); type = object_type(_id >> 61); } + if (type >= object_type::COUNT || type == object_type::none) [[unlikely]] + fm_throw("invalid_object_type '{}'"_cf, (int)type); + const auto local = local_coords{s.read<uint8_t>()}; Vector2b offset; @@ -388,6 +394,7 @@ void reader_state::read_chunks(reader_t& s) s >> e.bbox_size[1]; }; SET_CHUNK_SIZE(); + switch (type) { case object_type::critter: { @@ -409,8 +416,8 @@ void reader_state::read_chunks(reader_t& s) if (PROTO >= 9) [[likely]] { - uint32_t id; id << s; - auto name = lookup_string(id); + uint32_t string_id; string_id << s; + auto name = lookup_string(string_id); fm_soft_assert(name.size() < critter_name_max); proto.name = name; } @@ -527,8 +534,8 @@ void reader_state::read_chunks(reader_t& s) (void)L; break; } - default: - fm_throw("invalid_object_type '{}'"_cf, (int)type); + case object_type::none: + case object_type::COUNT: std::unreachable(); } } diff --git a/serialize/savegame.cpp b/serialize/savegame.cpp index 912bb2c5..5a77db0f 100644 --- a/serialize/savegame.cpp +++ b/serialize/savegame.cpp @@ -150,9 +150,12 @@ struct visitor_ template<typename F> void visit_object_internal(object& obj, F&& f, object_id id, object_type type, chunk_coords_ ch) { - non_const(obj.id) = id; + if (type >= object_type::COUNT || type == object_type::none) [[unlikely]] + fm_throw("invalid object type {}"_cf, (int)type); switch (type) { + case object_type::none: + case object_type::COUNT: std::unreachable(); case object_type::light: static_cast<Derived&>(*this).visit(non_const(obj.atlas), atlas_type::vobj, f); break; @@ -160,19 +163,15 @@ struct visitor_ case object_type::critter: static_cast<Derived&>(*this).visit(non_const(obj.atlas), atlas_type::anim, f); break; - case object_type::none: - case object_type::COUNT: - default: - break; + } - if (!obj.atlas) - fm_throw("invalid object type {}"_cf, (int)type); - //do_visit(*obj.c, f); + fm_debug_assert(obj.atlas); { auto pt = obj.coord.local(); do_visit(pt, f); non_const(obj.coord) = {ch, pt}; } + non_const(obj.id) = id; do_visit_nonconst(obj.offset, f); do_visit_nonconst(obj.bbox_offset, f); do_visit_nonconst(obj.bbox_size, f); @@ -190,14 +189,10 @@ struct visitor_ switch (type) { + default: break; case object_type::critter: do_visit(static_cast<critter&>(obj), f); return; case object_type::scenery: do_visit(static_cast<scenery&>(obj), f); return; case object_type::light: do_visit(static_cast<light&>(obj), f); return; - case object_type::COUNT: - case object_type::none: - break; - default: - fm_abort("invalid object type '%d'", (int)type); } } @@ -455,16 +450,19 @@ struct writer final : visitor_<writer> StringView name; + if (type >= atlas_type::COUNT || type == atlas_type::none) [[unlikely]] + fm_abort("invalid atlas type '%d'", (int)type); switch (type) { - case atlas_type::ground: name = static_cast<const ground_atlas*>(atlas)->name(); break; - case atlas_type::wall: name = static_cast<const wall_atlas*>(atlas)->name(); break; + case atlas_type::ground: + name = static_cast<const ground_atlas*>(atlas)->name(); break; + case atlas_type::wall: + name = static_cast<const wall_atlas*>(atlas)->name(); break; case atlas_type::vobj: case atlas_type::anim: - name = static_cast<const anim_atlas*>(atlas)->name(); - break; - default: - fm_abort("invalid atlas type '%d'", (int)type); + name = static_cast<const anim_atlas*>(atlas)->name(); break; + case atlas_type::none: + case atlas_type::COUNT: std::unreachable(); } do_visit(intern_string(name), f); } diff --git a/serialize/scenery.cpp b/serialize/scenery.cpp index 080d0f71..5950ddf3 100644 --- a/serialize/scenery.cpp +++ b/serialize/scenery.cpp @@ -151,10 +151,12 @@ void adl_serializer<scenery_proto>::from_json(const json& j, scenery_proto& f) fm_soft_assert(bbox_offset == Vector2i(Vector2b(bbox_offset))); fm_soft_assert(bbox_size == Vector2ui(Vector2ub(bbox_size))); + + fm_assert(type < scenery_type::COUNT); switch (type) { - default: - fm_throw("unhandled scenery type '{}'"_cf, (unsigned)type); + case scenery_type::none: + case scenery_type::COUNT: std::unreachable(); case scenery_type::generic: { constexpr generic_scenery_proto G; auto s = G; |