From 3d5de92058296f4b6bbc7986b29a3518354522ea Mon Sep 17 00:00:00 2001 From: Kp Date: Mon, 31 Oct 2022 00:51:32 +0000 Subject: [PATCH] Fix OS X clang build OS X still uses clang-14, which lacks sufficient std::ranges support for recent Rebirth changes. - Rewrite uses of std::ranges::SYMBOL to ranges::SYMBOL - Add a stub header that, on gcc, provides for each SYMBOL a statement `using std::ranges::SYMBOL;`, to delegate back to the standard library implementation. - On clang, define a minimal implementation of the required symbols, without constraint enforcement. Compile-testing with gcc will catch constraint violations. Once OS X clang ships a standard library with the required features, this stub header will be removed and the uses changed back to their full names. --- SConstruct | 58 ++++++++++++---- common/arch/sdl/key.cpp | 3 +- common/arch/sdl/rbaudio.cpp | 2 +- common/include/partial_range.h | 1 + common/include/physfs_list.h | 5 +- common/include/physfsx.h | 6 +- common/main/backports-ranges.h | 117 +++++++++++++++++++++++++++++++++ common/main/d_enumerate.h | 1 - common/main/multi.h | 4 +- common/ui/keypad.cpp | 4 +- d2x-rebirth/main/escort.cpp | 4 +- similar/editor/group.cpp | 2 +- similar/main/console.cpp | 2 +- similar/main/digiobj.cpp | 2 +- similar/main/dumpmine.cpp | 2 +- similar/main/fireball.cpp | 2 +- similar/main/fuelcen.cpp | 2 +- similar/main/game.cpp | 2 +- similar/main/gamecntl.cpp | 2 +- similar/main/gamesave.cpp | 2 +- similar/main/menu.cpp | 20 +++--- similar/main/mission.cpp | 8 +-- similar/main/morph.cpp | 2 +- similar/main/multi.cpp | 4 +- similar/main/net_udp.cpp | 6 +- similar/main/newmenu.cpp | 4 +- similar/main/playsave.cpp | 4 +- similar/main/render.cpp | 4 +- similar/main/scores.cpp | 2 +- similar/main/wall.cpp | 10 +-- similar/misc/physfsx.cpp | 6 +- 31 files changed, 222 insertions(+), 71 deletions(-) create mode 100644 common/main/backports-ranges.h diff --git a/SConstruct b/SConstruct index 09062bc18..51c0fcd11 100644 --- a/SConstruct +++ b/SConstruct @@ -2682,25 +2682,59 @@ constexpr literal_as_type operator""_literal_as_type(); self.successful_flags['CXXFLAGS'].append('-Wno-gnu-string-literal-operator-template') @_custom_test - def check_have_std_ranges(self,context,_successflags={'CPPDEFINES' : ['_LIBCPP_ENABLE_EXPERIMENTAL']}): + def check_have_std_ranges(self,context,_testflags={'CPPDEFINES' : ['_LIBCPP_ENABLE_EXPERIMENTAL']}): text = ''' -#include +#include "backports-ranges.h" + +struct test_borrowed_range {}; + +template <> +constexpr bool std::ranges::enable_borrowed_range = true; + +template +requires(std::ranges::range) +static void requires_range(R &) {} + +template +requires(std::ranges::borrowed_range) +static void requires_borrowed_range(R &&) {} ''' main = ''' int a[3]{1, 2, 3}; - return std::ranges::find(a, argc) == a; + int b[2]{4, 5}; + const ranges::subrange c(b); + const ranges::subrange c2(b); + (void)c2; + const auto m = [](int i) { return i * 2; }; + (void)(ranges::find(a, argc) == a); + (void)(ranges::find(a, argc, m) == a); + (void)(ranges::find(std::ranges::begin(b), std::ranges::end(b), argc) == a); + (void)(ranges::find(std::ranges::begin(b), std::ranges::end(b), argc, m) == a); + const auto predicate = [](int i) { return i == 3; }; + (void)(ranges::find_if(b, predicate) == a); + (void)(ranges::find_if(std::ranges::begin(b), std::ranges::end(b), predicate) == a); + requires_range(a); + requires_borrowed_range(a); + return 0; ''' if self.Compile(context, text=text, main=main, msg='whether C++ compiler provides std::ranges by default'): return - # As a special case, put this define in the command-line instead of - # allowing it to be moved to `dxxsconf.h`. This define must be in - # effect before the C++ compiler sees a `#include` of any system - # headers that conditionally define experimental functionality. - # Placing the define on the command line ensures that. If the - # preprocessor definition were in `dxxsconf.h`, then some files might - # include the system header before including the definition. - if self.Compile(context, text=text, main=main, msg='whether C++ compiler provides std::ranges with -D_LIBCPP_ENABLE_EXPERIMENTAL', testflags=_successflags): - self.successful_flags['CPPDEFINES'].extend(*_successflags.items()) + # std::ranges is a C++20 feature. + # gcc first shipped std::ranges in gcc-10.1 [1], which was released on + # 2020-05-07 [2]. + # clang shipped incomplete std::ranges behind a preprocessor guard in + # clang-14 [3], which was released on 2022-03-25 [4]. + # + # As of this writing, Apple clang is still clang-14, and so does not + # support all needed std::ranges features, even with the preprocessor + # guard defined. Try to work around this by bundling an implementation + # sufficient to cover Rebirth's needs. + # + # [1]: https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#table.cxx20_features + # [2]: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=6e6e3f144a33ae504149dc992453b4f6dea12fdb + # [3]: https://libcxx.llvm.org/Status/Ranges.html + # [4]: https://discourse.llvm.org/t/llvm-14-0-0-release/61224 + if self.Compile(context, text=text, main=main, msg='whether C++ compiler can use bundled ranges support with -D_LIBCPP_ENABLE_EXPERIMENTAL', testflags=_testflags): return raise SCons.Errors.StopError("C++ compiler does not support std::ranges.") diff --git a/common/arch/sdl/key.cpp b/common/arch/sdl/key.cpp index 51166eb0c..b78ac343f 100644 --- a/common/arch/sdl/key.cpp +++ b/common/arch/sdl/key.cpp @@ -33,6 +33,7 @@ #include "dsx-ns.h" #include "compiler-range_for.h" #include +#include "backports-ranges.h" namespace dcx { @@ -512,7 +513,7 @@ window_event_result key_handler(const SDL_KeyboardEvent *const kevent) //===================================================== const auto re = key_properties.rend(); - const auto &&fi = std::ranges::find(key_properties.rbegin(), re, event_keysym, &key_props::sym); + const auto &&fi = ranges::find(key_properties.rbegin(), re, event_keysym, &key_props::sym); if (fi == re) return window_event_result::ignored; unsigned keycode = std::distance(key_properties.begin(), std::next(fi).base()); diff --git a/common/arch/sdl/rbaudio.cpp b/common/arch/sdl/rbaudio.cpp index a4bf3af13..b2a03e56a 100644 --- a/common/arch/sdl/rbaudio.cpp +++ b/common/arch/sdl/rbaudio.cpp @@ -89,7 +89,7 @@ void RBAInit() if (s_cd && CD_INDRIVE(SDL_CDStatus(s_cd))) { const auto &&r = partial_const_range(s_cd->track, static_cast(s_cd->numtracks)); - if (std::ranges::find(r, SDL_AUDIO_TRACK, &SDL_CDtrack::type) != r.end()) + if (ranges::find(r, SDL_AUDIO_TRACK, &SDL_CDtrack::type) != r.end()) { initialised = 1; RBAList(); diff --git a/common/include/partial_range.h b/common/include/partial_range.h index bfa0743b8..704e9beaa 100644 --- a/common/include/partial_range.h +++ b/common/include/partial_range.h @@ -14,6 +14,7 @@ #include "fwd-partial_range.h" #include #include "dxxsconf.h" +#include "backports-ranges.h" /* If no value was specified for DXX_PARTIAL_RANGE_MINIMIZE_ERROR_TYPE, * then define it to true for NDEBUG builds and false for debug builds. diff --git a/common/include/physfs_list.h b/common/include/physfs_list.h index 5ee518619..210c3ce58 100644 --- a/common/include/physfs_list.h +++ b/common/include/physfs_list.h @@ -19,6 +19,7 @@ typedef char file_extension_t[5]; #include "dsx-ns.h" #include "fwd-partial_range.h" #include +#include "backports-ranges.h" namespace dcx { @@ -79,11 +80,11 @@ typedef PHYSFSX_counted_list_template PHYSFSX_counted_list; [[nodiscard]] __attribute_nonnull() -PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, std::ranges::subrange exts); +PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, ranges::subrange exts); [[nodiscard]] __attribute_nonnull() -PHYSFSX_uncounted_list PHYSFSX_findabsoluteFiles(const char *path, const char *realpath, std::ranges::subrange exts); +PHYSFSX_uncounted_list PHYSFSX_findabsoluteFiles(const char *path, const char *realpath, ranges::subrange exts); } #endif diff --git a/common/include/physfsx.h b/common/include/physfsx.h index d5ed4d397..e0324756c 100644 --- a/common/include/physfsx.h +++ b/common/include/physfsx.h @@ -36,7 +36,6 @@ #include "vecmat.h" #include "byteutil.h" -#ifdef __cplusplus #include #include "u_mem.h" #include "pack.h" @@ -44,6 +43,7 @@ #include "fwd-partial_range.h" #include #include +#include "backports-ranges.h" #ifdef DXX_CONSTANT_TRUE #define _DXX_PHYSFS_CHECK_SIZE_CONSTANT(S,v) DXX_CONSTANT_TRUE((S) > (v)) @@ -424,7 +424,7 @@ typedef char file_extension_t[5]; [[nodiscard]] __attribute_nonnull() -int PHYSFSX_checkMatchingExtension(const char *filename, const std::ranges::subrange range); +int PHYSFSX_checkMatchingExtension(const char *filename, const ranges::subrange range); enum class physfs_search_path : int { @@ -502,5 +502,3 @@ RAIIPHYSFS_ComputedPathMount make_PHYSFSX_ComputedPathMount(const char *const na } #endif - -#endif diff --git a/common/main/backports-ranges.h b/common/main/backports-ranges.h new file mode 100644 index 000000000..d9964bbe3 --- /dev/null +++ b/common/main/backports-ranges.h @@ -0,0 +1,117 @@ +/* + * This file is part of the DXX-Rebirth project . + * It is copyright by its individual contributors, as recorded in the + * project's Git history. See COPYING.txt at the top level for license + * terms and a link to the Git history. + */ + +/* + * std::ranges is a C++20 feature. + * + * gcc-10.1 (released 2020-05-07) shipped std::ranges support. + * + * clang-14 (released 2022-03-25) lacks sufficient std::ranges support, and + * requires a preprocessor symbol to unlock the parts it provides. + * + * clang-15 (released 2022-09-06) defines sufficient std::ranges support, but + * is still incomplete, and still requires a preprocessor symbol to unlock + * them. + * + * clang-14 is currently standard on OS X. + * + * When Rebirth is built with clang, this header provides a minimal + * implementation to allow calling code to use those features, but does not + * attempt to provide the constraints that a standards-conforming + * implementation would provide. + * + * When Rebirth is built with gcc, this header provides `using` declarations to + * pull in the compiler's `std::ranges` implementation, which will include the + * standards-conforming constraints. + */ + +#pragma once +#include +#include + +namespace ranges { + +#ifdef __clang__ + +template +class subrange +{ + iterator b; + sentinel e; +public: + subrange(iterator b, sentinel e) : + b(b), e(e) + { + } + subrange(auto &r) : + b(std::ranges::begin(r)), e(std::ranges::end(r)) + { + } + iterator begin() const { return b; } + sentinel end() const { return e; } +}; + +subrange(auto &r) -> subrange; + +template +requires( + requires(IB b, V v) { + *b == v; + } +) +auto find(IB b, auto e, V v) +{ + for (; b != e; ++b) + if (*b == v) + break; + return b; +} + +auto find(auto b, auto e, auto v, auto project) +{ + for (; b != e; ++b) + if (std::invoke(project, *b) == v) + break; + return b; +} + +auto find(auto &r, auto v) +{ + return find(std::ranges::begin(r), std::ranges::end(r), v); +} + +template +requires( + requires(R &r, P p) { + std::invoke(p, *std::ranges::begin(r)); + } +) +auto find(R &r, auto v, P project) +{ + return find(std::ranges::begin(r), std::ranges::end(r), v, project); +} + +auto find_if(auto b, auto e, auto predicate) +{ + for (; b != e; ++b) + if (predicate(*b)) + break; + return b; +} + +auto find_if(auto &r, auto predicate) +{ + return find_if(std::ranges::begin(r), std::ranges::end(r), predicate); +} + +#else +using std::ranges::subrange; +using std::ranges::find; +using std::ranges::find_if; +#endif + +} diff --git a/common/main/d_enumerate.h b/common/main/d_enumerate.h index 915f237d2..895e257b8 100644 --- a/common/main/d_enumerate.h +++ b/common/main/d_enumerate.h @@ -10,7 +10,6 @@ #include "dxxsconf.h" #include "partial_range.h" #include "ephemeral_range.h" -#include #include #include diff --git a/common/main/multi.h b/common/main/multi.h index 4e10263b8..e68ade4e9 100644 --- a/common/main/multi.h +++ b/common/main/multi.h @@ -65,7 +65,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include #ifdef dsx -#include +#include "backports-ranges.h" #endif namespace dcx { @@ -526,7 +526,7 @@ void multi_disconnect_player(playernum_t); namespace dsx { void multi_initiate_save_game(); void multi_initiate_restore_game(); -void multi_execute_save_game(d_game_unique_state::save_slot slot, const d_game_unique_state::savegame_description &desc, std::ranges::subrange player_range); +void multi_execute_save_game(d_game_unique_state::save_slot slot, const d_game_unique_state::savegame_description &desc, ranges::subrange player_range); #if defined(DXX_BUILD_DESCENT_I) static inline void multi_send_got_flag (playernum_t) {} #elif defined(DXX_BUILD_DESCENT_II) diff --git a/common/ui/keypad.cpp b/common/ui/keypad.cpp index 06c7997df..04ad2eee9 100644 --- a/common/ui/keypad.cpp +++ b/common/ui/keypad.cpp @@ -75,7 +75,7 @@ static keypad_input_line_t::const_iterator find_fake_comma(keypad_input_line_t:: const auto is_fake_comma = [](const char c) { return !c || static_cast(c) == 179; }; - return std::ranges::find_if(i, e, is_fake_comma); + return ranges::find_if(i, e, is_fake_comma); } template @@ -84,7 +84,7 @@ static keypad_input_line_t::const_iterator set_row(keypad_input_line_t::const_it const auto oe = r.end(); auto ob = r.begin(); if (append) - ob = std::ranges::find(ob, oe, 0); + ob = ranges::find(ob, oe, 0); auto comma0 = find_fake_comma(i, e); if (comma0 == e) /* Start not found */ diff --git a/d2x-rebirth/main/escort.cpp b/d2x-rebirth/main/escort.cpp index bc6a51b40..a29498a2e 100644 --- a/d2x-rebirth/main/escort.cpp +++ b/d2x-rebirth/main/escort.cpp @@ -687,13 +687,13 @@ static std::pair exi return vcsegptr(s)->special == segment_special::fuelcen; }; const auto &&rb = partial_const_range(bfs_list, length); - const auto &&i = std::ranges::find_if(rb, predicate); + const auto &&i = ranges::find_if(rb, predicate); if (i != rb.end()) return {*i, d_unique_buddy_state::Escort_goal_reachability::reachable}; } { const auto &&rh = make_range(vcsegptridx); - const auto &&i = std::ranges::find(rh, segment_special::fuelcen, &shared_segment::special); + const auto &&i = ranges::find(rh, segment_special::fuelcen, &shared_segment::special); if (i != rh.end()) return {*i, d_unique_buddy_state::Escort_goal_reachability::unreachable}; } diff --git a/similar/editor/group.cpp b/similar/editor/group.cpp index d15b5f5e9..ef76e3fd4 100644 --- a/similar/editor/group.cpp +++ b/similar/editor/group.cpp @@ -564,7 +564,7 @@ static int med_copy_group(const unsigned delta_flag, const vmsegptridx_t base_se auto gb = GroupList[current_group].segments.begin(); auto ge = GroupList[current_group].segments.end(); auto gp = Groupsegp[current_group]; - const auto &&gi = std::ranges::find_if(gb, ge, [gp](const segnum_t segnum) { return vcsegptr(segnum) == gp; }); + const auto &&gi = ranges::find_if(gb, ge, [gp](const segnum_t segnum) { return vcsegptr(segnum) == gp; }); int gs_index = (gi == ge) ? 0 : std::distance(gb, gi); GroupList[new_current_group] = GroupList[current_group]; diff --git a/similar/main/console.cpp b/similar/main/console.cpp index d86873f13..bca98c15c 100644 --- a/similar/main/console.cpp +++ b/similar/main/console.cpp @@ -113,7 +113,7 @@ static void con_scrub_markup(const std::span buffer) { const auto b = buffer.begin(); const auto e = buffer.end(); - const auto &&i = std::ranges::find_if(b, e, [](const char c) { return c == CC_COLOR || c == CC_LSPACING || c == CC_UNDERLINE; }); + const auto &&i = ranges::find_if(b, e, [](const char c) { return c == CC_COLOR || c == CC_LSPACING || c == CC_UNDERLINE; }); if (i == e) return; auto p1 = i; diff --git a/similar/main/digiobj.cpp b/similar/main/digiobj.cpp index 710c1e9d5..1d07eecba 100644 --- a/similar/main/digiobj.cpp +++ b/similar/main/digiobj.cpp @@ -113,7 +113,7 @@ static void digi_kill_sound(sound_object &s) static std::pair find_sound_object_flags0(sound_objects_t &SoundObjects) { const auto eso = SoundObjects.end(); - const auto &&i = std::ranges::find(SoundObjects.begin(), eso, 0, &sound_object::flags); + const auto &&i = ranges::find(SoundObjects.begin(), eso, 0, &sound_object::flags); return {i, eso}; } diff --git a/similar/main/dumpmine.cpp b/similar/main/dumpmine.cpp index be54b4b03..f22c9e8e2 100644 --- a/similar/main/dumpmine.cpp +++ b/similar/main/dumpmine.cpp @@ -616,7 +616,7 @@ static void write_trigger_text(PHYSFS_File *my_file) // Find which wall this trigger is connected to. const auto &&we = vcwallptr.end(); - const auto &&wi = std::ranges::find(vcwallptr.begin(), we, i, &wall::trigger); + const auto &&wi = ranges::find(vcwallptr.begin(), we, i, &wall::trigger); if (wi == we) err_printf(my_file, "Error: Trigger %i is not connected to any wall, so it can never be triggered.", underlying_value(i)); else diff --git a/similar/main/fireball.cpp b/similar/main/fireball.cpp index ae61f9a71..a28303bdb 100644 --- a/similar/main/fireball.cpp +++ b/similar/main/fireball.cpp @@ -789,7 +789,7 @@ static vmsegptridx_t choose_drop_segment(fvmsegptridx &vmsegptridx, fvcvertptr & std::optional fallback_drop; for (const unsigned candidate_depth : xrange(std::uniform_int_distribution(net_drop_max_depth_lower + 0u, net_drop_max_depth_upper + 0u)(mrd), net_drop_min_depth, xrange_descending())) { - for (const auto pnum : std::ranges::subrange(candidate_drop_players.begin(), end_drop_players)) + for (const auto pnum : ranges::subrange(candidate_drop_players.begin(), end_drop_players)) { auto &plr = *vcplayerptr(pnum); auto &plrobj = *vcobjptr(plr.objnum); diff --git a/similar/main/fuelcen.cpp b/similar/main/fuelcen.cpp index 3901ba7fe..ad0158803 100644 --- a/similar/main/fuelcen.cpp +++ b/similar/main/fuelcen.cpp @@ -667,7 +667,7 @@ void init_all_matcens(void) station.Enabled = 0; station.Disable_time = 0; // Make sure this fuelcen is pointed at by a matcen. - if (std::ranges::find(robot_range, i, &matcen_info::fuelcen_num) == robot_range.end()) + if (ranges::find(robot_range, i, &matcen_info::fuelcen_num) == robot_range.end()) { station.Lives = 0; LevelError("Station %i has type robotmaker, but no robotmaker uses it; ignoring.", underlying_value(i)); diff --git a/similar/main/game.cpp b/similar/main/game.cpp index cd2dc5890..71c007b75 100644 --- a/similar/main/game.cpp +++ b/similar/main/game.cpp @@ -2269,7 +2269,7 @@ static std::pair items) : + briefing_menu(grs_canvas &canvas, const ranges::subrange items) : passive_newmenu(menu_title{nullptr}, menu_subtitle{"Briefing to play?"}, menu_filename{nullptr}, tiny_mode_flag::normal, tab_processing_flag::ignore, adjusted_citem::create(items, 0), canvas) { } diff --git a/similar/main/gamesave.cpp b/similar/main/gamesave.cpp index 7c837d4cf..364db7579 100644 --- a/similar/main/gamesave.cpp +++ b/similar/main/gamesave.cpp @@ -1198,7 +1198,7 @@ static int load_game_data( { const auto i = (*iter).get_unchecked_index(); // Find which wall this trigger is connected to. - const auto &&w = std::ranges::find(wr, i, &wall::trigger); + const auto &&w = ranges::find(wr, i, &wall::trigger); if (w == wr.end()) { remove_trigger_num(Triggers, Walls.vmptr, i); diff --git a/similar/main/menu.cpp b/similar/main/menu.cpp index 0a66c5765..b3c6fd460 100644 --- a/similar/main/menu.cpp +++ b/similar/main/menu.cpp @@ -251,7 +251,7 @@ enum class select_dir_flag : uint8_t }; __attribute_nonnull() -static int select_file_recursive(const menu_title title, const std::array &orig_path, const std::ranges::subrange &ext_list, select_dir_flag select_dir, ntstring &userdata); +static int select_file_recursive(const menu_title title, const std::array &orig_path, const ranges::subrange &ext_list, select_dir_flag select_dir, ntstring &userdata); static window_event_result get_absolute_path(ntstring &full_path, const char *rel_path) { @@ -1264,7 +1264,7 @@ void screen_resolution_menu::check_apply_preset_resolution() const return 0; return ni.value; }; - const auto &&i = std::ranges::find_if(r, predicate); + const auto &&i = ranges::find_if(r, predicate); if (i == r.end()) return; const auto requested_mode = std::get<0>(*i); @@ -2216,23 +2216,23 @@ struct browser_storage { struct target_path_not_mounted {}; // List of file extensions we're looking for (if looking for a music file many types are possible) - const std::ranges::subrange ext_range; + const ranges::subrange ext_range; const select_dir_flag select_dir; // Allow selecting the current directory (e.g. for Jukebox level song directory) physfsx_mounted_path view_path; // The absolute path we're currently looking at string_array_t list; - browser_storage(const char *orig_path, const std::ranges::subrange &ext_range, const select_dir_flag select_dir, const char *const sep) : + browser_storage(const char *orig_path, const ranges::subrange &ext_range, const select_dir_flag select_dir, const char *const sep) : ext_range(ext_range), select_dir(select_dir), /* view_path is trivially constructed, then properly initialized as * a side effect of preparing the string list */ list(construct_string_list(orig_path, view_path, ext_range, select_dir, sep)) { } - static string_array_t construct_string_list(const char *orig_path, physfsx_mounted_path &view_path, const std::ranges::subrange &r, const select_dir_flag select_dir, const char *const sep); + static string_array_t construct_string_list(const char *orig_path, physfsx_mounted_path &view_path, const ranges::subrange &r, const select_dir_flag select_dir, const char *const sep); }; struct browser : browser_storage, listbox { - browser(const char *orig_path, menu_title title, const std::ranges::subrange &r, const select_dir_flag select_dir, const char *const sep, ntstring &userdata) : + browser(const char *orig_path, menu_title title, const ranges::subrange &r, const select_dir_flag select_dir, const char *const sep, ntstring &userdata) : browser_storage(orig_path, r, select_dir, sep), listbox(0, list.pointer().size(), &list.pointer().front(), title, grd_curscreen->sc_canvas, 1), userdata(userdata) @@ -2245,7 +2245,7 @@ struct browser : browser_storage, listbox struct list_directory_context { string_array_t &string_list; - const std::ranges::subrange ext_range; + const ranges::subrange ext_range; const std::array &path; }; @@ -2280,7 +2280,7 @@ window_event_result browser::callback_handler(const d_event &event, window_event }}; struct drive_letter_menu : passive_newmenu { - drive_letter_menu(grs_canvas &canvas, const std::ranges::subrange items) : + drive_letter_menu(grs_canvas &canvas, const ranges::subrange items) : passive_newmenu(menu_title{nullptr}, menu_subtitle{"Enter drive letter"}, menu_filename{nullptr}, tiny_mode_flag::normal, tab_processing_flag::ignore, adjusted_citem::create(items, 0), canvas) { } @@ -2364,7 +2364,7 @@ window_event_result browser::callback_handler(const d_event &event, window_event return window_event_result::ignored; } -static int select_file_recursive(const menu_title title, const std::array &orig_path_storage, const std::ranges::subrange &ext_range, const select_dir_flag select_dir, ntstring &userdata) +static int select_file_recursive(const menu_title title, const std::array &orig_path_storage, const ranges::subrange &ext_range, const select_dir_flag select_dir, ntstring &userdata) { const auto sep = PHYSFS_getDirSeparator(); auto orig_path = orig_path_storage.data(); @@ -2383,7 +2383,7 @@ static int select_file_recursive(const menu_title title, const std::array &ext_range, const select_dir_flag select_dir, const char *const sep) +string_array_t browser_storage::construct_string_list(const char *orig_path, physfsx_mounted_path &view_path, const ranges::subrange &ext_range, const select_dir_flag select_dir, const char *const sep) { view_path.path.front() = 0; // Set the viewing directory to orig_path, or some parent of it diff --git a/similar/main/mission.cpp b/similar/main/mission.cpp index 7e9ee5d68..9a3ddd868 100644 --- a/similar/main/mission.cpp +++ b/similar/main/mission.cpp @@ -879,7 +879,7 @@ static void set_briefing_filename(d_fname &f, const char *const v) auto a = [](char c) { return !c || c == '.'; }; - const auto &&i = std::ranges::find_if(v, next(v, f.size() - sizeof(tex)), a); + const auto &&i = ranges::find_if(v, next(v, f.size() - sizeof(tex)), a); std::size_t d = std::distance(v, i); set_briefing_filename(f, {v, d}); } @@ -889,7 +889,7 @@ static void record_briefing(d_fname &f, std::array &buf) const auto v = get_value(buf.data()); if (!v) return; - const std::size_t d = std::distance(v, std::ranges::find_if(v, buf.end(), null_or_space)); + const std::size_t d = std::distance(v, ranges::find_if(v, buf.end(), null_or_space)); if (d >= FILENAME_LEN) return; { @@ -1046,7 +1046,7 @@ static const char *load_mission(const mle *const mission) if (!PHYSFSX_fgets(buf, mfile)) break; auto &line = buf.line(); - const auto &&s = std::ranges::find_if(line, null_or_space); + const auto &&s = ranges::find_if(line, null_or_space); if (i.copy_if(line, std::distance(line.begin(), s))) { ++level_names_loaded; @@ -1092,7 +1092,7 @@ static const char *load_mission(const mle *const mission) auto a = [](char c) { return isspace(static_cast(c)); }; - const auto &&s = std::ranges::find_if(lb, t, a); + const auto &&s = ranges::find_if(lb, t, a); if (name.copy_if(line, std::distance(lb, s))) { unsigned long ls = strtoul(t + 1, &ip, 10); diff --git a/similar/main/morph.cpp b/similar/main/morph.cpp index 28bd6a134..15c66e186 100644 --- a/similar/main/morph.cpp +++ b/similar/main/morph.cpp @@ -476,7 +476,7 @@ void morph_start(d_level_unique_morph_object_state &LevelUniqueMorphObjectState, auto &mo = *pmo.get(); return mo.obj->type == OBJ_NONE || mo.obj->signature != mo.Morph_sig; }; - const auto moi = std::ranges::find_if(mob, moe, mop); + const auto moi = ranges::find_if(mob, moe, mop); if (moi == moe) //no free slots return; diff --git a/similar/main/multi.cpp b/similar/main/multi.cpp index 2d8389d54..a2021492b 100644 --- a/similar/main/multi.cpp +++ b/similar/main/multi.cpp @@ -3463,7 +3463,7 @@ texture_index find_goal_texture(const d_level_unique_tmap_info_state &LevelUniqu return (i.flags & tmi_flag); }; const auto begin = r.begin(); - const auto idx = std::distance(begin, std::ranges::find_if(begin, r.end(), predicate)); + const auto idx = std::distance(begin, ranges::find_if(begin, r.end(), predicate)); return idx; } @@ -4909,7 +4909,7 @@ void multi_initiate_save_game() multi_execute_save_game(slot, desc, player_range); } -void multi_execute_save_game(const d_game_unique_state::save_slot slot, const d_game_unique_state::savegame_description &desc, const std::ranges::subrange player_range) +void multi_execute_save_game(const d_game_unique_state::save_slot slot, const d_game_unique_state::savegame_description &desc, const ranges::subrange player_range) { // Make a unique game id fix game_id; diff --git a/similar/main/net_udp.cpp b/similar/main/net_udp.cpp index 9fbb78288..775468f6b 100644 --- a/similar/main/net_udp.cpp +++ b/similar/main/net_udp.cpp @@ -3047,7 +3047,7 @@ static unsigned net_udp_send_request(void) // game, non-zero if there is some problem. auto b = Netgame.players.begin(); auto e = Netgame.players.end(); - const auto &&i = std::ranges::find_if(b, e, [](const netplayer_info &ni) { return ni.connected != player_connection_status::disconnected; }); + const auto &&i = ranges::find_if(b, e, [](const netplayer_info &ni) { return ni.connected != player_connection_status::disconnected; }); if (i == e) { Assert(false); @@ -3110,7 +3110,7 @@ static void net_udp_process_game_info_light(const uint8_t *data, uint_fast32_t, menu->num_active_udp_changed = 1; auto r = partial_range(menu->Active_udp_games, menu->num_active_udp_games); - const auto &&i = std::ranges::find_if(r, [&recv_game](const UDP_netgame_info_lite &g) { return !d_stricmp(g.game_name.data(), recv_game.game_name.data()) && g.GameID == recv_game.GameID; }); + const auto &&i = ranges::find_if(r, [&recv_game](const UDP_netgame_info_lite &g) { return !d_stricmp(g.game_name.data(), recv_game.game_name.data()) && g.GameID == recv_game.GameID; }); if (i == menu->Active_udp_games.end()) { return; @@ -5671,7 +5671,7 @@ void net_udp_noloss_process_queue(fix64 time) { const auto b = UDP_mdata_queue.begin(); const auto e = std::next(b, UDP_mdata_queue_highest); - const auto &&first_used_entry = std::ranges::find_if(b, e, [](const UDP_mdata_store &m) { return m.used; }); + const auto &&first_used_entry = ranges::find_if(b, e, [](const UDP_mdata_store &m) { return m.used; }); if (first_used_entry != b) { std::move(first_used_entry, e, b); diff --git a/similar/main/newmenu.cpp b/similar/main/newmenu.cpp index 899524a51..0058c519a 100644 --- a/similar/main/newmenu.cpp +++ b/similar/main/newmenu.cpp @@ -688,13 +688,13 @@ static void newmenu_scroll(newmenu *const menu, const int amount) const auto predicate = [](const newmenu_item &n) { return n.type != nm_type::text; }; - const auto &&first = std::ranges::find_if(range, predicate); + const auto &&first = ranges::find_if(range, predicate); if (first == range.end()) /* This should not happen. If every entry is of type `nm_type::text`, * then `menu->all_text` should have been true. */ return; - const auto &&rlast = std::ranges::find_if(std::reverse_iterator(range.end()), std::reverse_iterator(first), predicate).base(); + const auto &&rlast = ranges::find_if(std::reverse_iterator(range.end()), std::reverse_iterator(first), predicate).base(); /* `first == rlast` should not happen, since that would mean that * there are no elements in `range` for which `predicate` is true. * If there are no such elements, then `first == range.end()` should diff --git a/similar/main/playsave.cpp b/similar/main/playsave.cpp index dd119f833..ad80d0925 100644 --- a/similar/main/playsave.cpp +++ b/similar/main/playsave.cpp @@ -1271,7 +1271,7 @@ namespace { * pointer to end(). The caller must check that the first unused * element is not end(). */ -static std::array::pointer, 2> find_hli_entry(const std::ranges::subrange r, const Mission_path &m) +static std::array::pointer, 2> find_hli_entry(const ranges::subrange r, const Mission_path &m) { const auto mission_filename = m.filename; const auto mission_length = std::distance(mission_filename, m.path.end()); @@ -1286,7 +1286,7 @@ static std::array::pointer, 2> find_hli_entry(cons const auto &&a = [p = &*mission_filename](const hli &h) { return !d_stricmp(h.Shortname.data(), p); }; - const auto &&i = std::ranges::find_if(r, a); + const auto &&i = ranges::find_if(r, a); return {{&*i, r.end()}}; } } diff --git a/similar/main/render.cpp b/similar/main/render.cpp index 05e0fe949..946cde013 100644 --- a/similar/main/render.cpp +++ b/similar/main/render.cpp @@ -1040,7 +1040,7 @@ static bool compare_children(fvcvertptr &vcvertptr, const vms_vector &Viewer_eye //short the children of segment to render in the correct order //returns non-zero if swaps were made using sort_child_array_t = per_side_array; -static void sort_seg_children(fvcvertptr &vcvertptr, const vms_vector &Viewer_eye, const vcsegptridx_t seg, const std::ranges::subrange &r) +static void sort_seg_children(fvcvertptr &vcvertptr, const vms_vector &Viewer_eye, const vcsegptridx_t seg, const ranges::subrange &r) { //for each child, compare with other children and see if order matters //if order matters, fix if wrong @@ -1400,7 +1400,7 @@ static void build_segment_list(render_state_t &rstate, const vms_vector &Viewer_ continue; //now order the sides in some magical way - const auto &&child_range = std::ranges::subrange(child_begin, child_iter); + const auto &&child_range = ranges::subrange(child_begin, child_iter); sort_seg_children(vcvertptr, Viewer_eye, seg, child_range); project_list(seg->verts); range_for (const auto siden, child_range) diff --git a/similar/main/scores.cpp b/similar/main/scores.cpp index 2952aeca3..dab8ab789 100644 --- a/similar/main/scores.cpp +++ b/similar/main/scores.cpp @@ -290,7 +290,7 @@ void scores_maybe_add_player() const auto end_score_stats = std::end(scores.stats); /* Find the position at which the player's score should be placed. */ - const auto &&iter_position = std::ranges::find_if(begin_score_stats, end_score_stats, predicate); + const auto &&iter_position = ranges::find_if(begin_score_stats, end_score_stats, predicate); const auto position = std::distance(begin_score_stats, iter_position); /* If iter_position == end_score_stats, then the player's score does * not beat any of the existing high scores. Include a special case diff --git a/similar/main/wall.cpp b/similar/main/wall.cpp index b4bb522d1..9b5b4ee18 100644 --- a/similar/main/wall.cpp +++ b/similar/main/wall.cpp @@ -437,7 +437,7 @@ void wall_open_door(const vmsegptridx_t seg, const sidenum_t side) if (w->state == wall_state::closing) { //closing, so reuse door const auto &&r = make_range(vmactdoorptr); const auto &&re = r.end(); - const auto &&i = std::ranges::find_if(r.begin(), re, find_active_door_predicate(wall_num)); + const auto &&i = ranges::find_if(r.begin(), re, find_active_door_predicate(wall_num)); if (i == re) // likely in demo playback or multiplayer { const auto c = ActiveDoors.get_count(); @@ -550,7 +550,7 @@ void start_wall_cloak(const vmsegptridx_t seg, const sidenum_t side) { //decloaking, so reuse door const auto &&r = make_range(CloakingWalls.vmptr); const auto &&re = r.end(); - const auto &&i = std::ranges::find_if(r.begin(), re, find_cloaked_wall_predicate(w)); + const auto &&i = ranges::find_if(r.begin(), re, find_cloaked_wall_predicate(w)); if (i == re) { d_debugbreak(); @@ -627,7 +627,7 @@ void start_wall_decloak(const vmsegptridx_t seg, const sidenum_t side) if (w->state == wall_state::cloaking) { //cloaking, so reuse door const auto &&r = make_range(CloakingWalls.vmptr); const auto &&re = r.end(); - const auto &&i = std::ranges::find_if(r.begin(), re, find_cloaked_wall_predicate(w)); + const auto &&i = ranges::find_if(r.begin(), re, find_cloaked_wall_predicate(w)); if (i == re) { d_debugbreak(); @@ -800,7 +800,7 @@ void wall_close_door(wall_array &Walls, const vmsegptridx_t seg, const sidenum_t { //reuse door const auto &&r = make_range(vmactdoorptr); const auto &&re = r.end(); - const auto &&i = std::ranges::find_if(r.begin(), re, find_active_door_predicate(wall_num)); + const auto &&i = ranges::find_if(r.begin(), re, find_active_door_predicate(wall_num)); if (i == re) { d_debugbreak(); @@ -1463,7 +1463,7 @@ void d_level_unique_stuck_object_state::remove_stuck_object(const vcobjidx_t obj auto &&pr = partial_range(Stuck_objects, Num_stuck_objects); auto &&pre = pr.end(); const auto predicate = [obj](const stuckobj &so) { return so.objnum == obj; }; - const auto &&i = std::ranges::find_if(pr.begin(), pre, predicate); + const auto &&i = ranges::find_if(pr.begin(), pre, predicate); if (i == pre) /* Objects enter this function if they are able to become stuck, * without regard to whether they actually are stuck. If the diff --git a/similar/misc/physfsx.cpp b/similar/misc/physfsx.cpp index 1f815c3cb..2eb44d885 100644 --- a/similar/misc/physfsx.cpp +++ b/similar/misc/physfsx.cpp @@ -71,7 +71,7 @@ char *PHYSFSX_fgets_t::get(const std::span buf, PHYSFS_File *const fp) return cleanup(); } -int PHYSFSX_checkMatchingExtension(const char *filename, const std::ranges::subrange range) +int PHYSFSX_checkMatchingExtension(const char *filename, const ranges::subrange range) { const char *ext = strrchr(filename, '.'); if (!ext) @@ -504,7 +504,7 @@ static inline PHYSFSX_uncounted_list PHYSFSX_findPredicateFiles(const char *path // Find files at path that have an extension listed in exts // The extension list exts must be NULL-terminated, with each ext beginning with a '.' -PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, const std::ranges::subrange exts) +PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, const ranges::subrange exts) { const auto predicate = [&](const char *i) { return PHYSFSX_checkMatchingExtension(i, exts); @@ -514,7 +514,7 @@ PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, const std::ranges::su // Same function as above but takes a real directory as second argument, only adding files originating from this directory. // This can be used to further seperate files in search path but it must be made sure realpath is properly formatted. -PHYSFSX_uncounted_list PHYSFSX_findabsoluteFiles(const char *path, const char *realpath, const std::ranges::subrange exts) +PHYSFSX_uncounted_list PHYSFSX_findabsoluteFiles(const char *path, const char *realpath, const ranges::subrange exts) { const auto predicate = [&](const char *i) { return PHYSFSX_checkMatchingExtension(i, exts) && (!strcmp(PHYSFS_getRealDir(i), realpath));