From a8c24df4cbfaa4bae5d00f439a61f448aab1d3cf Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Thu, 4 Jun 2026 17:11:23 +0200 Subject: [PATCH 01/18] Implement C++20 versions for future std::format functions: formatting a range (C++26), std::print (C++23) For the string one, I went with the same behavior as fmt ``` std::vector v{"element1", "element2", "element3"}; fmt::print("{}\n", v); => ["element1", "element2", "element3"] ``` --- src/EnergyPlus/Formatters.hh | 130 +++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/EnergyPlus/Formatters.hh diff --git a/src/EnergyPlus/Formatters.hh b/src/EnergyPlus/Formatters.hh new file mode 100644 index 00000000000..861b0fad1c2 --- /dev/null +++ b/src/EnergyPlus/Formatters.hh @@ -0,0 +1,130 @@ +// EnergyPlus, Copyright (c) 1996-present, The Board of Trustees of the University of Illinois, +// The Regents of the University of California, through Lawrence Berkeley National Laboratory +// (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge +// National Laboratory, managed by UT-Battelle, Alliance for Energy Innovation, LLC, and other +// contributors. All rights reserved. +// +// NOTICE: This Software was developed under funding from the U.S. Department of Energy and the +// U.S. Government consequently retains certain rights. As such, the U.S. Government has been +// granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, +// worldwide license in the Software to reproduce, distribute copies to the public, prepare +// derivative works, and perform publicly and display publicly, and to permit others to do so. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, +// the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific prior +// written permission. +// +// (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form +// without changes from the version obtained under this License, or (ii) Licensee makes a +// reference solely to the software portion of its product, Licensee must refer to the +// software as "EnergyPlus version X" software, where "X" is the version number Licensee +// obtained under this License and may not use a different name for the software. Except as +// specifically required in this Section (4), Licensee shall not use in a company name, a +// product name, in advertising, publicity, or other promotional activities any name, trade +// name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly +// similar designation, without the U.S. Department of Energy's prior written consent. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef Formatters_hh_INCLUDED +#define Formatters_hh_INCLUDED + +#include +#include +#include +#include +#include + +#if __cplusplus >= 202302L +# error "std::formattable is defined, remove C++ 20 implementation" +#endif + +template +concept formattable = + requires(std::remove_reference_t & v, std::basic_format_context>, CharT> ctx) +{ + std::formatter, CharT>{}.format(v, ctx); + std::formatter, CharT>{}.parse(std::declval &>()); +}; + +template +concept formattable_range = + // A range + std::ranges::range // A range + // A range of formattable elements. It'd be a nicer error message to include it, but that prevents using it for a range of range + // eg : std::vector>. + // && std::formattable, char> + // But we exclude the ones that are already formattable as a whole, like std::string and std::string_view, char*. + && !std::is_same_v && !std::is_same_v && !std::is_same_v, char>; + +template struct std::formatter +{ + using T = std::ranges::range_value_t; + std::formatter element_formatter; + + constexpr auto parse(std::format_parse_context &ctx) -> std::format_parse_context::iterator + { + return element_formatter.parse(ctx); + } + + auto format(const Container &v, std::format_context &ctx) const -> std::format_context::iterator + { + auto it = ctx.out(); + *it++ = '['; + bool first = true; + for (const auto &elem : v) { + if (!first) { + it = std::format_to(it, ", "); + } + first = false; + if constexpr (std::is_same_v || std::is_same_v) { + it = std::format_to(it, "\""); + it = element_formatter.format(elem, ctx); + it = std::format_to(it, "\""); + } else { + it = element_formatter.format(elem, ctx); + } + } + *it++ = ']'; + return it; + } +}; + +#ifdef __cpp_lib_print +# error "std::print is defined, remove C++ 20 implementation" +#endif + +namespace std { +template void print(FILE *stream, std::format_string fmt, Args &&...args) +{ + std::string formatted = std::format(fmt, std::forward(args)...); + if (std::fwrite(formatted.data(), 1, formatted.size(), stream) != formatted.size()) { + throw std::system_error(EIO, std::generic_category()); + } +} +template void print(std::format_string fmt, Args &&...args) +{ + print(stdout, fmt, std::forward(args)...); +} +} // namespace std + +#endif From 2c85be8e59103824df0cef2369ff38971fee0cf0 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Thu, 4 Jun 2026 17:51:14 +0200 Subject: [PATCH 02/18] Add tests for Formatters + Implement fmt-like and C++23 range format of std::set as {1, 2, 3} not [1, 2, 3] --- src/EnergyPlus/Formatters.hh | 20 ++- tst/EnergyPlus/unit/CMakeLists.txt | 1 + tst/EnergyPlus/unit/Formatters.unit.cc | 177 +++++++++++++++++++++++++ 3 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 tst/EnergyPlus/unit/Formatters.unit.cc diff --git a/src/EnergyPlus/Formatters.hh b/src/EnergyPlus/Formatters.hh index 861b0fad1c2..098653aea9c 100644 --- a/src/EnergyPlus/Formatters.hh +++ b/src/EnergyPlus/Formatters.hh @@ -66,10 +66,15 @@ concept formattable = std::formatter, CharT>{}.parse(std::declval &>()); }; +template concept set_like = std::ranges::range && requires +{ + typename T::key_type; +}; + template concept formattable_range = // A range - std::ranges::range // A range + std::ranges::range // A range of formattable elements. It'd be a nicer error message to include it, but that prevents using it for a range of range // eg : std::vector>. // && std::formattable, char> @@ -88,15 +93,18 @@ template struct std::formatter auto format(const Container &v, std::format_context &ctx) const -> std::format_context::iterator { + constexpr char open = set_like ? '{' : '['; + constexpr char close = set_like ? '}' : ']'; + constexpr bool quoted = std::is_same_v || std::is_same_v; + auto it = ctx.out(); - *it++ = '['; - bool first = true; - for (const auto &elem : v) { + *it++ = open; + for (bool first = true; const auto &elem : v) { if (!first) { it = std::format_to(it, ", "); } first = false; - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (quoted) { it = std::format_to(it, "\""); it = element_formatter.format(elem, ctx); it = std::format_to(it, "\""); @@ -104,7 +112,7 @@ template struct std::formatter it = element_formatter.format(elem, ctx); } } - *it++ = ']'; + *it++ = close; return it; } }; diff --git a/tst/EnergyPlus/unit/CMakeLists.txt b/tst/EnergyPlus/unit/CMakeLists.txt index 8e2d08e3c75..579c5893457 100644 --- a/tst/EnergyPlus/unit/CMakeLists.txt +++ b/tst/EnergyPlus/unit/CMakeLists.txt @@ -125,6 +125,7 @@ set(test_src FiniteDifferenceGroundTemperatureModel.unit.cc FluidCoolers.unit.cc FluidProperties.unit.cc + Formatters.unit.cc FuelCellElectricGenerator.unit.cc Furnaces.unit.cc General.unit.cc diff --git a/tst/EnergyPlus/unit/Formatters.unit.cc b/tst/EnergyPlus/unit/Formatters.unit.cc new file mode 100644 index 00000000000..b17aeab691c --- /dev/null +++ b/tst/EnergyPlus/unit/Formatters.unit.cc @@ -0,0 +1,177 @@ +// EnergyPlus, Copyright (c) 1996-present, The Board of Trustees of the University of Illinois, +// The Regents of the University of California, through Lawrence Berkeley National Laboratory +// (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge +// National Laboratory, managed by UT-Battelle, Alliance for Energy Innovation, LLC, and other +// contributors. All rights reserved. +// +// NOTICE: This Software was developed under funding from the U.S. Department of Energy and the +// U.S. Government consequently retains certain rights. As such, the U.S. Government has been +// granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, +// worldwide license in the Software to reproduce, distribute copies to the public, prepare +// derivative works, and perform publicly and display publicly, and to permit others to do so. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, +// the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific prior +// written permission. +// +// (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form +// without changes from the version obtained under this License, or (ii) Licensee makes a +// reference solely to the software portion of its product, Licensee must refer to the +// software as "EnergyPlus version X" software, where "X" is the version number Licensee +// obtained under this License and may not use a different name for the software. Except as +// specifically required in this Section (4), Licensee shall not use in a company name, a +// product name, in advertising, publicity, or other promotional activities any name, trade +// name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly +// similar designation, without the U.S. Department of Energy's prior written consent. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// Google Test Headers +#include + +// C++ Headers +#include +#include +#include +#include +#include +#include + +// Third Party Headers +#include + +// EnergyPlus Headers +#include +#include +#include + +using namespace EnergyPlus; + +TEST(Formatters, Formatters_Path) +{ + EXPECT_EQ("foo/bar/baz", std::format("{}", fs::path("foo/bar/baz"))); + EXPECT_EQ("foo\\bar\\baz", std::format("{}", fs::path("foo\\bar\\baz"))); + EXPECT_EQ("foo/bar/baz", std::format("{:g}", fs::path("foo/bar/baz"))); +#ifdef _WIN32 + EXPECT_EQ("foo\\bar\\baz", std::format("{:g}", fs::path("foo/bar/baz"))); +#endif +} + +TEST(Formatters, Formatters_Ranges_Numeric) +{ + + { + std::vector vec{1, 2, 3}; + EXPECT_EQ("[1, 2, 3]", std::format("{}", vec)); + } + + { + std::vector vec{1.1, 2.2, 3.3}; + EXPECT_EQ("[1.1, 2.2, 3.3]", std::format("{}", vec)); + EXPECT_EQ("[1.10, 2.20, 3.30]", std::format("{:.2f}", vec)); + EXPECT_EQ("[1.100, 2.200, 3.300]", std::format("{:.3f}", vec)); + } + + { + std::array vec{1.1, 2.2, 3.3}; + EXPECT_EQ("[1.1, 2.2, 3.3]", std::format("{}", vec)); + EXPECT_EQ("[1.10, 2.20, 3.30]", std::format("{:.2f}", vec)); + EXPECT_EQ("[1.100, 2.200, 3.300]", std::format("{:.3f}", vec)); + } + + { + EnergyPlus::EPVector vec; + vec.allocate(3); + vec(1) = 1.1; + vec(2) = 2.2; + vec(3) = 3.3; + EXPECT_EQ("[1.1, 2.2, 3.3]", std::format("{}", vec)); + EXPECT_EQ("[1.10, 2.20, 3.30]", std::format("{:.2f}", vec)); + EXPECT_EQ("[1.100, 2.200, 3.300]", std::format("{:.3f}", vec)); + } + + { + ObjexxFCL::Array1D vec(3); + vec(1) = 1.1; + vec(2) = 2.2; + vec(3) = 3.3; + EXPECT_EQ("[1.1, 2.2, 3.3]", std::format("{}", vec)); + EXPECT_EQ("[1.10, 2.20, 3.30]", std::format("{:.2f}", vec)); + EXPECT_EQ("[1.100, 2.200, 3.300]", std::format("{:.3f}", vec)); + } + + { + std::set s{1, 2, 3}; + EXPECT_EQ("{1, 2, 3}", std::format("{}", s)); + } +} + +TEST(Formatters, Formatters_Ranges_Chars) +{ + + { + std::string str = "element"; + EXPECT_EQ("element", std::format("{}", str)); + } + + { + std::string_view str = "element"; + EXPECT_EQ("element", std::format("{}", str)); + } + + { + const char *str = "element"; + EXPECT_EQ("element", std::format("{}", str)); + } + + { + std::vector vec{"a", "b", "c"}; + EXPECT_EQ(R"(["a", "b", "c"])", std::format("{}", vec)); + } + + { + std::vector vec{"a", "b", "c"}; + EXPECT_EQ(R"(["a", "b", "c"])", std::format("{}", vec)); + } + + { + std::vector vec{"a", "b", "c"}; + EXPECT_EQ("[a, b, c]", std::format("{}", vec)); + } +} + +TEST(Formatters, Formatters_Ranges_Nested) +{ + { + std::vector> vec{{1, 2}, {3, 4}, {5, 6, 7}}; + EXPECT_EQ(R"([[1, 2], [3, 4], [5, 6, 7]])", std::format("{}", vec)); + } +} + +TEST(Formatters, Formatters_join) +{ + { + std::vector CondTempArray{0.0000, 0.1000, 0.2000, 0.3000, 0.4000, 0.5000, 0.6000, 0.7000, 0.8000, 0.9000, 1.0000}; + EXPECT_EQ("PLR = 0.00 0.10 0.20 0.30 0.40 0.50 0.60 0.70 0.80 0.90 1.00", + fmt::format("PLR = {:7.2F}", fmt::join(CondTempArray, ""))); + } +} From d0dd821791a01d38aefab25b93b2e127662fb5bf Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Thu, 4 Jun 2026 18:06:51 +0200 Subject: [PATCH 03/18] Implement a fmt::join equivalent --- src/EnergyPlus/Formatters.hh | 40 ++++++++++++++++++++++++++ tst/EnergyPlus/unit/Formatters.unit.cc | 2 ++ 2 files changed, 42 insertions(+) diff --git a/src/EnergyPlus/Formatters.hh b/src/EnergyPlus/Formatters.hh index 098653aea9c..1279558235f 100644 --- a/src/EnergyPlus/Formatters.hh +++ b/src/EnergyPlus/Formatters.hh @@ -135,4 +135,44 @@ template void print(std::format_string fmt, Args &&...a } } // namespace std +namespace detail { +template struct format_join_view +{ + const R ⦥ + std::string_view sep; +}; +} // namespace detail + +template struct std::formatter<::detail::format_join_view> +{ + std::formatter> element_formatter; + + constexpr auto parse(std::format_parse_context &ctx) -> std::format_parse_context::iterator + { + return element_formatter.parse(ctx); + } + + auto format(const ::detail::format_join_view &jv, std::format_context &ctx) const -> std::format_context::iterator + { + auto it = ctx.out(); + bool first = true; + for (const auto &elem : jv.range) { + if (!first) { + it = std::ranges::copy(jv.sep, it).out; + } + first = false; + it = element_formatter.format(elem, ctx); + } + return it; + } +}; + +namespace EnergyPlus { +template auto join(const R &r, std::string_view sep) +{ + return ::detail::format_join_view{r, sep}; +} + +} // namespace EnergyPlus + #endif diff --git a/tst/EnergyPlus/unit/Formatters.unit.cc b/tst/EnergyPlus/unit/Formatters.unit.cc index b17aeab691c..dee9071d65a 100644 --- a/tst/EnergyPlus/unit/Formatters.unit.cc +++ b/tst/EnergyPlus/unit/Formatters.unit.cc @@ -173,5 +173,7 @@ TEST(Formatters, Formatters_join) std::vector CondTempArray{0.0000, 0.1000, 0.2000, 0.3000, 0.4000, 0.5000, 0.6000, 0.7000, 0.8000, 0.9000, 1.0000}; EXPECT_EQ("PLR = 0.00 0.10 0.20 0.30 0.40 0.50 0.60 0.70 0.80 0.90 1.00", fmt::format("PLR = {:7.2F}", fmt::join(CondTempArray, ""))); + EXPECT_EQ("PLR = 0.00 0.10 0.20 0.30 0.40 0.50 0.60 0.70 0.80 0.90 1.00", + std::format("PLR = {:7.2F}", EnergyPlus::join(CondTempArray, ""))); } } From acd56dce5a7c22e97d2e13912a1f54012cc47b5d Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Thu, 4 Jun 2026 18:50:34 +0200 Subject: [PATCH 04/18] Eliminate all calls to fmt::join + one usage --- src/EnergyPlus/ChillerElectricEIR.cc | 7 +-- src/EnergyPlus/ChillerReformulatedEIR.cc | 5 +- .../BaseGroundTemperatureModel.hh | 3 +- src/EnergyPlus/IOFiles.hh | 1 - src/EnergyPlus/OutputReportTabular.cc | 55 +++++++++---------- src/EnergyPlus/PlantCentralGSHP.cc | 6 +- src/EnergyPlus/ResultsFramework.cc | 8 +-- src/EnergyPlus/ZoneTempPredictorCorrector.cc | 5 +- tst/EnergyPlus/unit/CurveManager.unit.cc | 10 ++-- 9 files changed, 51 insertions(+), 49 deletions(-) diff --git a/src/EnergyPlus/ChillerElectricEIR.cc b/src/EnergyPlus/ChillerElectricEIR.cc index 0bc40c1c992..ff00a317bd5 100644 --- a/src/EnergyPlus/ChillerElectricEIR.cc +++ b/src/EnergyPlus/ChillerElectricEIR.cc @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -728,10 +729,8 @@ void GetElectricEIRChillerInput(EnergyPlusData &state) ShowSevereError(state, std::format("{}{}=\"{}\"", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1))); ShowContinueError(state, "Energy input ratio as a function of part-load ratio curve shows negative values."); ShowContinueError(state, "EIR as a function of PLR curve output at various part-load ratios shown below:"); - ShowContinueError( - state, fmt::format(fmt::runtime("PLR = {:7." + std::to_string(DecimalPrecision) + "F}"), fmt::join(PLRArray, ","))); - ShowContinueError( - state, fmt::format(fmt::runtime("Curve Output = {:7." + std::to_string(DecimalPrecision) + "F}"), fmt::join(CurveValArray, ","))); + ShowContinueError(state, std::format("PLR = {:7.{}F}", EnergyPlus::join(PLRArray, ","), DecimalPrecision)); + ShowContinueError(state, std::format("Curve Output = {:7.{}F}", EnergyPlus::join(CurveValArray, ","), DecimalPrecision)); ErrorsFound = true; } } diff --git a/src/EnergyPlus/ChillerReformulatedEIR.cc b/src/EnergyPlus/ChillerReformulatedEIR.cc index cb4c61ee9f8..f5260394c25 100644 --- a/src/EnergyPlus/ChillerReformulatedEIR.cc +++ b/src/EnergyPlus/ChillerReformulatedEIR.cc @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -1641,8 +1642,8 @@ void ReformulatedEIRChillerSpecs::size(EnergyPlusData &state) ShowContinueError(state, "EIR as a function of PLR curve output at various part-load ratios and condenser water temperatures shown below:"); ShowContinueError(state, "PLR = 0.00 0.10 0.20 0.30 0.40 0.50 0.60 0.70 0.80 0.90 1.00"); - ShowContinueError(state, fmt::format("Cond Temp(C) = {:7.2F}", fmt::join(CondTempArray, " "))); - ShowContinueError(state, fmt::format("Curve Output = {:7.2F}", fmt::join(CurveValArray, " "))); + ShowContinueError(state, std::format("Cond Temp(C) = {:7.2F}", EnergyPlus::join(CondTempArray, ""))); + ShowContinueError(state, std::format("Curve Output = {:7.2F}", EnergyPlus::join(CurveValArray, ""))); ErrorsFound = true; } } diff --git a/src/EnergyPlus/GroundTemperatureModeling/BaseGroundTemperatureModel.hh b/src/EnergyPlus/GroundTemperatureModeling/BaseGroundTemperatureModel.hh index 2956c62caca..d9945d9b501 100644 --- a/src/EnergyPlus/GroundTemperatureModeling/BaseGroundTemperatureModel.hh +++ b/src/EnergyPlus/GroundTemperatureModeling/BaseGroundTemperatureModel.hh @@ -51,6 +51,7 @@ // EnergyPlus Headers #include #include +#include namespace EnergyPlus { @@ -119,7 +120,7 @@ namespace GroundTemp { ",Jan{{C}},Feb{{C}},Mar{{C}},Apr{{C}},May{{C}},Jun{{C}},Jul{{C}},Aug{{C}},Sep{{C}},Oct{{" "C}},Nov{{C}},Dec{{C}}\n", name); - print(os, " Site:GroundTemperature:{}, {}\n", name, fmt::format("{:6.2F}", fmt::join(data, ", "))); + print(os, " Site:GroundTemperature:{}, {}\n", name, std::format("{:6.2F}", EnergyPlus::join(data, ", "))); } }; diff --git a/src/EnergyPlus/IOFiles.hh b/src/EnergyPlus/IOFiles.hh index 3ce425bb815..e5fc2b182a4 100644 --- a/src/EnergyPlus/IOFiles.hh +++ b/src/EnergyPlus/IOFiles.hh @@ -62,7 +62,6 @@ #include #include #include -#include #include // EnergyPlus Headers diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index 220713b71c0..508f2691d8b 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -72,7 +72,6 @@ // Third Party Headers #include -#include // EnergyPlus Headers #include @@ -107,6 +106,7 @@ #include #include #include +#include #include #include #include @@ -5291,20 +5291,19 @@ void WriteTabularReports(EnergyPlusData &state) } constexpr static std::string_view variable_fmt = " {}={:12}\n"; - constexpr static auto variable_fmt_syntax = check_syntax(variable_fmt); // (AUTO_OK) not sure what this is state.files.audit.ensure_open(state, "WriteTabularReports", state.files.outputControl.audit); - print(state.files.audit, variable_fmt, "MonthlyInputCount", ort->MonthlyInputCount); - print(state.files.audit, variable_fmt, "sizeMonthlyInput", ort->sizeMonthlyInput); - print(state.files.audit, variable_fmt, "MonthlyFieldSetInputCount", ort->MonthlyFieldSetInputCount); - print(state.files.audit, variable_fmt, "sizeMonthlyFieldSetInput", ort->sizeMonthlyFieldSetInput); - print(state.files.audit, variable_fmt, "MonthlyTablesCount", ort->MonthlyTablesCount); - print(state.files.audit, variable_fmt, "MonthlyColumnsCount", ort->MonthlyColumnsCount); - print(state.files.audit, variable_fmt, "sizeReportName", state.dataOutRptPredefined->sizeReportName); - print(state.files.audit, variable_fmt, "numReportName", state.dataOutRptPredefined->numReportName); - print(state.files.audit, variable_fmt, "sizeSubTable", state.dataOutRptPredefined->sizeSubTable); - print(state.files.audit, variable_fmt, "numSubTable", state.dataOutRptPredefined->numSubTable); - print(state.files.audit, variable_fmt, "sizeColumnTag", state.dataOutRptPredefined->sizeColumnTag); - print(state.files.audit, variable_fmt, "numColumnTag", state.dataOutRptPredefined->numColumnTag); + print(state.files.audit, variable_fmt, "MonthlyInputCount", ort->MonthlyInputCount); + print(state.files.audit, variable_fmt, "sizeMonthlyInput", ort->sizeMonthlyInput); + print(state.files.audit, variable_fmt, "MonthlyFieldSetInputCount", ort->MonthlyFieldSetInputCount); + print(state.files.audit, variable_fmt, "sizeMonthlyFieldSetInput", ort->sizeMonthlyFieldSetInput); + print(state.files.audit, variable_fmt, "MonthlyTablesCount", ort->MonthlyTablesCount); + print(state.files.audit, variable_fmt, "MonthlyColumnsCount", ort->MonthlyColumnsCount); + print(state.files.audit, variable_fmt, "sizeReportName", state.dataOutRptPredefined->sizeReportName); + print(state.files.audit, variable_fmt, "numReportName", state.dataOutRptPredefined->numReportName); + print(state.files.audit, variable_fmt, "sizeSubTable", state.dataOutRptPredefined->sizeSubTable); + print(state.files.audit, variable_fmt, "numSubTable", state.dataOutRptPredefined->numSubTable); + print(state.files.audit, variable_fmt, "sizeColumnTag", state.dataOutRptPredefined->sizeColumnTag); + print(state.files.audit, variable_fmt, "numColumnTag", state.dataOutRptPredefined->numColumnTag); int sizeTableEntry = 0; int numTableEntry = 0; @@ -5313,10 +5312,10 @@ void WriteTabularReports(EnergyPlusData &state) numTableEntry += state.dataOutRptPredefined->subTable(i).numEntries; } - print(state.files.audit, variable_fmt, "sizeTableEntry", sizeTableEntry); - print(state.files.audit, variable_fmt, "numTableEntry", numTableEntry); - print(state.files.audit, variable_fmt, "sizeCompSizeTableEntry", state.dataOutRptPredefined->sizeCompSizeTableEntry); - print(state.files.audit, variable_fmt, "numCompSizeTableEntry", state.dataOutRptPredefined->numCompSizeTableEntry); + print(state.files.audit, variable_fmt, "sizeTableEntry", sizeTableEntry); + print(state.files.audit, variable_fmt, "numTableEntry", numTableEntry); + print(state.files.audit, variable_fmt, "sizeCompSizeTableEntry", state.dataOutRptPredefined->sizeCompSizeTableEntry); + print(state.files.audit, variable_fmt, "numCompSizeTableEntry", state.dataOutRptPredefined->numCompSizeTableEntry); } void setTabularReportStyles(EnergyPlusData &state) @@ -11054,7 +11053,7 @@ void WriteCompCostTable(EnergyPlusData &state) columnWidth = {7, 30, 16, 10, 16, 16}; // array assignment - for all columns for (int item = 1; item <= (int)state.dataCostEstimateManager->CostLineItem.size(); ++item) { - tableBody(1, item) = fmt::to_string(state.dataCostEstimateManager->CostLineItem(item).LineNumber); + tableBody(1, item) = std::to_string(state.dataCostEstimateManager->CostLineItem(item).LineNumber); tableBody(2, item) = state.dataCostEstimateManager->CostLineItem(item).LineName; if (currentStyle.unitsStyle == OutputReportTabular::UnitsStyle::InchPound || currentStyle.unitsStyle == OutputReportTabular::UnitsStyle::InchPoundExceptElectricity) { @@ -11280,7 +11279,7 @@ void WriteVeriSumTable(EnergyPlusData &state) tableBody(1, 8) = RealToStr(currentStyle.formatReals, state.dataHeatBal->BuildingAzimuth, 2); // north axis angle tableBody(1, 9) = RealToStr(currentStyle.formatReals, state.dataHeatBal->BuildingRotationAppendixG, 2); // Rotation for Appendix G tableBody(1, 10) = RealToStr(currentStyle.formatReals, ort->gatherElapsedTimeBEPS, 2); // hours simulated - // tableBody(9,1) = TRIM(fmt::to_string(numTableEntry)) !number of table entries for predefined tables + // tableBody(9,1) = TRIM(std::to_string(numTableEntry)) !number of table entries for predefined tables if (currentStyle.produceTabular) { WriteSubtitle(state, "General"); @@ -12229,7 +12228,7 @@ void writeVeriSumSpaceTables(EnergyPlusData &state, const tabularReportStyle &st spaceTableBody(colSpacePlugProcess, spaceTableRowNum) = RealToStr(style.formatReals, 0.0, 4); } - spaceTableBody(colSpaceTags, spaceTableRowNum) = fmt::format("{}", fmt::join(curSpace.tags, ", ")); + spaceTableBody(colSpaceTags, spaceTableRowNum) = std::format("{}", EnergyPlus::join(curSpace.tags, ", ")); // If not part of total, goes directly to this row if (!useSpaceFloorArea) { @@ -14696,7 +14695,7 @@ void WriteEioTables(EnergyPlusData &state) break; // should never happen since same test as original could } std::vector dataFields = splitCommaString(bodyLine); - rowHead(rowNum) = fmt::to_string(rowNum); + rowHead(rowNum) = std::to_string(rowNum); for (int iCol = 1; iCol <= numCols && iCol < int(dataFields.size()); ++iCol) { if (currentStyle.unitsStyle == OutputReportTabular::UnitsStyle::InchPound || currentStyle.unitsStyle == OutputReportTabular::UnitsStyle::InchPoundExceptElectricity || @@ -17231,11 +17230,11 @@ void OutputCompLoadSummary(EnergyPlusData &state, } tableBody(1, 1) = std::format("{:.{}f}", curCompLoad.outsideAirRatio, 4); // outside Air - tableBody(1, 2) = fmt::format("{:0.3E}", curCompLoad.airflowPerFlrArea); // airflow per floor area - tableBody(1, 3) = fmt::format("{:0.3E}", curCompLoad.airflowPerTotCap); // airflow per total capacity - tableBody(1, 4) = fmt::format("{:0.3E}", curCompLoad.areaPerTotCap); // area per total capacity - tableBody(1, 5) = fmt::format("{:0.3E}", curCompLoad.totCapPerArea); // total capacity per area - tableBody(1, 6) = fmt::format("{:.{}f}", curCompLoad.numPeople, 1); // number of people + tableBody(1, 2) = std::format("{:0.3E}", curCompLoad.airflowPerFlrArea); // airflow per floor area + tableBody(1, 3) = std::format("{:0.3E}", curCompLoad.airflowPerTotCap); // airflow per total capacity + tableBody(1, 4) = std::format("{:0.3E}", curCompLoad.areaPerTotCap); // area per total capacity + tableBody(1, 5) = std::format("{:0.3E}", curCompLoad.totCapPerArea); // total capacity per area + tableBody(1, 6) = std::format("{:.{}f}", curCompLoad.numPeople, 1); // number of people if (style.produceTabular) { WriteSubtitle(state, engineeringCheckName); @@ -17272,7 +17271,7 @@ void OutputCompLoadSummary(EnergyPlusData &state, columnHead(1) = "Zone Name"; for (int zi = 1; zi <= maxRow; ++zi) { - rowHead(zi) = fmt::to_string(zi); + rowHead(zi) = std::to_string(zi); if (curCompLoad.zoneIndices(zi) > 0) { tableBody(1, zi) = state.dataHeatBal->Zone(curCompLoad.zoneIndices(zi)).Name; } diff --git a/src/EnergyPlus/PlantCentralGSHP.cc b/src/EnergyPlus/PlantCentralGSHP.cc index a3dcb3de04a..dc49d65307f 100644 --- a/src/EnergyPlus/PlantCentralGSHP.cc +++ b/src/EnergyPlus/PlantCentralGSHP.cc @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -1437,7 +1438,7 @@ void GetChillerHeaterInput(EnergyPlusData &state) ShowContinueError(state, "EIR as a function of PLR curve output at various part-load ratios shown below:"); ShowContinueError(state, "PLR = 0.00 0.10 0.20 0.30 0.40 0.50 0.60 0.70 0.80 0.90 1.00"); - ShowContinueError(state, fmt::format("Curve Output = {:7.2F}", fmt::join(CurveValArray, ","))); + ShowContinueError(state, std::format("Curve Output = {:7.2F}", EnergyPlus::join(CurveValArray, ","))); CHErrorsFound = true; } @@ -1502,8 +1503,7 @@ void GetChillerHeaterInput(EnergyPlusData &state) ShowContinueError(state, "EIR as a function of PLR curve output at various part-load ratios shown below:"); ShowContinueError(state, "PLR = 0.00 0.10 0.20 0.30 0.40 0.50 0.60 0.70 0.80 0.90 1.00"); - std::string const curve_output = fmt::format("Curve Output = {:7.2F}", fmt::join(CurveValArray, ",")); - ShowContinueError(state, curve_output); + ShowContinueError(state, std::format("Curve Output = {:7.2F}", EnergyPlus::join(CurveValArray, ","))); CHErrorsFound = true; } diff --git a/src/EnergyPlus/ResultsFramework.cc b/src/EnergyPlus/ResultsFramework.cc index 3bca7f5c089..15bdbb9c8b1 100644 --- a/src/EnergyPlus/ResultsFramework.cc +++ b/src/EnergyPlus/ResultsFramework.cc @@ -61,12 +61,12 @@ #include // Third Party Headers -#include #include // EnergyPlus Headers #include #include +#include #include #include #include @@ -373,8 +373,8 @@ namespace ResultsFramework { std::swap(curMin, lastMinute); } // future start of ISO 8601 datetime output - // fmt::format("YYYY-{:02d}/{:02d}T{:02d}:{:02d}:00", month, dayOfMonth, hourOfDay, curMin); - // fmt::format("{:02d}/{:02d} {:02d}:{:02d}:00", month, dayOfMonth, hourOfDay, curMin); + // std::format("YYYY-{:02d}/{:02d}T{:02d}:{:02d}:00", month, dayOfMonth, hourOfDay, curMin); + // std::format("{:02d}/{:02d} {:02d}:{:02d}:00", month, dayOfMonth, hourOfDay, curMin); if (iso8601) { TS.emplace_back(EnergyPlus::format("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:00", calendarYear, month, dayOfMonth, hourOfDay, curMin)); } else { @@ -857,7 +857,7 @@ namespace ResultsFramework { last = (result + 1).base(); } - print(outputFile, "{},", fmt::join(item.second.begin(), last, ",")); + print(outputFile, "{}", std::format("{}", EnergyPlus::join(std::ranges::subrange(item.second.begin(), last), ","))); print(outputFile, "{}\n", *last); } diff --git a/src/EnergyPlus/ZoneTempPredictorCorrector.cc b/src/EnergyPlus/ZoneTempPredictorCorrector.cc index cb0246b9987..40b463497ac 100644 --- a/src/EnergyPlus/ZoneTempPredictorCorrector.cc +++ b/src/EnergyPlus/ZoneTempPredictorCorrector.cc @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -6705,7 +6706,7 @@ void FillPredefinedTableOnThermostatSchedules(EnergyPlusData &state) }; using ControlTypeInfoMemPtr = std::string ControlTypeInfo::*; - // How many people on the EnergyPlus team understand this code? + // Traverses a vector of ControlTypeInfo and joins the values of the specified member pointer with a comma, skipping empty values auto joinStrings = [](const std::vector &infos, ControlTypeInfoMemPtr memPtr) -> std::string { std::vector result; result.reserve(infos.size()); @@ -6716,7 +6717,7 @@ void FillPredefinedTableOnThermostatSchedules(EnergyPlusData &state) } result.emplace_back(std::move(val)); } - return fmt::format("{}", fmt::join(result, ", ")); + return std::format("{}", EnergyPlus::join(result, ", ")); }; for (int idx = 1; idx <= state.dataZoneCtrls->NumTempControlledZones; ++idx) { diff --git a/tst/EnergyPlus/unit/CurveManager.unit.cc b/tst/EnergyPlus/unit/CurveManager.unit.cc index 76641ee3604..25055e11d01 100644 --- a/tst/EnergyPlus/unit/CurveManager.unit.cc +++ b/tst/EnergyPlus/unit/CurveManager.unit.cc @@ -55,9 +55,11 @@ #include #include #include +#include #include #include +#include #include #include "Fixtures/EnergyPlusFixture.hh" @@ -797,7 +799,7 @@ TEST_P(InputUnitTypeIsValid, IndepentVariable) " 0.714, !- Minimum Value", " 1.2857, !- Maximum Value", " , !- Normalization Reference Value", - fmt::format(" {}, !- Unit Type", unit_type), + std::format(" {}, !- Unit Type", unit_type), " , !- External File Name", " , !- External File Column Number", " , !- External File Starting Row Number", @@ -874,7 +876,7 @@ TEST_P(OutputUnitTypeIsValid, TableLookup) " , !- Normalization Divisor", " 0.8234, !- Minimum Output", " 1.1256, !- Maximum Output", - fmt::format(" {}, !- Output Unit Type", unit_type), + std::format(" {}, !- Output Unit Type", unit_type), " , !- External File Name", " , !- External File Column Number", " , !- External File Starting Row Number", @@ -934,8 +936,8 @@ TEST_F(EnergyPlusFixture, AllPossibleUnitTypeValid) // As of 2024-12-18 // in = ["", "Angle", "Dimensionless", "Distance", "MassFlow", "Power", "Pressure", "Temperature", "VolumetricFlow","VolumetricFlowPerPower"] // out = ["", "Capacity", "Dimensionless", "Power", "Pressure", "Temperature"] - EXPECT_FALSE(all_input_choices.empty()) << fmt::format("{}", all_input_choices); - EXPECT_FALSE(all_output_choices.empty()) << fmt::format("{}", all_output_choices); + EXPECT_FALSE(all_input_choices.empty()) << std::format("{}", all_input_choices); + EXPECT_FALSE(all_output_choices.empty()) << std::format("{}", all_output_choices); for (const auto &input_unit_type : all_input_choices) { EXPECT_TRUE(Curve::IsCurveInputTypeValid(input_unit_type)) << input_unit_type << " is rejected by IsCurveOutputTypeValid"; From 480b053b070c6f8f6d789004baed913b3de9ff7b Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 14:59:55 +0200 Subject: [PATCH 05/18] Replace fs::path formatter wiht a std::format one, same for PyStatus --- src/EnergyPlus/CommandLineInterface.cc | 15 +-- src/EnergyPlus/FileSystem.cc | 11 +- src/EnergyPlus/FileSystem.hh | 25 ++-- src/EnergyPlus/PluginManager.cc | 119 +++++++++--------- src/EnergyPlus/PythonEngine.cc | 71 +++++------ .../unit/CommandLineInterface.unit.cc | 2 +- 6 files changed, 112 insertions(+), 131 deletions(-) diff --git a/src/EnergyPlus/CommandLineInterface.cc b/src/EnergyPlus/CommandLineInterface.cc index 866a938470f..a10a8e24905 100644 --- a/src/EnergyPlus/CommandLineInterface.cc +++ b/src/EnergyPlus/CommandLineInterface.cc @@ -59,6 +59,7 @@ #include #include #include +#include #include #if LINK_WITH_PYTHON # include @@ -216,20 +217,20 @@ Built on Platform: {} bool debugCLI = std::any_of(args.begin(), args.end(), [](const auto &arg) { return arg == "--debug-cli"; }); if (debugCLI) { { - fmt::print("ProcessArgs: received args\n"); + std::print("ProcessArgs: received args\n"); int na = 0; for (const auto &a : args) { - fmt::print("* {}: '{}'\n", na++, a); + std::print("* {}: '{}'\n", na++, a); } } { - fmt::print("\nAfter massaging/expanding of args\n"); + std::print("\nAfter massaging/expanding of args\n"); int na = 0; for (const auto &a : arguments) { - fmt::print("* {}: '{}'\n", na++, a); + std::print("* {}: '{}'\n", na++, a); } } - fmt::print("\n"); + std::print("\n"); } // bool debugCLI = false; app.add_flag("--debug-cli", debugCLI, "Print the result of the CLI assignments to the console and exit")->group(""); // Empty group to hide it @@ -357,7 +358,7 @@ run_manager_from_cli() } if (debugCLI) { - fmt::print(stderr, + std::print(stderr, R"debug( state.dataGlobal->AnnualSimulation = {}, state.dataGlobal->DDOnlySimulation = {}, @@ -392,7 +393,7 @@ state.dataStrGlobals->inputFilePath='{:g}', state.files.inputWeatherFilePath.filePath, state.dataStrGlobals->inputFilePath); - fmt::print(stderr, "--debug-cli passed: exiting early\n"); + std::print(stderr, "--debug-cli passed: exiting early\n"); exit(0); } diff --git a/src/EnergyPlus/FileSystem.cc b/src/EnergyPlus/FileSystem.cc index a61213118ae..077bd1531c2 100644 --- a/src/EnergyPlus/FileSystem.cc +++ b/src/EnergyPlus/FileSystem.cc @@ -346,9 +346,8 @@ namespace FileSystem { std::string readFile(fs::path const &filePath, std::ios_base::openmode mode) { - // Shenanigans would not be needed with fmt 10+ (maybe earlier), because fmt has native fs::path support if (!fileExists(filePath)) { - throw FatalError(std::format("File does not exists: {}", filePath.string())); + throw FatalError(std::format("File does not exists: {}", filePath)); } // Can only be 'r', 'b' or 'rb' @@ -359,7 +358,7 @@ namespace FileSystem { const std::uintmax_t file_size = fs::file_size(filePath); std::ifstream file(filePath, mode); if (!file.is_open()) { - throw FatalError(std::format("Could not open file: {}", filePath.string())); + throw FatalError(std::format("Could not open file: {}", filePath)); } std::string result(file_size, '\0'); file.read(result.data(), file_size); @@ -368,10 +367,8 @@ namespace FileSystem { nlohmann::json readJSON(fs::path const &filePath, std::ios_base::openmode mode) { - - // Shenanigans would not be needed with fmt 10+ (maybe earlier), because fmt has native fs::path support if (!fileExists(filePath)) { - throw FatalError(std::format("File does not exists: {}", filePath.string())); + throw FatalError(std::format("File does not exists: {}", filePath)); } // Can only be 'r', 'b' or 'rb' @@ -381,7 +378,7 @@ namespace FileSystem { std::ifstream file(filePath, mode); if (!file.is_open()) { - throw FatalError(std::format("Could not open file: {}", filePath.string())); + throw FatalError(std::format("Could not open file: {}", filePath)); } FileTypes const ext = getFileType(filePath); diff --git a/src/EnergyPlus/FileSystem.hh b/src/EnergyPlus/FileSystem.hh index 3d1ebcdcf5b..a518d93668a 100644 --- a/src/EnergyPlus/FileSystem.hh +++ b/src/EnergyPlus/FileSystem.hh @@ -68,7 +68,6 @@ namespace fs = std::experimental::filesystem; // #include #include #include -#include #include // EnergyPlus Headers @@ -316,19 +315,22 @@ namespace FileSystem { } // namespace FileSystem } // namespace EnergyPlus -// Add a custom formatter for fmt -template <> struct fmt::formatter +#if __cpp_lib_format_path >= 202403L +# error \ + "std::formatter specialization for std::filesystem::path is available in the STL, so the custom specialization in FileSystem.hh should be removed" +#endif +template <> struct std::formatter { - // Presentation format: 's' - string, 'g' - generic_string. - char presentation = 's'; + bool generic_string = false; - // Parses format specifications of the form ['s' | 'g']. - constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) + // parse is inherited from formatter. + constexpr auto parse(std::format_parse_context &ctx) -> std::format_parse_context::iterator { // Parse the presentation format and store it in the formatter: - auto it = ctx.begin(), end = ctx.end(); + auto it = ctx.begin(); + auto end = ctx.end(); if (it != end && (*it == 's' || *it == 'g')) { - presentation = *it++; + generic_string = (*it++) == 'g'; } // Check if reached the end of the range: @@ -340,10 +342,9 @@ template <> struct fmt::formatter return it; } - template auto format(const fs::path &p, FormatContext &ctx) -> decltype(ctx.out()) + auto format(const fs::path &p, std::format_context &ctx) const -> std::format_context::iterator { - return fmt::format_to( - ctx.out(), "{}", presentation == 'g' ? EnergyPlus::FileSystem::toGenericString(p) : EnergyPlus::FileSystem::toString(p)); + return std::format_to(ctx.out(), "{}", generic_string ? EnergyPlus::FileSystem::toGenericString(p) : EnergyPlus::FileSystem::toString(p)); } }; diff --git a/src/EnergyPlus/PluginManager.cc b/src/EnergyPlus/PluginManager.cc index 3171bc334cc..98547e961ce 100644 --- a/src/EnergyPlus/PluginManager.cc +++ b/src/EnergyPlus/PluginManager.cc @@ -64,49 +64,49 @@ #include #include -// Third Party Headers +#include + +// EnergyPlus Headers +#include +#include +#include +#include +#include +#include +#include +#include +#include + #if LINK_WITH_PYTHON -# include -template <> struct fmt::formatter +template <> struct std::formatter { // parse is inherited from formatter. - static constexpr auto parse(const format_parse_context &ctx) -> format_parse_context::iterator + constexpr auto parse(std::format_parse_context &ctx) -> std::format_parse_context::iterator { return ctx.begin(); } - static auto format(const PyStatus &status, format_context &ctx) -> format_context::iterator + auto format(const PyStatus &status, std::format_context &ctx) const -> std::format_context::iterator { if (PyStatus_Exception(status) == 0) { return ctx.out(); } if (PyStatus_IsExit(status) != 0) { - return fmt::format_to(ctx.out(), "Exited with code {}", status.exitcode); + return std::format_to(ctx.out(), "Exited with code {}", status.exitcode); } if (PyStatus_IsError(status) != 0) { auto it = ctx.out(); - it = fmt::format_to(it, "Fatal Python error: "); + it = std::format_to(it, "Fatal Python error: "); if (status.func != nullptr) { - it = fmt::format_to(it, "{}: ", status.func); + it = std::format_to(it, "{}: ", status.func); } - it = fmt::format_to(it, "{}", status.err_msg); + it = std::format_to(it, "{}", status.err_msg); return it; } return ctx.out(); } -}; // namespace fmt +}; #endif -#include - -// EnergyPlus Headers -#include -#include -#include -#include -#include -#include -#include -#include namespace EnergyPlus::PluginManagement { @@ -200,8 +200,7 @@ void PluginManager::setupOutputVariables([[maybe_unused]] EnergyPlusData &state) if (outputVarInstances > 0) { auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(sOutputVariable); if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) { - ShowSevereError(state, - EnergyPlus::format("{}: Somehow getNumObjectsFound was > 0 but epJSON.find found 0", sOutputVariable)); // LCOV_EXCL_LINE + ShowSevereError(state, std::format("{}: Somehow getNumObjectsFound was > 0 but epJSON.find found 0", sOutputVariable)); // LCOV_EXCL_LINE } auto &instancesValue = instances.value(); for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) { @@ -222,7 +221,7 @@ void PluginManager::setupOutputVariables([[maybe_unused]] EnergyPlusData &state) int variableHandle = EnergyPlus::PluginManagement::PluginManager::getGlobalVariableHandle(state, varName); if (variableHandle == -1) { ShowSevereError(state, "Failed to match Python Plugin Output Variable"); - ShowContinueError(state, EnergyPlus::format("Trying to create output instance for variable name \"{}\"", varName)); + ShowContinueError(state, std::format("Trying to create output instance for variable name \"{}\"", varName)); ShowContinueError(state, "No match found, make sure variable is listed in PythonPlugin:Variables object"); ShowFatalError(state, "Python Plugin Output Variable problem causes program termination"); } @@ -278,7 +277,7 @@ void PluginManager::setupOutputVariables([[maybe_unused]] EnergyPlusData &state) // We are doing a metered type, we need to get the extra stuff // Resource Type if (fields.find("resource_type") == fields.end()) { - ShowSevereError(state, EnergyPlus::format("Input error on PythonPlugin:OutputVariable = {}", thisObjectName)); + ShowSevereError(state, std::format("Input error on PythonPlugin:OutputVariable = {}", thisObjectName)); ShowContinueError(state, "The variable was marked as metered, but did not define a resource type"); ShowContinueError(state, "For metered variables, the resource type, group type, and end use category must be defined"); ShowFatalError(state, "Input error on PythonPlugin:OutputVariable causes program termination"); @@ -305,14 +304,13 @@ void PluginManager::setupOutputVariables([[maybe_unused]] EnergyPlusData &state) resource = Constant::eResource::SolarAir; } else if ((resource = static_cast(getEnumValue(Constant::eResourceNamesUC, resourceType))) == Constant::eResource::Invalid) { - ShowSevereError(state, - EnergyPlus::format("Invalid input for PythonPlugin:OutputVariable, unexpected Resource Type = {}", resourceType)); + ShowSevereError(state, std::format("Invalid input for PythonPlugin:OutputVariable, unexpected Resource Type = {}", resourceType)); ShowFatalError(state, "Python plugin output variable input problem causes program termination"); } // Group Type if (fields.find("group_type") == fields.end()) { - ShowSevereError(state, EnergyPlus::format("Input error on PythonPlugin:OutputVariable = {}", thisObjectName)); + ShowSevereError(state, std::format("Input error on PythonPlugin:OutputVariable = {}", thisObjectName)); ShowContinueError(state, "The variable was marked as metered, but did not define a group type"); ShowContinueError(state, "For metered variables, the resource type, group type, and end use category must be defined"); ShowFatalError(state, "Input error on PythonPlugin:OutputVariable causes program termination"); @@ -320,14 +318,13 @@ void PluginManager::setupOutputVariables([[maybe_unused]] EnergyPlusData &state) std::string const groupType = EnergyPlus::Util::makeUPPER(fields.at("group_type").get()); auto group = static_cast(getEnumValue(OutputProcessor::groupNamesUC, groupType)); if (group == OutputProcessor::Group::Invalid) { - ShowSevereError(state, - EnergyPlus::format("Invalid input for PythonPlugin:OutputVariable, unexpected Group Type = {}", groupType)); + ShowSevereError(state, std::format("Invalid input for PythonPlugin:OutputVariable, unexpected Group Type = {}", groupType)); ShowFatalError(state, "Python plugin output variable input problem causes program termination"); } // End Use Type if (fields.find("end_use_category") == fields.end()) { - ShowSevereError(state, EnergyPlus::format("Input error on PythonPlugin:OutputVariable = {}", thisObjectName)); + ShowSevereError(state, std::format("Input error on PythonPlugin:OutputVariable = {}", thisObjectName)); ShowContinueError(state, "The variable was marked as metered, but did not define an end-use category"); ShowContinueError(state, "For metered variables, the resource type, group type, and end use category must be defined"); ShowFatalError(state, "Input error on PythonPlugin:OutputVariable causes program termination"); @@ -336,8 +333,7 @@ void PluginManager::setupOutputVariables([[maybe_unused]] EnergyPlusData &state) auto endUseCat = static_cast(getEnumValue(OutputProcessor::endUseCatNamesUC, endUse)); if (endUseCat == OutputProcessor::EndUseCat::Invalid) { - ShowSevereError(state, - EnergyPlus::format("Invalid input for PythonPlugin:OutputVariable, unexpected End-use Subcategory = {}", endUse)); + ShowSevereError(state, std::format("Invalid input for PythonPlugin:OutputVariable, unexpected End-use Subcategory = {}", endUse)); ShowFatalError(state, "Python plugin output variable input problem causes program termination"); } @@ -347,9 +343,8 @@ void PluginManager::setupOutputVariables([[maybe_unused]] EnergyPlusData &state) endUseCat == OutputProcessor::EndUseCat::Chillers || endUseCat == OutputProcessor::EndUseCat::Boilers || endUseCat == OutputProcessor::EndUseCat::Baseboard || endUseCat == OutputProcessor::EndUseCat::HeatRecoveryForCooling || endUseCat == OutputProcessor::EndUseCat::HeatRecoveryForHeating)) { - ShowWarningError(state, - EnergyPlus::format("Inconsistent resource type input for PythonPlugin:OutputVariable = {}", thisObjectName)); - ShowContinueError(state, EnergyPlus::format("For end use subcategory = {}, resource type must be EnergyTransfer", endUse)); + ShowWarningError(state, std::format("Inconsistent resource type input for PythonPlugin:OutputVariable = {}", thisObjectName)); + ShowContinueError(state, std::format("For end use subcategory = {}, resource type must be EnergyTransfer", endUse)); ShowContinueError(state, "Resource type is being reset to EnergyTransfer and the simulation continues..."); resource = Constant::eResource::EnergyTransfer; } @@ -403,7 +398,7 @@ void initPython(EnergyPlusData &state, fs::path const &pathToPythonPackages) preConfig.utf8_mode = 1; status = Py_PreInitialize(&preConfig); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not pre-initialize Python to speak UTF-8... {}", status)); + ShowFatalError(state, std::format("Could not pre-initialize Python to speak UTF-8... {}", status)); } PyConfig config; @@ -412,12 +407,12 @@ void initPython(EnergyPlusData &state, fs::path const &pathToPythonPackages) status = PyConfig_SetBytesString(&config, &config.program_name, PluginManagement::programName); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not initialize program_name on PyConfig... {}", status)); + ShowFatalError(state, std::format("Could not initialize program_name on PyConfig... {}", status)); } status = PyConfig_Read(&config); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not read back the PyConfig... {}", status)); + ShowFatalError(state, std::format("Could not read back the PyConfig... {}", status)); } // ReSharper disable once CppRedundantTypenameKeyword @@ -429,16 +424,16 @@ void initPython(EnergyPlusData &state, fs::path const &pathToPythonPackages) status = PyConfig_SetString(&config, &config.home, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not set home to {:g} on PyConfig... {}", pathToPythonPackages, status)); + ShowFatalError(state, std::format("Could not set home to {:g} on PyConfig... {}", pathToPythonPackages, status)); } status = PyConfig_SetString(&config, &config.base_prefix, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not set base_prefix to {:g} on PyConfig... {}", pathToPythonPackages, status)); + ShowFatalError(state, std::format("Could not set base_prefix to {:g} on PyConfig... {}", pathToPythonPackages, status)); } config.module_search_paths_set = 1; status = PyWideStringList_Append(&config.module_search_paths, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not add {:g} to module_search_paths on PyConfig... {}", pathToPythonPackages, status)); + ShowFatalError(state, std::format("Could not add {:g} to module_search_paths on PyConfig... {}", pathToPythonPackages, status)); } } else { @@ -449,16 +444,16 @@ void initPython(EnergyPlusData &state, fs::path const &pathToPythonPackages) status = PyConfig_SetString(&config, &config.home, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not set home to {:g} on PyConfig... {}", pathToPythonPackages, status)); + ShowFatalError(state, std::format("Could not set home to {:g} on PyConfig... {}", pathToPythonPackages, status)); } status = PyConfig_SetString(&config, &config.base_prefix, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not set base_prefix to {:g} on PyConfig... {}", pathToPythonPackages, status)); + ShowFatalError(state, std::format("Could not set base_prefix to {:g} on PyConfig... {}", pathToPythonPackages, status)); } config.module_search_paths_set = 1; status = PyWideStringList_Append(&config.module_search_paths, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not add {:g} to module_search_paths on PyConfig... {}", pathToPythonPackages, status)); + ShowFatalError(state, std::format("Could not add {:g} to module_search_paths on PyConfig... {}", pathToPythonPackages, status)); } PyMem_RawFree(wcharPath); @@ -652,7 +647,7 @@ PluginManager::PluginManager(EnergyPlusData &state) : eplusRunningViaPythonAPI(s if (globalVarInstances > 0) { auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(sGlobals); if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) { - ShowSevereError(state, EnergyPlus::format("{}: Somehow getNumObjectsFound was > 0 but epJSON.find found 0", sGlobals)); // LCOV_EXCL_LINE + ShowSevereError(state, std::format("{}: Somehow getNumObjectsFound was > 0 but epJSON.find found 0", sGlobals)); // LCOV_EXCL_LINE } std::set uniqueNames; auto &instancesValue = instances.value(); @@ -668,7 +663,7 @@ PluginManager::PluginManager(EnergyPlusData &state) : eplusRunningViaPythonAPI(s uniqueNames.insert(varNameToAdd); } else { ShowWarningMessage( - state, EnergyPlus::format("Found duplicate variable name in PythonPLugin:Variables objects, ignoring: \"{}\"", varNameToAdd)); + state, std::format("Found duplicate variable name in PythonPLugin:Variables objects, ignoring: \"{}\"", varNameToAdd)); } } } @@ -693,7 +688,7 @@ PluginManager::PluginManager(EnergyPlusData &state) : eplusRunningViaPythonAPI(s if (trendInstances > 0) { auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(sTrends); if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) { - ShowSevereError(state, EnergyPlus::format("{}: Somehow getNumObjectsFound was > 0 but epJSON.find found 0", sTrends)); // LCOV_EXCL_LINE + ShowSevereError(state, std::format("{}: Somehow getNumObjectsFound was > 0 but epJSON.find found 0", sTrends)); // LCOV_EXCL_LINE } auto &instancesValue = instances.value(); for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) { @@ -795,7 +790,7 @@ void PluginInstance::reportPythonError([[maybe_unused]] EnergyPlusData &state) if (!traceback_line.empty() && traceback_line[traceback_line.length() - 1] == '\n') { traceback_line.erase(traceback_line.length() - 1); } - ShowContinueError(state, EnergyPlus::format(" >>> {}", traceback_line)); + ShowContinueError(state, std::format(" >>> {}", traceback_line)); } // PyList_GetItem returns a borrowed reference, do not decrement } @@ -826,14 +821,14 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) pModuleName = PyUnicode_FromString(s.c_str()); // New reference } if (pModuleName == nullptr) { - ShowFatalError(state, EnergyPlus::format("Failed to convert the Module Path \"{:g}\" for import", this->modulePath)); + ShowFatalError(state, std::format("Failed to convert the Module Path \"{:g}\" for import", this->modulePath)); } this->pModule = PyImport_Import(pModuleName); Py_DECREF(pModuleName); if (this->pModule == nullptr) { - ShowSevereError(state, EnergyPlus::format("Failed to import module \"{:g}\"", this->modulePath)); - ShowContinueError(state, EnergyPlus::format("Current sys.path={}", PluginManager::currentPythonPath())); + ShowSevereError(state, std::format("Failed to import module \"{:g}\"", this->modulePath)); + ShowContinueError(state, std::format("Current sys.path={}", PluginManager::currentPythonPath())); // ONLY call PyErr_Print if PyErr has occurred, otherwise it will cause other problems if (PyErr_Occurred() != nullptr) { reportPythonError(state); @@ -844,7 +839,7 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) } PyObject *pModuleDict = PyModule_GetDict(this->pModule); if (pModuleDict == nullptr) { - ShowSevereError(state, EnergyPlus::format("Failed to read module dictionary from module \"{:g}\"", this->modulePath)); + ShowSevereError(state, std::format("Failed to read module dictionary from module \"{:g}\"", this->modulePath)); if (PyErr_Occurred() != nullptr) { reportPythonError(state); } else { @@ -861,12 +856,12 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) } else { const char *zStr = PyUnicode_AsUTF8(pFullPath); std::string sHere(zStr); - ShowMessage(state, EnergyPlus::format("PythonPlugin: Class {} imported from: {}", className, sHere)); + ShowMessage(state, std::format("PythonPlugin: Class {} imported from: {}", className, sHere)); } PyObject *pClass = PyDict_GetItemString(pModuleDict, className.c_str()); // Py_DECREF(pModuleDict); // PyModule_GetDict returns a borrowed reference, DO NOT decrement if (pClass == nullptr) { - ShowSevereError(state, EnergyPlus::format(R"(Failed to get class type "{}" from module "{:g}")", className, modulePath)); + ShowSevereError(state, std::format(R"(Failed to get class type "{}" from module "{:g}")", className, modulePath)); if (PyErr_Occurred() != nullptr) { reportPythonError(state); } else { @@ -875,7 +870,7 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) ShowFatalError(state, "Python class import error causes program termination"); } if (PyCallable_Check(pClass) == 0) { - ShowSevereError(state, EnergyPlus::format("Got class type \"{}\", but it cannot be called/instantiated", className)); + ShowSevereError(state, std::format("Got class type \"{}\", but it cannot be called/instantiated", className)); if (PyErr_Occurred() != nullptr) { reportPythonError(state); } else { @@ -886,7 +881,7 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) this->pClassInstance = PyObject_CallObject(pClass, nullptr); // Py_DECREF(pClass); // PyDict_GetItemString returns a borrowed reference, DO NOT decrement if (this->pClassInstance == nullptr) { - ShowSevereError(state, EnergyPlus::format("Something went awry calling class constructor for class \"{}\"", className)); + ShowSevereError(state, std::format("Something went awry calling class constructor for class \"{}\"", className)); if (PyErr_Occurred() != nullptr) { reportPythonError(state); } else { @@ -905,7 +900,7 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) if ((detectFunction == nullptr) || (PyCallable_Check(detectFunction) == 0)) { ShowSevereError( state, - EnergyPlus::format( + std::format( R"(Could not find or call function "{}" on class "{:g}.{}")", detectOverriddenFunctionName, this->modulePath, this->className)); if (PyErr_Occurred() != nullptr) { reportPythonError(state); @@ -917,7 +912,7 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) PyObject *pFunctionResponse = PyObject_CallFunction(detectFunction, nullptr); Py_DECREF(detectFunction); // PyObject_GetAttrString returns a new reference, decrement it if (pFunctionResponse == nullptr) { - ShowSevereError(state, EnergyPlus::format("Call to _detect_overridden() on {} failed!", this->stringIdentifier)); + ShowSevereError(state, std::format("Call to _detect_overridden() on {} failed!", this->stringIdentifier)); if (PyErr_Occurred() != nullptr) { reportPythonError(state); } else { @@ -1246,7 +1241,7 @@ void PluginManager::addToPythonPath(EnergyPlusData &state, const fs::path &inclu unicodeIncludePath = PyUnicode_FromString(s.c_str()); // New reference } if (unicodeIncludePath == nullptr) { - ShowFatalError(state, EnergyPlus::format("ERROR converting the path \"{:g}\" for addition to the sys.path in Python", includePath)); + ShowFatalError(state, std::format("ERROR converting the path \"{:g}\" for addition to the sys.path in Python", includePath)); } PyObject *sysPath = PySys_GetObject("path"); // Borrowed reference @@ -1257,11 +1252,11 @@ void PluginManager::addToPythonPath(EnergyPlusData &state, const fs::path &inclu if (PyErr_Occurred() != nullptr) { PluginInstance::reportPythonError(state); } - ShowFatalError(state, EnergyPlus::format("ERROR adding \"{:g}\" to the sys.path in Python", includePath)); + ShowFatalError(state, std::format("ERROR adding \"{:g}\" to the sys.path in Python", includePath)); } if (userDefinedPath) { - ShowMessage(state, EnergyPlus::format("Successfully added path \"{:g}\" to the sys.path in Python", includePath)); + ShowMessage(state, std::format("Successfully added path \"{:g}\" to the sys.path in Python", includePath)); } // PyRun_SimpleString)("print(' EPS : ' + str(sys.path))"); diff --git a/src/EnergyPlus/PythonEngine.cc b/src/EnergyPlus/PythonEngine.cc index fc747b7abc0..2c6d73c1ea6 100644 --- a/src/EnergyPlus/PythonEngine.cc +++ b/src/EnergyPlus/PythonEngine.cc @@ -61,21 +61,26 @@ #endif // C++ Headers +#include #include -// Third Party Headers +// EnergyPlus Headers +#include +#include +#include +#include +#include + #if LINK_WITH_PYTHON -# include -namespace fmt { -template <> struct formatter +template <> struct std::formatter { // parse is inherited from formatter. - constexpr auto parse(format_parse_context &ctx) -> format_parse_context::iterator + constexpr auto parse(std::format_parse_context &ctx) -> std::format_parse_context::iterator { return ctx.begin(); } - auto format(const PyStatus &status, format_context &ctx) const -> format_context::iterator + auto format(const PyStatus &status, std::format_context &ctx) const -> std::format_context::iterator { if (PyStatus_Exception(status) == 0) { return ctx.out(); @@ -95,16 +100,8 @@ template <> struct formatter return ctx.out(); } }; -} // namespace fmt - #endif -// EnergyPlus Headers -#include -#include -#include -#include - namespace EnergyPlus { namespace Python { @@ -170,7 +167,7 @@ namespace Python { if (!traceback_line.empty() && traceback_line[traceback_line.length() - 1] == '\n') { traceback_line.erase(traceback_line.length() - 1); } - EnergyPlus::ShowContinueError(state, EnergyPlus::format(" >>> {}", traceback_line)); + EnergyPlus::ShowContinueError(state, std::format(" >>> {}", traceback_line)); } // PyList_GetItem returns a borrowed reference, do not decrement } @@ -201,8 +198,7 @@ namespace Python { unicodeIncludePath = PyUnicode_FromString(s.c_str()); // New reference } if (unicodeIncludePath == nullptr) { - EnergyPlus::ShowFatalError( - state, EnergyPlus::format("ERROR converting the path \"{}\" for addition to the sys.path in Python", includePath.generic_string())); + EnergyPlus::ShowFatalError(state, std::format("ERROR converting the path \"{:g}\" for addition to the sys.path in Python", includePath)); } PyObject *sysPath = PySys_GetObject("path"); // Borrowed reference @@ -213,12 +209,11 @@ namespace Python { if (PyErr_Occurred() != nullptr) { reportPythonError(state); } - EnergyPlus::ShowFatalError(state, EnergyPlus::format("ERROR adding \"{}\" to the sys.path in Python", includePath.generic_string())); + EnergyPlus::ShowFatalError(state, std::format("ERROR adding \"{:g}\" to the sys.path in Python", includePath)); } if (userDefinedPath) { - EnergyPlus::ShowMessage(state, - EnergyPlus::format("Successfully added path \"{}\" to the sys.path in Python", includePath.generic_string())); + EnergyPlus::ShowMessage(state, std::format("Successfully added path \"{:g}\" to the sys.path in Python", includePath)); } // PyRun_SimpleString)("print(' EPS : ' + str(sys.path))"); @@ -237,7 +232,7 @@ namespace Python { preConfig.utf8_mode = 1; status = Py_PreInitialize(&preConfig); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not pre-initialize Python to speak UTF-8... {}", status)); + ShowFatalError(state, std::format("Could not pre-initialize Python to speak UTF-8... {}", status)); } PyConfig config; @@ -246,12 +241,12 @@ namespace Python { status = PyConfig_SetBytesString(&config, &config.program_name, PluginManagement::programName); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not initialize program_name on PyConfig... {}", status)); + ShowFatalError(state, std::format("Could not initialize program_name on PyConfig... {}", status)); } status = PyConfig_Read(&config); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, EnergyPlus::format("Could not read back the PyConfig... {}", status)); + ShowFatalError(state, std::format("Could not read back the PyConfig... {}", status)); } if constexpr (std::is_same_v) { @@ -261,20 +256,16 @@ namespace Python { status = PyConfig_SetString(&config, &config.home, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, - EnergyPlus::format("Could not set home to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, std::format("Could not set home to {:g} on PyConfig... {}", pathToPythonPackages, status)); } status = PyConfig_SetString(&config, &config.base_prefix, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError( - state, EnergyPlus::format("Could not set base_prefix to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, std::format("Could not set base_prefix to {:g} on PyConfig... {}", pathToPythonPackages, status)); } config.module_search_paths_set = 1; status = PyWideStringList_Append(&config.module_search_paths, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError( - state, - EnergyPlus::format("Could not add {} to module_search_paths on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, std::format("Could not add {:g} to module_search_paths on PyConfig... {}", pathToPythonPackages, status)); } } else { @@ -285,20 +276,16 @@ namespace Python { status = PyConfig_SetString(&config, &config.home, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError(state, - EnergyPlus::format("Could not set home to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, std::format("Could not set home to {:g} on PyConfig... {}", pathToPythonPackages, status)); } status = PyConfig_SetString(&config, &config.base_prefix, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError( - state, EnergyPlus::format("Could not set base_prefix to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, std::format("Could not set base_prefix to {:g} on PyConfig... {}", pathToPythonPackages, status)); } config.module_search_paths_set = 1; status = PyWideStringList_Append(&config.module_search_paths, wcharPath); if (PyStatus_Exception(status) != 0) { - ShowFatalError( - state, - EnergyPlus::format("Could not add {} to module_search_paths on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, std::format("Could not add {:g} to module_search_paths on PyConfig... {}", pathToPythonPackages, status)); } PyMem_RawFree(wcharPath); @@ -384,7 +371,7 @@ sys.argv.append("energyplus") fs::path const pathToPythonPackages = programDir / "python_lib"; std::string sPathToPythonPackages = std::string(pathToPythonPackages.string()); std::replace(sPathToPythonPackages.begin(), sPathToPythonPackages.end(), '\\', '/'); - cmd += EnergyPlus::format("sys.path.insert(0, \"{}\")\n", sPathToPythonPackages); + cmd += std::format("sys.path.insert(0, \"{}\")\n", sPathToPythonPackages); return cmd; } @@ -395,13 +382,13 @@ sys.argv.clear() sys.argv.append("energyplus") )python"; for (const auto &arg : python_fwd_args) { - cmd += EnergyPlus::format("sys.argv.append(\"{}\")\n", arg); + cmd += std::format("sys.argv.append(\"{}\")\n", arg); } fs::path programDir = FileSystem::getParentDirectoryPath(FileSystem::getAbsolutePath(FileSystem::getProgramPath())); fs::path const pathToPythonPackages = programDir / "python_lib"; std::string sPathToPythonPackages = std::string(pathToPythonPackages.string()); std::replace(sPathToPythonPackages.begin(), sPathToPythonPackages.end(), '\\', '/'); - cmd += EnergyPlus::format("sys.path.insert(0, \"{}\")\n", sPathToPythonPackages); + cmd += std::format("sys.path.insert(0, \"{}\")\n", sPathToPythonPackages); std::string tclConfigDir; std::string tkConfigDir; for (auto &p : std::filesystem::directory_iterator(pathToPythonPackages)) { @@ -419,8 +406,8 @@ sys.argv.append("energyplus") } } cmd += "from os import environ\n"; - cmd += EnergyPlus::format("environ[\'TCL_LIBRARY\'] = \"{}/{}\"\n", sPathToPythonPackages, tclConfigDir); - cmd += EnergyPlus::format("environ[\'TK_LIBRARY\'] = \"{}/{}\"\n", sPathToPythonPackages, tkConfigDir); + cmd += std::format("environ[\'TCL_LIBRARY\'] = \"{}/{}\"\n", sPathToPythonPackages, tclConfigDir); + cmd += std::format("environ[\'TK_LIBRARY\'] = \"{}/{}\"\n", sPathToPythonPackages, tkConfigDir); return cmd; } diff --git a/tst/EnergyPlus/unit/CommandLineInterface.unit.cc b/tst/EnergyPlus/unit/CommandLineInterface.unit.cc index c61805b6b2f..2bc2e19b8e4 100644 --- a/tst/EnergyPlus/unit/CommandLineInterface.unit.cc +++ b/tst/EnergyPlus/unit/CommandLineInterface.unit.cc @@ -271,7 +271,7 @@ TEST_F(CommandLineInterfaceFixture, IdfDoesNotExist) EXPECT_EQ(static_cast(ReturnCodes::Failure), exitcode); compare_cout_stream(""); compare_cerr_stream(delimited_string({ - fmt::format("input_file: File does not exist: {}", expectedParams.inputFilePath.generic_string()), + std::format("input_file: File does not exist: {:g}", expectedParams.inputFilePath), "Run with --help for more information.", })); } From 56789849927344cc9f3c5d03a2f59ba05b92200d Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 15:01:07 +0200 Subject: [PATCH 06/18] Add Formatters.hh to the PCH --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d0166b7f47..3f47abf2c41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,8 @@ set(EP_CXX_PCH_HEADERS "$<$:${PROJECT_SOURCE_DIR}/src/EnergyPlus/Data/EnergyPlusData.hh>" "$<$:${PROJECT_SOURCE_DIR}/third_party/ObjexxFCL/src/ObjexxFCL/Array.functions.hh>" "$<$:${PROJECT_SOURCE_DIR}/third_party/ObjexxFCL/src/ObjexxFCL/Array1D.hh>" - "$<$:${PROJECT_SOURCE_DIR}/third_party/nlohmann/json.hpp>") + "$<$:${PROJECT_SOURCE_DIR}/third_party/nlohmann/json.hpp>" + "$<$:${PROJECT_SOURCE_DIR}/src/EnergyPlus/Formatters.hh>") set(EP_TEST_CXX_PCH_HEADERS ${EP_CXX_PCH_HEADERS} "$<$:>" From 24c479f63e91257e2c58b3a903ef0f29aff83fba Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 18:19:08 +0200 Subject: [PATCH 07/18] Use the fs::path formatter everywhere I used a Clang LibTooling-based refactoring tool that I created to do so: https://github.com/jmarrec/EnergyPlus-fmt-clang-refactoring/blob/main/path_format_fixer.cpp --- src/EnergyPlus/ChillerElectricASHRAE205.cc | 2 +- .../CoilCoolingDXAshrae205Performance.cc | 2 +- src/EnergyPlus/CommandLineInterface.cc | 34 ++++++++----------- src/EnergyPlus/CurveManager.cc | 25 ++++++-------- src/EnergyPlus/DataSystemVariables.cc | 4 +-- src/EnergyPlus/ExternalInterface.cc | 2 +- src/EnergyPlus/HeatBalanceManager.cc | 6 ++-- src/EnergyPlus/IOFiles.cc | 4 +-- .../InputProcessing/InputProcessor.cc | 2 +- src/EnergyPlus/OutputProcessor.cc | 6 ++-- src/EnergyPlus/OutputReportTabular.cc | 2 +- src/EnergyPlus/ScheduleManager.cc | 24 ++++++------- src/EnergyPlus/SimulationManager.cc | 4 +-- src/EnergyPlus/SolarShading.cc | 6 ++-- src/EnergyPlus/UtilityRoutines.cc | 12 +++---- src/EnergyPlus/WeatherManager.cc | 14 ++++---- src/EnergyPlus/ZoneTempPredictorCorrector.cc | 2 +- 17 files changed, 71 insertions(+), 80 deletions(-) diff --git a/src/EnergyPlus/ChillerElectricASHRAE205.cc b/src/EnergyPlus/ChillerElectricASHRAE205.cc index 52907894adb..bb008a1116c 100644 --- a/src/EnergyPlus/ChillerElectricASHRAE205.cc +++ b/src/EnergyPlus/ChillerElectricASHRAE205.cc @@ -159,7 +159,7 @@ void getChillerASHRAE205Input(EnergyPlusData &state) thisChiller.Representation = std::dynamic_pointer_cast( RSInstanceFactory::create("RS0001", FileSystem::toString(rep_file_path).c_str(), std::make_shared())); if (nullptr == thisChiller.Representation) { - ShowSevereError(state, std::format("{} is not an instance of an ASHRAE205 Chiller.", rep_file_path.string())); + ShowSevereError(state, std::format("{} is not an instance of an ASHRAE205 Chiller.", rep_file_path)); ErrorsFound = true; } thisChiller.Representation->performance.performance_map_cooling.get_logger()->set_message_context(&thisChiller.LoggerContext); diff --git a/src/EnergyPlus/Coils/CoilCoolingDXAshrae205Performance.cc b/src/EnergyPlus/Coils/CoilCoolingDXAshrae205Performance.cc index fa3728e82af..4fae1106ec8 100644 --- a/src/EnergyPlus/Coils/CoilCoolingDXAshrae205Performance.cc +++ b/src/EnergyPlus/Coils/CoilCoolingDXAshrae205Performance.cc @@ -115,7 +115,7 @@ CoilCoolingDX205Performance::CoilCoolingDX205Performance(EnergyPlus::EnergyPlusD representation = std::dynamic_pointer_cast(RSInstanceFactory::create("RS0004", rep_file_path.string().c_str(), coil_logger)); if (nullptr == representation) { - ShowSevereError(state, std::format("{} is not an instance of an ASHRAE205 Coil.", rep_file_path.string())); + ShowSevereError(state, std::format("{} is not an instance of an ASHRAE205 Coil.", rep_file_path)); errorsFound = true; } else { representation->performance.performance_map_cooling.get_logger()->set_message_context(&logger_context); diff --git a/src/EnergyPlus/CommandLineInterface.cc b/src/EnergyPlus/CommandLineInterface.cc index a10a8e24905..afd8c76ee61 100644 --- a/src/EnergyPlus/CommandLineInterface.cc +++ b/src/EnergyPlus/CommandLineInterface.cc @@ -297,10 +297,10 @@ main([)python"; bool eplus_dir_provided = std::any_of(fwd_args.begin(), fwd_args.end(), [](const std::string &a) { return a == "-e" || a == "--eplus-dir"; }); if (!eplus_dir_provided) { - cmd += EnergyPlus::format(R"("--eplus-dir", "{}", )", state.dataStrGlobals->exeDirectoryPath.generic_string()); + cmd += std::format(R"("--eplus-dir", "{:g}", )", state.dataStrGlobals->exeDirectoryPath); } for (const auto &arg : fwd_args) { - cmd += EnergyPlus::format("\"{}\", ", arg); + cmd += std::format("\"{}\", ", arg); } } cmd += "])\n"; @@ -430,8 +430,7 @@ state.dataStrGlobals->inputFilePath='{:g}', break; default: DisplayString(state, - std::format("ERROR: Input file must have IDF, IMF, or epJSON extension: {}", - state.dataStrGlobals->inputFilePath.generic_string())); + std::format("ERROR: Input file must have IDF, IMF, or epJSON extension: {:g}", state.dataStrGlobals->inputFilePath)); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); } @@ -641,7 +640,7 @@ state.dataStrGlobals->inputFilePath='{:g}', if (FileSystem::fileExists(state.files.iniFile.filePath)) { EnergyPlus::InputFile iniFile = state.files.iniFile.try_open(); if (!iniFile.good()) { - DisplayString(state, std::format("ERROR: Could not open file {} for input (read).", iniFile.filePath.string())); + DisplayString(state, std::format("ERROR: Could not open file {} for input (read).", iniFile.filePath)); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); } @@ -669,8 +668,7 @@ state.dataStrGlobals->inputFilePath='{:g}', // Check if specified files exist if (!FileSystem::fileExists(state.dataStrGlobals->inputFilePath)) { DisplayString( - state, - std::format("ERROR: Could not find input data file: {}.", FileSystem::getAbsolutePath(state.dataStrGlobals->inputFilePath).string())); + state, std::format("ERROR: Could not find input data file: {}.", FileSystem::getAbsolutePath(state.dataStrGlobals->inputFilePath))); DisplayString(state, errorFollowUp); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); @@ -680,9 +678,9 @@ state.dataStrGlobals->inputFilePath='{:g}', if ((weatherPathOpt->count() > 0) && !state.dataGlobal->DDOnlySimulation) { if (!FileSystem::fileExists(state.files.inputWeatherFilePath.filePath)) { - DisplayString(state, - std::format("ERROR: Could not find weather file: {}.", - FileSystem::getAbsolutePath(state.files.inputWeatherFilePath.filePath).string())); + DisplayString( + state, + std::format("ERROR: Could not find weather file: {}.", FileSystem::getAbsolutePath(state.files.inputWeatherFilePath.filePath))); DisplayString(state, errorFollowUp); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); @@ -697,7 +695,7 @@ state.dataStrGlobals->inputFilePath='{:g}', if (runEPMacro) { fs::path epMacroPath = (state.dataStrGlobals->exeDirectoryPath / "EPMacro").replace_extension(FileSystem::exeExtension); if (!FileSystem::fileExists(epMacroPath)) { - DisplayString(state, std::format("ERROR: Could not find EPMacro executable: {}.", FileSystem::getAbsolutePath(epMacroPath).string())); + DisplayString(state, std::format("ERROR: Could not find EPMacro executable: {}.", FileSystem::getAbsolutePath(epMacroPath))); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); } @@ -723,9 +721,8 @@ state.dataStrGlobals->inputFilePath='{:g}', fs::path expandObjectsPath = (state.dataStrGlobals->exeDirectoryPath / fs::path("ExpandObjects")).replace_extension(FileSystem::exeExtension); if (!FileSystem::fileExists(expandObjectsPath)) { - DisplayString( - state, - std::format("ERROR: Could not find ExpandObjects executable: {}.", FileSystem::getAbsolutePath(expandObjectsPath).string())); + DisplayString(state, + std::format("ERROR: Could not find ExpandObjects executable: {}.", FileSystem::getAbsolutePath(expandObjectsPath))); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); } @@ -738,7 +735,7 @@ state.dataStrGlobals->inputFilePath='{:g}', if (!FileSystem::fileExists(state.dataStrGlobals->inputIddFilePath)) { DisplayString(state, std::format("ERROR: Could not find input data dictionary: {}.", - FileSystem::getAbsolutePath(state.dataStrGlobals->inputIddFilePath).string())); + FileSystem::getAbsolutePath(state.dataStrGlobals->inputIddFilePath))); DisplayString(state, errorFollowUp); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); @@ -931,8 +928,7 @@ state.dataStrGlobals->inputFilePath='{:g}', state, "ERROR: Could not find ReadVarsESO executable. When calling through C API, make sure to call setEnergyPlusRootDirectory"); } else { - DisplayString( - state, std::format("ERROR: Could not find ReadVarsESO executable: {}.", FileSystem::getAbsolutePath(readVarsPath).string())); + DisplayString(state, std::format("ERROR: Could not find ReadVarsESO executable: {}.", FileSystem::getAbsolutePath(readVarsPath))); } return static_cast(ReturnCodes::Failure); } @@ -945,7 +941,7 @@ state.dataStrGlobals->inputFilePath='{:g}', if (!rviFileExists) { std::ofstream ofs{RVIfile}; if (!ofs.good()) { - ShowFatalError(state, std::format("EnergyPlus: Could not open file \"{}\" for output (write).", RVIfile.string())); + ShowFatalError(state, std::format("EnergyPlus: Could not open file \"{}\" for output (write).", RVIfile)); } else { ofs << FileSystem::toString(state.files.eso.filePath) << '\n'; ofs << FileSystem::toString(state.files.csv.filePath) << '\n'; @@ -956,7 +952,7 @@ state.dataStrGlobals->inputFilePath='{:g}', if (!mviFileExists) { std::ofstream ofs{MVIfile}; if (!ofs.good()) { - ShowFatalError(state, std::format("EnergyPlus: Could not open file \"{}\" for output (write).", RVIfile.string())); + ShowFatalError(state, std::format("EnergyPlus: Could not open file \"{}\" for output (write).", RVIfile)); } else { ofs << FileSystem::toString(state.files.mtr.filePath) << '\n'; ofs << FileSystem::toString(state.files.mtr_csv.filePath) << '\n'; diff --git a/src/EnergyPlus/CurveManager.cc b/src/EnergyPlus/CurveManager.cc index 5b7d839511e..729f4619e79 100644 --- a/src/EnergyPlus/CurveManager.cc +++ b/src/EnergyPlus/CurveManager.cc @@ -2396,14 +2396,12 @@ namespace Curve { std::string tmp = indVarInstance.at("external_file_name").get(); fs::path filePath(tmp); if (indVarInstance.count("external_file_column_number") == 0u) { - ShowSevereError( - state, std::format("{}: No column number defined for external file \"{}\"", contextString, filePath.string())); + ShowSevereError(state, std::format("{}: No column number defined for external file \"{}\"", contextString, filePath)); ErrorsFound = true; } if (indVarInstance.count("external_file_starting_row_number") == 0u) { - ShowSevereError( - state, - std::format("{}: No starting row number defined for external file \"{}\"", contextString, filePath.string())); + ShowSevereError(state, + std::format("{}: No starting row number defined for external file \"{}\"", contextString, filePath)); ErrorsFound = true; } @@ -2605,14 +2603,13 @@ namespace Curve { fs::path filePath(tmp); if (fields.count("external_file_column_number") == 0u) { - ShowSevereError( - state, std::format("{}: No column number defined for external file \"{}\"", thisCurve->contextString, filePath.string())); + ShowSevereError(state, + std::format("{}: No column number defined for external file \"{}\"", thisCurve->contextString, filePath)); ErrorsFound = true; } if (fields.count("external_file_starting_row_number") == 0u) { ShowSevereError( - state, - std::format("{}: No starting row number defined for external file \"{}\"", thisCurve->contextString, filePath.string())); + state, std::format("{}: No starting row number defined for external file \"{}\"", thisCurve->contextString, filePath)); ErrorsFound = true; } @@ -2784,14 +2781,12 @@ namespace Curve { std::size_t row = colAndRow.second; // 0 indexed auto &content = contents[col]; if (col >= numColumns) { - ShowFatalError( - state, - std::format("File \"{}\" : Requested column ({}) exceeds the number of columns ({}).", filePath.string(), col + 1, numColumns)); + ShowFatalError(state, + std::format("File \"{}\" : Requested column ({}) exceeds the number of columns ({}).", filePath, col + 1, numColumns)); } if (row >= numRows) { - ShowFatalError( - state, - std::format("File \"{}\" : Requested starting row ({}) exceeds the number of rows ({}).", filePath.string(), row + 1, numRows)); + ShowFatalError(state, + std::format("File \"{}\" : Requested starting row ({}) exceeds the number of rows ({}).", filePath, row + 1, numRows)); } std::vector array(numRows - row); std::transform(content.begin() + row, content.end(), array.begin(), [](std::string_view str) { diff --git a/src/EnergyPlus/DataSystemVariables.cc b/src/EnergyPlus/DataSystemVariables.cc index d51e87a3896..3d52b15c771 100644 --- a/src/EnergyPlus/DataSystemVariables.cc +++ b/src/EnergyPlus/DataSystemVariables.cc @@ -193,10 +193,10 @@ namespace DataSystemVariables { } // If we get here, we didn't find the file - ShowSevereError(state, std::format("{}\"{}\" not found.", contextString, originalInputFilePath.string())); + ShowSevereError(state, std::format("{}\"{}\" not found.", contextString, originalInputFilePath)); ShowContinueError(state, " Paths searched:"); for (auto &path : pathsChecked) { - ShowContinueError(state, std::format(" {}: \"{}\"", path.second, path.first.string())); + ShowContinueError(state, std::format(" {}: \"{}\"", path.second, path.first)); } return foundFilePath; diff --git a/src/EnergyPlus/ExternalInterface.cc b/src/EnergyPlus/ExternalInterface.cc index 291f00f740f..e31c72e998e 100644 --- a/src/EnergyPlus/ExternalInterface.cc +++ b/src/EnergyPlus/ExternalInterface.cc @@ -406,7 +406,7 @@ void InitExternalInterface(EnergyPlusData &state) state.dataExternalInterface->ErrorsFound = true; } } else { - ShowSevereError(state, std::format("ExternalInterface: Did not find file \"{}\".", state.dataExternalInterface->socCfgFilPath.string())); + ShowSevereError(state, std::format("ExternalInterface: Did not find file \"{}\".", state.dataExternalInterface->socCfgFilPath)); ShowContinueError(state, "This file needs to be in same directory as in.idf."); ShowContinueError(state, "Check the documentation for the ExternalInterface."); state.dataExternalInterface->ErrorsFound = true; diff --git a/src/EnergyPlus/HeatBalanceManager.cc b/src/EnergyPlus/HeatBalanceManager.cc index 5094069d0cb..5de5bef6d65 100644 --- a/src/EnergyPlus/HeatBalanceManager.cc +++ b/src/EnergyPlus/HeatBalanceManager.cc @@ -1764,7 +1764,7 @@ namespace HeatBalanceManager { DisplayString(state, "--Construction not found"); ErrorsFound = true; ShowSevereError(state, std::format("No match on WINDOW5 data file for Construction={}, or error in data file.", ConstructAlphas(0))); - ShowContinueError(state, std::format("...Looking on file={}", window5DataFilePath.string())); // TODO: call getAbsolutePath maybe? + ShowContinueError(state, std::format("...Looking on file={}", window5DataFilePath)); // TODO: call getAbsolutePath maybe? continue; } @@ -3753,7 +3753,7 @@ namespace HeatBalanceManager { ShowSevereError(state, std::format("SearchWindow5DataFile: For \"{}\" in {} file, appears to be a Unicode or binary file.", DesiredConstructionName, - DesiredFilePath.string())); + DesiredFilePath)); ShowContinueError(state, "...This file cannot be read by this program. Please save as PC or Unix file and try again"); ShowFatalError(state, "Program terminates due to previous condition."); } @@ -3767,7 +3767,7 @@ namespace HeatBalanceManager { } ++FileLineCount; if (!has_prefixi(NextLine.data, "WINDOW5")) { - ShowSevereError(state, std::format("HeatBalanceManager: SearchWindow5DataFile: Error in Data File={}", DesiredFilePath.string())); + ShowSevereError(state, std::format("HeatBalanceManager: SearchWindow5DataFile: Error in Data File={}", DesiredFilePath)); ShowFatalError( state, std::format("Error reading Window5 Data File: first word of window entry is \"{}\", should be Window5.", NextLine.data.substr(0, 7))); diff --git a/src/EnergyPlus/IOFiles.cc b/src/EnergyPlus/IOFiles.cc index 530cb0c6e30..6d79ffd25f1 100644 --- a/src/EnergyPlus/IOFiles.cc +++ b/src/EnergyPlus/IOFiles.cc @@ -72,7 +72,7 @@ InputFile &InputFile::ensure_open(EnergyPlusData &state, const std::string &call open(false, output_to_file); } if (!good()) { - ShowFatalError(state, EnergyPlus::format("{}: Could not open file {} for input (read).", caller, filePath.string())); + ShowFatalError(state, std::format("{}: Could not open file {} for input (read).", caller, filePath)); } return *this; } @@ -219,7 +219,7 @@ InputOutputFile &InputOutputFile::ensure_open(EnergyPlusData &state, const std:: open(false, output_to_file); } if (!good()) { - ShowFatalError(state, EnergyPlus::format("{}: Could not open file {} for output (write).", caller, filePath.string())); + ShowFatalError(state, std::format("{}: Could not open file {} for output (write).", caller, filePath)); } return *this; } diff --git a/src/EnergyPlus/InputProcessing/InputProcessor.cc b/src/EnergyPlus/InputProcessing/InputProcessor.cc index 2d35e2a0ecc..235d32ed168 100644 --- a/src/EnergyPlus/InputProcessing/InputProcessor.cc +++ b/src/EnergyPlus/InputProcessing/InputProcessor.cc @@ -262,7 +262,7 @@ void cleanEPJSON(json &epjson) void InputProcessor::processInput(EnergyPlusData &state) { if (!FileSystem::fileExists(state.dataStrGlobals->inputFilePath)) { - ShowFatalError(state, EnergyPlus::format("Input file path {} not found", state.dataStrGlobals->inputFilePath.string())); + ShowFatalError(state, std::format("Input file path {} not found", state.dataStrGlobals->inputFilePath)); return; } diff --git a/src/EnergyPlus/OutputProcessor.cc b/src/EnergyPlus/OutputProcessor.cc index b43cece76e2..394682f0de8 100644 --- a/src/EnergyPlus/OutputProcessor.cc +++ b/src/EnergyPlus/OutputProcessor.cc @@ -4052,8 +4052,8 @@ void SetInitialMeterReportingAndOutputNames(EnergyPlusData &state, std::format(R"(Output:Meter:MeterFileOnly requested for "{}" ({}), already on "Output:Meter". Will report to both {} and {})", meter->Name, reportFreqNames[(freq == ReportFreq::EachCall) ? (int)ReportFreq::TimeStep : (int)freq], - state.files.eso.filePath.filename().string(), - state.files.mtr.filePath.filename().string())); + state.files.eso.filePath.filename(), + state.files.mtr.filePath.filename())); } if (!period.Rpt) { period.Rpt = true; @@ -4902,7 +4902,7 @@ int initErrorFile(EnergyPlusData &state) { state.files.err_stream = std::make_unique(state.files.outputErrFilePath); if (state.files.err_stream->bad()) { - DisplayString(state, std::format("ERROR: Could not open file {} for output (write).", state.files.outputErrFilePath.string())); + DisplayString(state, std::format("ERROR: Could not open file {} for output (write).", state.files.outputErrFilePath)); return EXIT_FAILURE; } diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index 508f2691d8b..70f3e747078 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -204,7 +204,7 @@ std::ofstream &open_tbl_stream(EnergyPlusData &state, int const iStyle, fs::path if (output_to_file) { tbl_stream.open(filePath); if (!tbl_stream) { - ShowFatalError(state, EnergyPlus::format("OpenOutputTabularFile: Could not open file \"{}\" for output (write).", filePath.string())); + ShowFatalError(state, std::format("OpenOutputTabularFile: Could not open file \"{}\" for output (write).", filePath)); } } else { tbl_stream.setstate(std::ios_base::badbit); diff --git a/src/EnergyPlus/ScheduleManager.cc b/src/EnergyPlus/ScheduleManager.cc index 45a03796585..10da793fc68 100644 --- a/src/EnergyPlus/ScheduleManager.cc +++ b/src/EnergyPlus/ScheduleManager.cc @@ -603,7 +603,7 @@ namespace Sched { ShowSevereError(state, error); } } - ShowContinueError(state, EnergyPlus::format("Error Occurred in {}", state.files.TempFullFilePath.filePath.string())); + ShowContinueError(state, std::format("Error Occurred in {}", state.files.TempFullFilePath.filePath)); ShowFatalError(state, "Program terminates due to previous condition."); } for (const auto &[warning, isContinued] : csvParser.warnings()) { @@ -632,8 +632,8 @@ namespace Sched { if (!csvParser.hasErrors()) { isCSV = true; ShowWarningMessage(state, - EnergyPlus::format("Extension of file {} is unrecognized, but parsed as CSV successfully", - state.files.TempFullFilePath.filePath.string())); + std::format("Extension of file {} is unrecognized, but parsed as CSV successfully", + state.files.TempFullFilePath.filePath)); schedule_file_shading_result = it.first; } } catch (...) { @@ -647,8 +647,8 @@ namespace Sched { s_sched->UniqueProcessedExternalFiles.emplace(state.files.TempFullFilePath.filePath, std::move(schedule_data)); schedule_file_shading_result = it.first; ShowWarningMessage(state, - EnergyPlus::format("Extension of file {} is unrecognized, but parsed as JSON successfully", - state.files.TempFullFilePath.filePath.string())); + std::format("Extension of file {} is unrecognized, but parsed as JSON successfully", + state.files.TempFullFilePath.filePath)); isJSON = true; } catch (...) { // We're testing to see if this is json, if any exception exists, then throw the standard error about an unknown extension @@ -1688,7 +1688,7 @@ namespace Sched { ShowSevereCustom(state, eoh, error); } } - ShowContinueError(state, std::format("Error Occurred in {}", state.files.TempFullFilePath.filePath.string())); + ShowContinueError(state, std::format("Error Occurred in {}", state.files.TempFullFilePath.filePath)); ShowFatalError(state, "Program terminates due to previous condition."); } for (const auto &[warning, isContinued] : csvParser.warnings()) { @@ -1716,7 +1716,7 @@ namespace Sched { isCSV = true; ShowWarningMessage(state, std::format("Extension of file {} is unrecognized, but parsed as CSV successfully", - state.files.TempFullFilePath.filePath.string())); + state.files.TempFullFilePath.filePath)); } } catch (...) { // We're testing to see if this is a csv, if any exception exists, then throw the standard error about an unknown @@ -1730,7 +1730,7 @@ namespace Sched { result = it.first; ShowWarningMessage(state, std::format("Extension of file {} is unrecognized, but parsed as JSON successfully", - state.files.TempFullFilePath.filePath.string())); + state.files.TempFullFilePath.filePath)); isJSON = true; } catch (...) { // We're testing to see if this is json, if any exception exists, then throw the standard error about an unknown @@ -1754,7 +1754,7 @@ namespace Sched { state, eoh, std::format("Requested column number {}, but found only {} columns.", curcolCount, result->second["values"].size())); - ShowContinueError(state, std::format("Error Occurred in {}", state.files.TempFullFilePath.filePath.string())); + ShowContinueError(state, std::format("Error Occurred in {}", state.files.TempFullFilePath.filePath)); ShowFatalError(state, "Program terminates due to previous condition."); } auto const &column_json = result->second["values"][curcolCount - 1]; @@ -1766,7 +1766,7 @@ namespace Sched { } catch (nlohmann::json::type_error &e) { ShowSevereCustom(state, eoh, std::format("Column number {} has non-numeric data.", curcolCount)); ShowContinueError(state, e.what()); - ShowContinueError(state, std::format("Error Occurred in {}", state.files.TempFullFilePath.filePath.string())); + ShowContinueError(state, std::format("Error Occurred in {}", state.files.TempFullFilePath.filePath)); ShowFatalError(state, "Program terminates due to previous condition."); } @@ -1883,7 +1883,7 @@ namespace Sched { eoh, std::format( "For header '{}', Requested column number {}, but found only {} columns.", header, column + 1, values_json.size())); - ShowContinueError(state, std::format("Error Occurred in {}", schedule_file_shading_result->first.string())); + ShowContinueError(state, std::format("Error Occurred in {}", schedule_file_shading_result->first)); ShowFatalError(state, "Program terminates due to previous condition."); } @@ -1893,7 +1893,7 @@ namespace Sched { } catch (nlohmann::json::type_error &e) { ShowSevereCustom(state, eoh, std::format("Column number {} has non-numeric data.", column + 1)); ShowContinueError(state, e.what()); - ShowContinueError(state, std::format("Error Occurred in {}", schedule_file_shading_result->first.string())); + ShowContinueError(state, std::format("Error Occurred in {}", schedule_file_shading_result->first)); ShowFatalError(state, "Program terminates due to previous condition."); } diff --git a/src/EnergyPlus/SimulationManager.cc b/src/EnergyPlus/SimulationManager.cc index 1af2fc578bc..5e129dbc903 100644 --- a/src/EnergyPlus/SimulationManager.cc +++ b/src/EnergyPlus/SimulationManager.cc @@ -1780,7 +1780,7 @@ namespace SimulationManager { { auto result = std::make_unique(filePath, mode); // (AUTO_OK_UPTR) if (!result->good()) { - ShowFatalError(state, std::format("OpenOutputFiles: Could not open file {} for output (write).", filePath.string())); + ShowFatalError(state, std::format("OpenOutputFiles: Could not open file {} for output (write).", filePath)); } return result; } @@ -1799,7 +1799,7 @@ namespace SimulationManager { result = std::make_unique(std::move(f)); } catch (const std::system_error &error) { ShowSevereError(state, error.what()); - ShowFatalError(state, std::format("OpenOutputFiles: Could not open file {} for output (write).", filePath.string())); + ShowFatalError(state, std::format("OpenOutputFiles: Could not open file {} for output (write).", filePath)); } return result; } diff --git a/src/EnergyPlus/SolarShading.cc b/src/EnergyPlus/SolarShading.cc index defd566313c..a66c95d92f8 100644 --- a/src/EnergyPlus/SolarShading.cc +++ b/src/EnergyPlus/SolarShading.cc @@ -189,9 +189,9 @@ void InitSolarCalculations(EnergyPlusData &state) state.dataSolarShading->shd_stream = std::make_unique(state.dataStrGlobals->outputShdFilePath, std::ios_base::out | std::ios_base::trunc); if (!static_cast(state.dataSolarShading->shd_stream.get())->is_open()) { - ShowFatalError(state, - EnergyPlus::format("InitSolarCalculations: Could not open file \"{}\" for output (write).", - state.dataStrGlobals->outputShdFilePath.string())); + ShowFatalError( + state, + std::format("InitSolarCalculations: Could not open file \"{}\" for output (write).", state.dataStrGlobals->outputShdFilePath)); } } else { state.dataSolarShading->shd_stream = std::make_unique(nullptr); diff --git a/src/EnergyPlus/UtilityRoutines.cc b/src/EnergyPlus/UtilityRoutines.cc index ec548c3dd72..9892a5595d9 100644 --- a/src/EnergyPlus/UtilityRoutines.cc +++ b/src/EnergyPlus/UtilityRoutines.cc @@ -325,8 +325,8 @@ namespace Util { fsPerfLog.open(state.dataStrGlobals->outputPerfLogFilePath, std::fstream::out); // open file normally if (!fsPerfLog) { ShowFatalError(state, - EnergyPlus::format("appendPerfLog: Could not open file \"{}\" for output (write).", - state.dataStrGlobals->outputPerfLogFilePath.string())); + std::format("appendPerfLog: Could not open file \"{}\" for output (write).", + state.dataStrGlobals->outputPerfLogFilePath)); } fsPerfLog << state.dataUtilityRoutines->appendPerfLog_headerRow << std::endl; fsPerfLog << state.dataUtilityRoutines->appendPerfLog_valuesRow << std::endl; @@ -336,8 +336,8 @@ namespace Util { fsPerfLog.open(state.dataStrGlobals->outputPerfLogFilePath, std::fstream::app); // append to already existing file if (!fsPerfLog) { ShowFatalError(state, - EnergyPlus::format("appendPerfLog: Could not open file \"{}\" for output (append).", - state.dataStrGlobals->outputPerfLogFilePath.string())); + std::format("appendPerfLog: Could not open file \"{}\" for output (append).", + state.dataStrGlobals->outputPerfLogFilePath)); } fsPerfLog << state.dataUtilityRoutines->appendPerfLog_valuesRow << std::endl; } @@ -452,7 +452,7 @@ int AbortEnergyPlus(EnergyPlusData &state) auto tempfl = state.files.endFile.try_open(state.files.outputControl.end); if (!tempfl.good()) { - DisplayString(state, EnergyPlus::format("AbortEnergyPlus: Could not open file {} for output (write).", tempfl.filePath.string())); + DisplayString(state, std::format("AbortEnergyPlus: Could not open file {} for output (write).", tempfl.filePath)); } print( tempfl, "EnergyPlus Terminated--Fatal Error Detected. {} Warning; {} Severe Errors; Elapsed Time={}\n", NumWarnings, NumSevere, Elapsed); @@ -572,7 +572,7 @@ int EndEnergyPlus(EnergyPlusData &state) { auto tempfl = state.files.endFile.try_open(state.files.outputControl.end); if (!tempfl.good()) { - DisplayString(state, EnergyPlus::format("EndEnergyPlus: Could not open file {} for output (write).", tempfl.filePath.string())); + DisplayString(state, std::format("EndEnergyPlus: Could not open file {} for output (write).", tempfl.filePath)); } print(tempfl, "EnergyPlus Completed Successfully-- {} Warning; {} Severe Errors; Elapsed Time={}\n", NumWarnings, NumSevere, Elapsed); } diff --git a/src/EnergyPlus/WeatherManager.cc b/src/EnergyPlus/WeatherManager.cc index 12712fbb7d0..13121955bd9 100644 --- a/src/EnergyPlus/WeatherManager.cc +++ b/src/EnergyPlus/WeatherManager.cc @@ -8677,8 +8677,8 @@ namespace Weather { if (statFileExists) { auto statFile = state.files.inStatFilePath.try_open(); if (!statFile.good()) { - ShowSevereError( - state, std::format("CalcAnnualAndMonthlyDryBulbTemp: Could not open file {} for input (read).", statFile.filePath.string())); + ShowSevereError(state, + std::format("CalcAnnualAndMonthlyDryBulbTemp: Could not open file {} for input (read).", statFile.filePath)); ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C."); return; } @@ -8698,7 +8698,7 @@ namespace Weather { ShowSevereError( state, std::format("CalcAnnualAndMonthlyDryBulbTemp: Stat file '{}' does not have Monthly Statistics for Dry Bulb temperatures.", - statFile.filePath.string())); + statFile.filePath)); ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C."); return; } @@ -8727,8 +8727,8 @@ namespace Weather { auto epwFile = state.files.inputWeatherFilePath.try_open(); bool epwHasLeapYear(false); if (!epwFile.good()) { - ShowSevereError( - state, std::format("CalcAnnualAndMonthlyDryBulbTemp: Could not open file {} for input (read).", epwFile.filePath.string())); + ShowSevereError(state, + std::format("CalcAnnualAndMonthlyDryBulbTemp: Could not open file {} for input (read).", epwFile.filePath)); ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C."); return; } @@ -8787,8 +8787,8 @@ namespace Weather { this->OADryBulbWeatherDataProcessed = true; } else { ShowSevereError(state, "CalcAnnualAndMonthlyDryBulbTemp: weather file or stat file does not exist."); - ShowContinueError(state, std::format("Weather file: {}.", state.files.inputWeatherFilePath.filePath.string())); - ShowContinueError(state, std::format("Stat file: {}.", state.files.inStatFilePath.filePath.string())); + ShowContinueError(state, std::format("Weather file: {}.", state.files.inputWeatherFilePath.filePath)); + ShowContinueError(state, std::format("Stat file: {}.", state.files.inStatFilePath.filePath)); ShowContinueError(state, "Water Mains Monthly Temperature cannot be calculated using CorrelationFromWeatherFile method."); ShowContinueError(state, "Instead a fixed default value of 10.0 C will be used."); } diff --git a/src/EnergyPlus/ZoneTempPredictorCorrector.cc b/src/EnergyPlus/ZoneTempPredictorCorrector.cc index 40b463497ac..3fa2ee8b09c 100644 --- a/src/EnergyPlus/ZoneTempPredictorCorrector.cc +++ b/src/EnergyPlus/ZoneTempPredictorCorrector.cc @@ -2273,7 +2273,7 @@ void CalculateMonthlyRunningAverageDryBulb(EnergyPlusData &state, Array1D Date: Mon, 8 Jun 2026 18:35:00 +0200 Subject: [PATCH 08/18] Missed one --- src/EnergyPlus/FileSystem.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EnergyPlus/FileSystem.hh b/src/EnergyPlus/FileSystem.hh index a518d93668a..073051e85d8 100644 --- a/src/EnergyPlus/FileSystem.hh +++ b/src/EnergyPlus/FileSystem.hh @@ -236,7 +236,7 @@ namespace FileSystem { auto close_file = [](FILE *f) { fclose(f); }; auto holder = std::unique_ptr(fopen(path, "wb"), close_file); if (!holder) { - throw FatalError(fmt::format("Could not open file: {}", static_cast(path))); + throw FatalError(std::format("Could not open file: {}", filePath)); } auto f = holder.get(); From 179341ef9365df18b78b9b7bf28ddb798a1104dd Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 18:36:23 +0200 Subject: [PATCH 09/18] Eliminate more fmt::format calls --- src/EnergyPlus/InputProcessing/IdfParser.cc | 21 ++++++++++----------- src/EnergyPlus/OutputProcessor.cc | 4 ++-- src/EnergyPlus/ThermalISO15099Calc.cc | 11 ++++++----- src/EnergyPlus/Timer.cc | 7 ++++--- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/EnergyPlus/InputProcessing/IdfParser.cc b/src/EnergyPlus/InputProcessing/IdfParser.cc index e000730e55f..9442f7c9c59 100644 --- a/src/EnergyPlus/InputProcessing/IdfParser.cc +++ b/src/EnergyPlus/InputProcessing/IdfParser.cc @@ -51,7 +51,6 @@ // Third Party Headers #include -#include #include #include @@ -245,7 +244,7 @@ json IdfParser::parse_idf(std::string_view idf, size_t &index, bool &success, js continue; } if (token == Token::COMMA) { - errors_.emplace_back(fmt::format("Line: {} Index: {} - Extraneous comma found.", cur_line_num, index_into_cur_line)); + errors_.emplace_back(std::format("Line: {} Index: {} - Extraneous comma found.", cur_line_num, index_into_cur_line)); success = false; return root; } @@ -257,7 +256,7 @@ json IdfParser::parse_idf(std::string_view idf, size_t &index, bool &success, js std::string const obj_name = normalizeObjectType(parsed_obj_name); if (obj_name.empty()) { errors_.emplace_back( - fmt::format("Line: {} Index: {} - \"{}\" is not a valid Object Type.", cur_line_num, index_into_cur_line, parsed_obj_name)); + std::format("Line: {} Index: {} - \"{}\" is not a valid Object Type.", cur_line_num, index_into_cur_line, parsed_obj_name)); while (token != Token::SEMICOLON && token != Token::END) { token = next_token(idf, index); } @@ -275,13 +274,13 @@ json IdfParser::parse_idf(std::string_view idf, size_t &index, bool &success, js line = idf.substr(beginning_of_line_index, found_index - beginning_of_line_index - 1); } errors_.emplace_back( - fmt::format("Line: {} Index: {} - Error parsing \"{}\". Error in following line.", cur_line_num, index_into_cur_line, obj_name)); - errors_.emplace_back(fmt::format("~~~ {}", line)); + std::format("Line: {} Index: {} - Error parsing \"{}\". Error in following line.", cur_line_num, index_into_cur_line, obj_name)); + errors_.emplace_back(std::format("~~~ {}", line)); success = false; continue; } u64toa(root[obj_name].size() + 1, s); - std::string name = fmt::format("{} {}", obj_name, s); + std::string name = std::format("{} {}", obj_name, s); if (!obj.is_null()) { auto const name_iter = obj.find("name"); @@ -301,7 +300,7 @@ json IdfParser::parse_idf(std::string_view idf, size_t &index, bool &success, js if (root[obj_name].find(name) != root[obj_name].end()) { errors_.emplace_back( - fmt::format(R"(Duplicate name found for object of type "{}" named "{}". Overwriting existing object.)", obj_name, name)); + std::format(R"(Duplicate name found for object of type "{}" named "{}". Overwriting existing object.)", obj_name, name)); } root[obj_name][name] = std::move(obj); @@ -411,14 +410,14 @@ json IdfParser::parse_object( } else if (legacy_idd_index >= legacy_idd_fields_array.size()) { if (legacy_idd_extensibles_iter == legacy_idd.end()) { errors_.emplace_back( - fmt::format("Line: {} Index: {} - Object contains more field values than maximum number of IDD fields and is not extensible.", + std::format("Line: {} Index: {} - Object contains more field values than maximum number of IDD fields and is not extensible.", cur_line_num, index_into_cur_line)); success = false; return root; } if (schema_obj_extensions == nullptr) { - errors_.emplace_back(fmt::format("Line: {} Index: {} - Object does not have extensible fields but should. Likely a parsing error.", + errors_.emplace_back(std::format("Line: {} Index: {} - Object does not have extensible fields but should. Likely a parsing error.", cur_line_num, index_into_cur_line)); success = false; @@ -447,7 +446,7 @@ json IdfParser::parse_object( root[field] = parse_string(idf, index); } else { u64toa(cur_line_num, s); - errors_.emplace_back(fmt::format("Line: {} - Field \"{}\" was not found.", s, field)); + errors_.emplace_back(std::format("Line: {} - Field \"{}\" was not found.", s, field)); } } else { json val = parse_value(idf, index, success, find_field_iter.value()); @@ -648,7 +647,7 @@ json IdfParser::parse_value(std::string_view idf, size_t &index, bool &success, if (anyOf_it == field_loc.end()) { errors_.emplace_back( - fmt::format("Line: {} Index: {} - Field cannot be Autosize or Autocalculate", cur_line_num, index_into_cur_line)); + std::format("Line: {} Index: {} - Field cannot be Autosize or Autocalculate", cur_line_num, index_into_cur_line)); return parsed_string; } // The following is hacky because it abuses knowing the consistent generated structure diff --git a/src/EnergyPlus/OutputProcessor.cc b/src/EnergyPlus/OutputProcessor.cc index 394682f0de8..e313a5c588e 100644 --- a/src/EnergyPlus/OutputProcessor.cc +++ b/src/EnergyPlus/OutputProcessor.cc @@ -2789,7 +2789,7 @@ namespace OutputProcessor { } if (state.files.eso.good()) { - print(state.files.eso, "{},{}\n", reportID, fmt::format_int(repValue).c_str()); + print(state.files.eso, "{},{}\n", reportID, repValue); } } // WriteNumericData() @@ -3736,7 +3736,7 @@ void UpdateDataandReport(EnergyPlusData &state, OutputProcessor::TimeStepType co ReportMeters(state, ReportFreq::Year, TimePrint); state.dataGlobal->CalendarYear += 1; - state.dataGlobal->CalendarYearChr = fmt::to_string(state.dataGlobal->CalendarYear); + state.dataGlobal->CalendarYearChr = std::to_string(state.dataGlobal->CalendarYear); } } // UpdateDataandReport() diff --git a/src/EnergyPlus/ThermalISO15099Calc.cc b/src/EnergyPlus/ThermalISO15099Calc.cc index 984935030e2..8a81c5fb666 100644 --- a/src/EnergyPlus/ThermalISO15099Calc.cc +++ b/src/EnergyPlus/ThermalISO15099Calc.cc @@ -47,6 +47,7 @@ // C++ Headers #include +#include // EnergyPlus Headers #include @@ -2956,9 +2957,9 @@ void storeIterationResults(EnergyPlusData &state, dynFormat = ""; } if (mod(i, 2) == 1) { - dynFormat += fmt::format("Ebf({:3})", (i + 1) / 2); + dynFormat += std::format("Ebf({:3})", (i + 1) / 2); } else { - dynFormat += fmt::format("Ebb({:3})", (i + 1) / 2); + dynFormat += std::format("Ebb({:3})", (i + 1) / 2); } if (i != 2 * nlayer) { dynFormat += "==="; @@ -2976,7 +2977,7 @@ void storeIterationResults(EnergyPlusData &state, // Write headers for Rb and Rf for (i = 1; i <= 2 * nlayer; ++i) { - const std::string a = fmt::format("{:3}", (i + 1) / 2); // this is just to simulate correct integer in brackets + const std::string a = std::format("{:3}", (i + 1) / 2); // this is just to simulate correct integer in brackets if (i == 1) { dynFormat = ""; } @@ -3000,7 +3001,7 @@ void storeIterationResults(EnergyPlusData &state, // Write header for temperatures for (i = 1; i <= 2 * nlayer; ++i) { - const std::string a = fmt::format("{:3}", i); + const std::string a = std::format("{:3}", i); if (i == 1) { dynFormat = ""; } @@ -3025,7 +3026,7 @@ void storeIterationResults(EnergyPlusData &state, if (index == 0) { dynFormat = " "; for (i = 1; i <= 2 * nlayer; ++i) { - const std::string a = fmt::format("{:3}", i); + const std::string a = std::format("{:3}", i); if (i != 2 * nlayer) { dynFormat += "theta(" + a + "),"; } else { diff --git a/src/EnergyPlus/Timer.cc b/src/EnergyPlus/Timer.cc index 326bb7bf64c..5f6478c8e66 100644 --- a/src/EnergyPlus/Timer.cc +++ b/src/EnergyPlus/Timer.cc @@ -49,6 +49,7 @@ #ifndef NDEBUG # include #endif +#include // Third Party Headers #include @@ -91,9 +92,9 @@ std::string Timer::formatAsHourMinSecs() const // TODO: do we want to report elapsed time of 25 hours as 1 day 1hr 0min 0sec or 25hr 0min 0sec? // constexpr auto num_ms_in_day = 1000 * 3600 * 24; // if (duration().count() > num_ms_in_day) { - // return fmt::format("{:.2%j days %Hhr %Mmin %Ssec}\n", duration()); + // return std::format("{:.2%j days %Hhr %Mmin %Ssec}\n", duration()); // } else { - // return fmt::format("{:%Hhr %Mmin %Ssec}\n", duration()); + // return std::format("{:%Hhr %Mmin %Ssec}\n", duration()); // } auto count = duration().count(); auto Hours = count / 3600000; @@ -105,7 +106,7 @@ std::string Timer::formatAsHourMinSecs() const if (Seconds < 0.0) { Seconds = 0.0; } - return fmt::format("{:02}hr {:02}min {:5.2F}sec", Hours, Minutes, Seconds); + return std::format("{:02}hr {:02}min {:5.2F}sec", Hours, Minutes, Seconds); } Real64 Timer::elapsedSeconds() const From 1a24245cebce144f7c4409441ba650603f8ba2ec Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 18:40:41 +0200 Subject: [PATCH 10/18] Replace all fmt::to_string (but the buffer one) with std::to_string WaterThermalTanks I handled manually --- src/EnergyPlus/CurveManager.cc | 4 ++-- src/EnergyPlus/DaylightingManager.cc | 4 ++-- src/EnergyPlus/EconomicLifeCycleCost.cc | 6 ++--- src/EnergyPlus/GroundHeatExchangers/Slinky.cc | 2 +- src/EnergyPlus/HVACSizingSimulationManager.cc | 4 ++-- src/EnergyPlus/HeatBalFiniteDiffManager.cc | 2 +- src/EnergyPlus/OutputReports.cc | 12 +++++----- src/EnergyPlus/Psychrometrics.cc | 2 +- src/EnergyPlus/RoomAirModelManager.cc | 2 +- src/EnergyPlus/RuntimeLanguageProcessor.cc | 2 +- src/EnergyPlus/ScheduleManager.cc | 4 ++-- src/EnergyPlus/SimAirServingZones.cc | 4 ++-- src/EnergyPlus/SimulationManager.cc | 20 ++++++++-------- src/EnergyPlus/SizingAnalysisObjects.cc | 2 +- src/EnergyPlus/SizingManager.cc | 4 ++-- src/EnergyPlus/SurfaceGeometry.cc | 8 +++---- src/EnergyPlus/SystemReports.cc | 4 ++-- src/EnergyPlus/UserDefinedComponents.cc | 8 +++---- src/EnergyPlus/UtilityRoutines.cc | 24 +++++++++---------- src/EnergyPlus/WaterThermalTanks.cc | 3 +-- src/EnergyPlus/WeatherManager.cc | 10 ++++---- 21 files changed, 65 insertions(+), 66 deletions(-) diff --git a/src/EnergyPlus/CurveManager.cc b/src/EnergyPlus/CurveManager.cc index 729f4619e79..87f41edfed2 100644 --- a/src/EnergyPlus/CurveManager.cc +++ b/src/EnergyPlus/CurveManager.cc @@ -2823,7 +2823,7 @@ namespace Curve { // SUBROUTINE LOCAL VARIABLE DECLARATIONS: for (auto *thisCurve : state.dataCurveManager->curves) { for (int dim = 1; dim <= thisCurve->numDims; ++dim) { - std::string numStr = fmt::to_string(dim); + std::string numStr = std::to_string(dim); SetupOutputVariable(state, std::format("Performance Curve Input Variable {} Value", numStr), Constant::Units::None, @@ -3065,7 +3065,7 @@ namespace Curve { ErrorObjectHeader eoh{routineName, objectType, objectName}; - std::string validDimsString = fmt::to_string(validDims[0]); + std::string validDimsString = std::to_string(validDims[0]); for (std::size_t i = 1; i < validDims.size(); i++) { validDimsString += std::format(" or {}", validDims[i]); } diff --git a/src/EnergyPlus/DaylightingManager.cc b/src/EnergyPlus/DaylightingManager.cc index 0d6e447c70e..15e3b77acc4 100644 --- a/src/EnergyPlus/DaylightingManager.cc +++ b/src/EnergyPlus/DaylightingManager.cc @@ -9150,7 +9150,7 @@ void ReportIllumMap(EnergyPlusData &state, int const MapNum) auto openMapFile = [&](const fs::path &filePath) -> InputOutputFile & { auto &outputFile = *illumMap.mapFile; - outputFile.filePath = FileSystem::appendSuffixToPath(filePath, fmt::to_string(MapNum)); + outputFile.filePath = FileSystem::appendSuffixToPath(filePath, std::to_string(MapNum)); outputFile.ensure_open(state, "ReportIllumMap"); return outputFile; }; @@ -9244,7 +9244,7 @@ void ReportIllumMap(EnergyPlusData &state, int const MapNum) mapLine = std::format("({:.2f};{:.2f})=", illumMap.refPts(RefPt).absCoords.x, illumMap.refPts(RefPt).absCoords.y); for (int R = RefPt; R <= RefPt + illumMap.Xnum - 1; ++R) { int IllumOut = nint(illumMap.refPts(R).lumsHr[iLum_Illum]); - std::string String = fmt::to_string(IllumOut); + std::string String = std::to_string(IllumOut); ; if (!illumMap.refPts(R).inBounds) { String = "*" + String; diff --git a/src/EnergyPlus/EconomicLifeCycleCost.cc b/src/EnergyPlus/EconomicLifeCycleCost.cc index c28aa277b36..489b188a329 100644 --- a/src/EnergyPlus/EconomicLifeCycleCost.cc +++ b/src/EnergyPlus/EconomicLifeCycleCost.cc @@ -1745,7 +1745,7 @@ void WriteTabularLifeCycleCostReport(EnergyPlusData &state) } tableBody(1, 7) = std::format("{} {}", Util::MonthNamesCC[static_cast(elcc->baseDateMonth)], elcc->baseDateYear); tableBody(1, 8) = std::format("{} {}", Util::MonthNamesCC[static_cast(elcc->serviceDateMonth)], elcc->serviceDateYear); - tableBody(1, 9) = fmt::to_string(elcc->lengthStudyYears); + tableBody(1, 9) = std::to_string(elcc->lengthStudyYears); tableBody(1, 10) = OutputReportTabular::RealToStr(currentStyle.formatReals, elcc->taxRate, 4); tableBody(1, 11) = DeprMethodNames[static_cast(elcc->depreciationMethod)]; @@ -1782,7 +1782,7 @@ void WriteTabularLifeCycleCostReport(EnergyPlusData &state) rowHead(1) = "Resource"; rowHead(2) = "Start Date"; for (int iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) { - rowHead(iYear + 2) = fmt::to_string(iYear); + rowHead(iYear + 2) = std::to_string(iYear); } for (int jObj = 1; jObj <= elcc->numUsePriceEscalation; ++jObj) { // loop through objects not columns to add names columnHead(jObj) = elcc->UsePriceEscalation(jObj).name; @@ -2243,7 +2243,7 @@ void WriteTabularLifeCycleCostReport(EnergyPlusData &state) columnHead(kMonth) = Util::MonthNamesCC[static_cast(kMonth - 1)]; } for (int iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) { - rowHead(iYear) = fmt::to_string(elcc->baseDateYear + iYear - 1); + rowHead(iYear) = std::to_string(elcc->baseDateYear + iYear - 1); for (int kMonth = 1; kMonth <= 12; ++kMonth) { tableBody(kMonth, iYear) = OutputReportTabular::RealToStr( currentStyle.formatReals, elcc->CashFlow[CostCategory::TotGrand].mnAmount((iYear - 1) * 12 + kMonth), 2); diff --git a/src/EnergyPlus/GroundHeatExchangers/Slinky.cc b/src/EnergyPlus/GroundHeatExchangers/Slinky.cc index 87e5750e63a..c067dbc52b2 100644 --- a/src/EnergyPlus/GroundHeatExchangers/Slinky.cc +++ b/src/EnergyPlus/GroundHeatExchangers/Slinky.cc @@ -131,7 +131,7 @@ GLHESlinky::GLHESlinky(EnergyPlusData &state, std::string const &objName, nlohma // Need to add a response factor object for the slinky model std::shared_ptr thisRF(new GLHEResponseFactors); - thisRF->name = "Response Factor Object Auto Generated No: " + fmt::to_string(state.dataGroundHeatExchanger->numAutoGeneratedResponseFactors + 1); + thisRF->name = "Response Factor Object Auto Generated No: " + std::to_string(state.dataGroundHeatExchanger->numAutoGeneratedResponseFactors + 1); this->myRespFactors = thisRF; state.dataGroundHeatExchanger->responseFactorsVector.push_back(thisRF); diff --git a/src/EnergyPlus/HVACSizingSimulationManager.cc b/src/EnergyPlus/HVACSizingSimulationManager.cc index 4a026ab0dfa..eb34f1209f9 100644 --- a/src/EnergyPlus/HVACSizingSimulationManager.cc +++ b/src/EnergyPlus/HVACSizingSimulationManager.cc @@ -275,7 +275,7 @@ void ManageHVACSizingSimulation(EnergyPlusData &state, bool &ErrorsFound) } // } ++state.dataGlobal->DayOfSim; - state.dataGlobal->DayOfSimChr = fmt::to_string(state.dataGlobal->DayOfSim); + state.dataGlobal->DayOfSimChr = std::to_string(state.dataGlobal->DayOfSim); if (!state.dataGlobal->WarmupFlag) { ++state.dataEnvrn->CurrentOverallSimDay; DisplaySimDaysProgress(state, state.dataEnvrn->CurrentOverallSimDay, state.dataEnvrn->TotalOverallSimDays); @@ -287,7 +287,7 @@ void ManageHVACSizingSimulation(EnergyPlusData &state, bool &ErrorsFound) if (state.dataGlobal->WarmupFlag) { ++state.dataReportFlag->NumOfWarmupDays; - state.dataReportFlag->cWarmupDay = fmt::to_string(state.dataReportFlag->NumOfWarmupDays); + state.dataReportFlag->cWarmupDay = std::to_string(state.dataReportFlag->NumOfWarmupDays); DisplayString(state, "Warming up {" + state.dataReportFlag->cWarmupDay + '}'); } else if (state.dataGlobal->DayOfSim == 1) { DisplayString( diff --git a/src/EnergyPlus/HeatBalFiniteDiffManager.cc b/src/EnergyPlus/HeatBalFiniteDiffManager.cc index 71f00ff38d7..2081b7aa8d1 100644 --- a/src/EnergyPlus/HeatBalFiniteDiffManager.cc +++ b/src/EnergyPlus/HeatBalFiniteDiffManager.cc @@ -295,7 +295,7 @@ namespace HeatBalFiniteDiffManager { s_ipsc->cCurrentModuleObject, MaterialNames(1))); ShowContinueError( - state, std::format("...occurs first at item=[{}], value=[{:#G}].", fmt::to_string(inegptr), matFD.TempEnth(1, inegptr))); + state, std::format("...occurs first at item=[{}], value=[{:#G}].", std::to_string(inegptr), matFD.TempEnth(1, inegptr))); ErrorsFound = true; } nonInc = false; diff --git a/src/EnergyPlus/OutputReports.cc b/src/EnergyPlus/OutputReports.cc index 82be7a4c1bd..d29cfe6854d 100644 --- a/src/EnergyPlus/OutputReports.cc +++ b/src/EnergyPlus/OutputReports.cc @@ -1144,9 +1144,9 @@ void DetailsForSurfaces(EnergyPlusData &state, int const RptType) // (1=Vertices << EnergyPlus::format("{:.2R}", thisSurface.NetAreaShadowCalc) << "," << EnergyPlus::format("{:.2R}", thisSurface.Azimuth) << "," << EnergyPlus::format("{:.2R}", thisSurface.Tilt) << "," << EnergyPlus::format("{:.2R}", thisSurface.Width) << "," << EnergyPlus::format("{:.2R}", thisSurface.Height) << ","; - *eiostream << ",,,,,,,,,," << fmt::to_string(thisSurface.Sides) << '\n'; + *eiostream << ",,,,,,,,,," << std::to_string(thisSurface.Sides) << '\n'; } else if (RptType == 1) { - *eiostream << fmt::to_string(thisSurface.Sides) << ","; + *eiostream << std::to_string(thisSurface.Sides) << ","; } else { if (thisSurface.shadowSurfSched != nullptr) { ScheduleName = thisSurface.shadowSurfSched->Name; @@ -1162,7 +1162,7 @@ void DetailsForSurfaces(EnergyPlusData &state, int const RptType) // (1=Vertices << EnergyPlus::format("{:.2R}", thisSurface.NetAreaShadowCalc) << "," << EnergyPlus::format("{:.2R}", thisSurface.Azimuth) << "," << EnergyPlus::format("{:.2R}", thisSurface.Tilt) << "," << EnergyPlus::format("{:.2R}", thisSurface.Width) << "," << EnergyPlus::format("{:.2R}", thisSurface.Height) << ","; - *eiostream << ",,,,,,,,,," << fmt::to_string(thisSurface.Sides) << ","; + *eiostream << ",,,,,,,,,," << std::to_string(thisSurface.Sides) << ","; } if (RptType == 10) { continue; @@ -1334,12 +1334,12 @@ void DetailsForSurfaces(EnergyPlusData &state, int const RptType) // (1=Vertices *eiostream << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorGround) << "," << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorSky) << "," << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorGroundIR) << "," - << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorSkyIR) << "," << fmt::to_string(thisSurface.Sides) << '\n'; + << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorSkyIR) << "," << std::to_string(thisSurface.Sides) << '\n'; } else { *eiostream << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorGround) << "," << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorSky) << "," << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorGroundIR) << "," - << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorSkyIR) << "," << fmt::to_string(thisSurface.Sides) << ","; + << EnergyPlus::format("{:.2R}", thisSurface.ViewFactorSkyIR) << "," << std::to_string(thisSurface.Sides) << ","; for (int vert = 1; vert <= thisSurface.Sides; ++vert) { if (vert != thisSurface.Sides) { *eiostream << EnergyPlus::format("{:.2R}", thisSurface.Vertex(vert).x) << "," @@ -1392,7 +1392,7 @@ void DetailsForSurfaces(EnergyPlusData &state, int const RptType) // (1=Vertices *eiostream << "HeatTransfer Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << BaseSurfName << "," << AlgoName << ","; - *eiostream << fmt::to_string(thisSurface.Sides) << ","; + *eiostream << std::to_string(thisSurface.Sides) << ","; for (int vert = 1; vert <= thisSurface.Sides; ++vert) { if (vert != thisSurface.Sides) { *eiostream << EnergyPlus::format("{:.2R}", thisSurface.Vertex(vert).x) << "," diff --git a/src/EnergyPlus/Psychrometrics.cc b/src/EnergyPlus/Psychrometrics.cc index d12823c077b..68ae0f38a5f 100644 --- a/src/EnergyPlus/Psychrometrics.cc +++ b/src/EnergyPlus/Psychrometrics.cc @@ -179,7 +179,7 @@ namespace Psychrometrics { if (!PsyReportIt[Loop]) { continue; } - const std::string istring = fmt::to_string(state.dataPsychCache->NumTimesCalled[Loop]); + const std::string istring = std::to_string(state.dataPsychCache->NumTimesCalled[Loop]); if (state.dataPsychCache->NumIterations[Loop] > 0) { AverageIterations = double(state.dataPsychCache->NumIterations[Loop]) / double(state.dataPsychCache->NumTimesCalled[Loop]); print(auditFile, "{},{},{:.2R}\n", PsyRoutineNames[Loop], istring, AverageIterations); diff --git a/src/EnergyPlus/RoomAirModelManager.cc b/src/EnergyPlus/RoomAirModelManager.cc index 5e49886c302..9208525ea5a 100644 --- a/src/EnergyPlus/RoomAirModelManager.cc +++ b/src/EnergyPlus/RoomAirModelManager.cc @@ -1628,7 +1628,7 @@ namespace RoomAir { ShowSevereError(state, std::format("GetRoomAirflowNetworkData: For {}: {}", cCurrentModuleObject, ipsc->cAlphaArgs(1))); ShowContinueError(state, std::format("Extensible field set are not evenly divisible by 4. Number of data entries = {}", - fmt::to_string(NumAlphas + NumNumbers - 1))); + std::to_string(NumAlphas + NumNumbers - 1))); ErrorsFound = true; break; } diff --git a/src/EnergyPlus/RuntimeLanguageProcessor.cc b/src/EnergyPlus/RuntimeLanguageProcessor.cc index dffa354ecad..54bd128eedb 100644 --- a/src/EnergyPlus/RuntimeLanguageProcessor.cc +++ b/src/EnergyPlus/RuntimeLanguageProcessor.cc @@ -1003,7 +1003,7 @@ void WriteTrace(EnergyPlusData &state, int const StackNum, int const Instruction NameString = state.dataRuntimeLang->ErlStack(StackNum).Name; LineNum = state.dataRuntimeLang->ErlStack(StackNum).Instruction(InstructionNum).LineNum; - LineNumString = fmt::to_string(LineNum); + LineNumString = std::to_string(LineNum); LineString = state.dataRuntimeLang->ErlStack(StackNum).Line(LineNum); cValueString = ValueToString(ReturnValue); diff --git a/src/EnergyPlus/ScheduleManager.cc b/src/EnergyPlus/ScheduleManager.cc index 10da793fc68..34cafc17d1b 100644 --- a/src/EnergyPlus/ScheduleManager.cc +++ b/src/EnergyPlus/ScheduleManager.cc @@ -2272,8 +2272,8 @@ namespace Sched { YesNoContinous = "Yes"; } else { YesNoContinous = "No"; - minValStr = fmt::to_string((int)schedType->minVal); - maxValStr = fmt::to_string((int)schedType->maxVal); + minValStr = std::to_string((int)schedType->minVal); + maxValStr = std::to_string((int)schedType->maxVal); } } else { YesNoLimited = "No"; diff --git a/src/EnergyPlus/SimAirServingZones.cc b/src/EnergyPlus/SimAirServingZones.cc index a4fee09a452..e3678534a16 100644 --- a/src/EnergyPlus/SimAirServingZones.cc +++ b/src/EnergyPlus/SimAirServingZones.cc @@ -2982,7 +2982,7 @@ void SolveAirLoopControllers( ++state.dataSimAirServingZones->ErrCountSALC; if (state.dataSimAirServingZones->ErrCountSALC < 15) { state.dataSimAirServingZones->ErrEnvironmentName = state.dataEnvrn->EnvironmentName; - const std::string CharErrOut = fmt::to_string(MaxIter); + const std::string CharErrOut = std::to_string(MaxIter); ShowWarningError(state, std::format("SolveAirLoopControllers: Maximum iterations ({}) exceeded for {}, {}, at {}, {} {}", CharErrOut, @@ -3210,7 +3210,7 @@ void SolveWaterCoilController(EnergyPlusData &state, ++state.dataSimAirServingZones->ErrCountSWCC; if (state.dataSimAirServingZones->ErrCountSWCC < 15) { state.dataSimAirServingZones->ErrEnvironmentNameSolveWaterCoilController = state.dataEnvrn->EnvironmentName; - const std::string CharErrOut = fmt::to_string(MaxIter); + const std::string CharErrOut = std::to_string(MaxIter); ShowWarningError(state, std::format("SolveAirLoopControllers: Maximum iterations ({}) exceeded for {}:{}, at {}, {} {}", CharErrOut, diff --git a/src/EnergyPlus/SimulationManager.cc b/src/EnergyPlus/SimulationManager.cc index 5e129dbc903..1490e3dbd67 100644 --- a/src/EnergyPlus/SimulationManager.cc +++ b/src/EnergyPlus/SimulationManager.cc @@ -523,7 +523,7 @@ namespace SimulationManager { } ++state.dataGlobal->DayOfSim; - state.dataGlobal->DayOfSimChr = fmt::to_string(state.dataGlobal->DayOfSim); + state.dataGlobal->DayOfSimChr = std::to_string(state.dataGlobal->DayOfSim); if (!state.dataGlobal->WarmupFlag) { ++state.dataEnvrn->CurrentOverallSimDay; DisplaySimDaysProgress(state, state.dataEnvrn->CurrentOverallSimDay, state.dataEnvrn->TotalOverallSimDays); @@ -535,7 +535,7 @@ namespace SimulationManager { if (state.dataGlobal->WarmupFlag) { ++state.dataReportFlag->NumOfWarmupDays; - state.dataReportFlag->cWarmupDay = fmt::to_string(state.dataReportFlag->NumOfWarmupDays); + state.dataReportFlag->cWarmupDay = std::to_string(state.dataReportFlag->NumOfWarmupDays); DisplayString(state, "Warming up {" + state.dataReportFlag->cWarmupDay + '}'); } else if (state.dataGlobal->DayOfSim == 1) { if (state.dataSysVars->ReportDuringWarmup) { @@ -902,7 +902,7 @@ namespace SimulationManager { state.dataGlobal->TimeStepsInHour = 2; // Force 30 minute time steps on CI } if (state.dataGlobal->TimeStepsInHour <= 0 || state.dataGlobal->TimeStepsInHour > 60) { - Alphas(1) = fmt::to_string(state.dataGlobal->TimeStepsInHour); + Alphas(1) = std::to_string(state.dataGlobal->TimeStepsInHour); ShowWarningError(state, std::format("{}: Requested number ({}) invalid, Defaulted to 4", CurrentModuleObject, Alphas(1))); state.dataGlobal->TimeStepsInHour = 4; } else if (mod(60, state.dataGlobal->TimeStepsInHour) != 0) { @@ -1526,13 +1526,13 @@ namespace SimulationManager { Alphas(2) = "ScriptF"; } Alphas(3) = overrideModeValue; - Alphas(4) = fmt::to_string(state.dataGlobal->TimeStepsInHour); + Alphas(4) = std::to_string(state.dataGlobal->TimeStepsInHour); if (state.dataHeatBal->OverrideZoneAirSolutionAlgo) { Alphas(5) = "Yes"; } else { Alphas(5) = "No"; } - Alphas(6) = fmt::to_string(state.dataHeatBal->MinNumberOfWarmupDays); + Alphas(6) = std::to_string(state.dataHeatBal->MinNumberOfWarmupDays); if (state.dataEnvrn->forceBeginEnvResetSuppress) { Alphas(7) = "Yes"; } else { @@ -1595,8 +1595,8 @@ namespace SimulationManager { Util::appendPerfLog(state, "Zone Radiant Exchange Algorithm", "ScriptF"); } Util::appendPerfLog(state, "Override Mode", currentOverrideModeValue); - Util::appendPerfLog(state, "Number of Timesteps per Hour", fmt::to_string(state.dataGlobal->TimeStepsInHour)); - Util::appendPerfLog(state, "Minimum Number of Warmup Days", fmt::to_string(state.dataHeatBal->MinNumberOfWarmupDays)); + Util::appendPerfLog(state, "Number of Timesteps per Hour", std::to_string(state.dataGlobal->TimeStepsInHour)); + Util::appendPerfLog(state, "Minimum Number of Warmup Days", std::to_string(state.dataHeatBal->MinNumberOfWarmupDays)); Util::appendPerfLog(state, "SuppressAllBeginEnvironmentResets", bool_to_string(state.dataEnvrn->forceBeginEnvResetSuppress)); Util::appendPerfLog(state, "Minimum System Timestep", EnergyPlus::format("{:.1R}", state.dataConvergeParams->MinTimeStepSys * 60.0)); Util::appendPerfLog(state, "MaxZoneTempDiff", EnergyPlus::format("{:.2R}", state.dataConvergeParams->MaxZoneTempDiff)); @@ -1958,17 +1958,17 @@ namespace SimulationManager { if (state.dataSysVars->iEnvSetThreads == 0) { cEnvSetThreads = "Not Set"; } else { - cEnvSetThreads = fmt::to_string(state.dataSysVars->iEnvSetThreads); + cEnvSetThreads = std::to_string(state.dataSysVars->iEnvSetThreads); } if (state.dataSysVars->iepEnvSetThreads == 0) { cepEnvSetThreads = "Not Set"; } else { - cepEnvSetThreads = fmt::to_string(state.dataSysVars->iepEnvSetThreads); + cepEnvSetThreads = std::to_string(state.dataSysVars->iepEnvSetThreads); } if (state.dataSysVars->iIDFSetThreads == 0) { cIDFSetThreads = "Not Set"; } else { - cIDFSetThreads = fmt::to_string(state.dataSysVars->iIDFSetThreads); + cIDFSetThreads = std::to_string(state.dataSysVars->iIDFSetThreads); } if (state.dataSysVars->lnumActiveSims) { print(state.files.eio, diff --git a/src/EnergyPlus/SizingAnalysisObjects.cc b/src/EnergyPlus/SizingAnalysisObjects.cc index c5b64c68a52..43cc122ff31 100644 --- a/src/EnergyPlus/SizingAnalysisObjects.cc +++ b/src/EnergyPlus/SizingAnalysisObjects.cc @@ -539,7 +539,7 @@ void PlantCoinicidentAnalysis::ResolveDesignFlowRate(EnergyPlusData &state, int "{},Normalized Change {},Specific Heat{J/kg-K},Density {kg/m3}\n"); state.dataGlobal->sizingAnalysisEioHeaderDoneOnce = true; } - chIteration = fmt::to_string(HVACSizingIterCount); + chIteration = std::to_string(HVACSizingIterCount); if (setNewSizes) { chSetSizes = "Yes"; } else { diff --git a/src/EnergyPlus/SizingManager.cc b/src/EnergyPlus/SizingManager.cc index 4ab9e50acd1..bccaff781b9 100644 --- a/src/EnergyPlus/SizingManager.cc +++ b/src/EnergyPlus/SizingManager.cc @@ -289,7 +289,7 @@ void ManageSizing(EnergyPlusData &state) ++state.dataSize->CurEnvirNumSimDay; } - state.dataGlobal->DayOfSimChr = fmt::to_string(state.dataGlobal->DayOfSim); + state.dataGlobal->DayOfSimChr = std::to_string(state.dataGlobal->DayOfSim); state.dataGlobal->BeginDayFlag = true; state.dataGlobal->EndDayFlag = false; @@ -485,7 +485,7 @@ void ManageSizing(EnergyPlusData &state) if (!state.dataGlobal->WarmupFlag && state.dataGlobal->DayOfSim > 1) { ++state.dataSize->CurEnvirNumSimDay; } - state.dataGlobal->DayOfSimChr = fmt::to_string(state.dataGlobal->DayOfSim); + state.dataGlobal->DayOfSimChr = std::to_string(state.dataGlobal->DayOfSim); state.dataGlobal->BeginDayFlag = true; state.dataGlobal->EndDayFlag = false; diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index 8b1c3587693..d48c7fd1fea 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -3542,7 +3542,7 @@ namespace SurfaceGeometry { s_ipsc->cCurrentModuleObject, surfTemp.Name, s_ipsc->cNumericFieldNames(1), - fmt::to_string(surfTemp.Sides))); + std::to_string(surfTemp.Sides))); ShowContinueError( state, std::format("...but {} were entered. Only the indicated {} will be used.", numSides, s_ipsc->cNumericFieldNames(1))); @@ -4301,7 +4301,7 @@ namespace SurfaceGeometry { s_ipsc->cCurrentModuleObject, surfTemp.Name, s_ipsc->cNumericFieldNames(2), - fmt::to_string(surfTemp.Sides))); + std::to_string(surfTemp.Sides))); ShowContinueError( state, std::format("...but {} were entered. Only the indicated {} will be used.", numSides, s_ipsc->cNumericFieldNames(2))); @@ -5268,7 +5268,7 @@ namespace SurfaceGeometry { s_ipsc->cCurrentModuleObject, surfTemp.Name, s_ipsc->cNumericFieldNames(3), - fmt::to_string(surfTemp.Sides))); + std::to_string(surfTemp.Sides))); ShowContinueError( state, std::format("...but {} were entered. Only the indicated {} will be used.", numSides, s_ipsc->cNumericFieldNames(3))); } @@ -13538,7 +13538,7 @@ namespace SurfaceGeometry { } // create unshaded construction with storm window - const std::string ChrNum = fmt::to_string(StormWinNum); + const std::string ChrNum = std::to_string(StormWinNum); std::string ConstrNameSt = "BARECONSTRUCTIONWITHSTORMWIN:" + ChrNum; // Name of unshaded construction with storm window // If this construction name already exists, set the surface's storm window construction number to it int ConstrNewSt = Util::FindItemInList(ConstrNameSt, diff --git a/src/EnergyPlus/SystemReports.cc b/src/EnergyPlus/SystemReports.cc index 741e96e2b8a..3af14062c95 100644 --- a/src/EnergyPlus/SystemReports.cc +++ b/src/EnergyPlus/SystemReports.cc @@ -4853,12 +4853,12 @@ void ReportAirLoopConnections(EnergyPlusData &state) std::string ChrOut; std::string ChrOut2; if (state.dataAirLoop->AirToOANodeInfo(Count).OASysInletNodeNum > 0) { - ChrOut = fmt::to_string(state.dataAirLoop->AirToOANodeInfo(Count).OASysInletNodeNum); + ChrOut = std::to_string(state.dataAirLoop->AirToOANodeInfo(Count).OASysInletNodeNum); } else { ChrOut = errstring; } if (state.dataAirLoop->AirToOANodeInfo(Count).OASysOutletNodeNum > 0) { - ChrOut2 = fmt::to_string(state.dataAirLoop->AirToOANodeInfo(Count).OASysOutletNodeNum); + ChrOut2 = std::to_string(state.dataAirLoop->AirToOANodeInfo(Count).OASysOutletNodeNum); } else { ChrOut2 = errstring; } diff --git a/src/EnergyPlus/UserDefinedComponents.cc b/src/EnergyPlus/UserDefinedComponents.cc index cc140648e6b..98bed3487f9 100644 --- a/src/EnergyPlus/UserDefinedComponents.cc +++ b/src/EnergyPlus/UserDefinedComponents.cc @@ -664,7 +664,7 @@ namespace UserDefinedComponents { for (int connectionIndex = 0; connectionIndex < NumPlantConnections; ++connectionIndex) { int const connectionNum = connectionIndex + 1; auto &plantConnection = userPlantComp.Loop[connectionIndex]; - const std::string LoopStr = fmt::to_string(connectionNum); + const std::string LoopStr = std::to_string(connectionNum); int aArgCount = connectionIndex * 6 + 3; plantConnection.InletNodeNum = Node::GetOnlySingleNode(state, cAlphaArgs(aArgCount), @@ -1160,7 +1160,7 @@ namespace UserDefinedComponents { static_cast(connectionNum), Node::ObjectIsNotParent); - const std::string LoopStr = fmt::to_string(connectionNum); + const std::string LoopStr = std::to_string(connectionNum); // model input related internal variables SetupEMSInternalVariable( state, "Inlet Temperature for Air Connection " + LoopStr, userCoil.Name, "[C]", airConnection.InletTemp); @@ -1737,7 +1737,7 @@ namespace UserDefinedComponents { plantConnection.HowLoadServed = DataPlant::HowMet::NoneDemand; plantConnection.FlowPriority = DataPlant::LoopFlowStatus::NeedyAndTurnsLoopOn; // Setup Internal Variables - const std::string LoopStr = fmt::to_string(connectionNum); + const std::string LoopStr = std::to_string(connectionNum); // model input related internal variables SetupEMSInternalVariable( state, "Inlet Temperature for Plant Connection " + LoopStr, userZoneAirHVAC.Name, "[C]", plantConnection.InletTemp); @@ -2275,7 +2275,7 @@ namespace UserDefinedComponents { plantConnection.HowLoadServed = DataPlant::HowMet::NoneDemand; plantConnection.FlowPriority = DataPlant::LoopFlowStatus::NeedyAndTurnsLoopOn; // Setup Internal Variables - const std::string LoopStr = fmt::to_string(connectionNum); + const std::string LoopStr = std::to_string(connectionNum); // model input related internal variables SetupEMSInternalVariable( state, "Inlet Temperature for Plant Connection " + LoopStr, userAirTerminal.Name, "[C]", plantConnection.InletTemp); diff --git a/src/EnergyPlus/UtilityRoutines.cc b/src/EnergyPlus/UtilityRoutines.cc index 9892a5595d9..beda8384bf9 100644 --- a/src/EnergyPlus/UtilityRoutines.cc +++ b/src/EnergyPlus/UtilityRoutines.cc @@ -421,12 +421,12 @@ int AbortEnergyPlus(EnergyPlusData &state) ShowRecurringErrors(state); SummarizeErrors(state); CloseMiscOpenFiles(state); - NumWarnings = fmt::to_string(state.dataErrTracking->TotalWarningErrors); - NumSevere = fmt::to_string(state.dataErrTracking->TotalSevereErrors); - NumWarningsDuringWarmup = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringWarmup); - NumSevereDuringWarmup = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringWarmup); - NumWarningsDuringSizing = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringSizing); - NumSevereDuringSizing = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringSizing); + NumWarnings = std::to_string(state.dataErrTracking->TotalWarningErrors); + NumSevere = std::to_string(state.dataErrTracking->TotalSevereErrors); + NumWarningsDuringWarmup = std::to_string(state.dataErrTracking->TotalWarningErrorsDuringWarmup); + NumSevereDuringWarmup = std::to_string(state.dataErrTracking->TotalSevereErrorsDuringWarmup); + NumWarningsDuringSizing = std::to_string(state.dataErrTracking->TotalWarningErrorsDuringSizing); + NumSevereDuringSizing = std::to_string(state.dataErrTracking->TotalSevereErrorsDuringSizing); // catch up with timings if in middle state.dataSysVars->runtimeTimer.tock(); @@ -530,17 +530,17 @@ int EndEnergyPlus(EnergyPlusData &state) ShowRecurringErrors(state); SummarizeErrors(state); CloseMiscOpenFiles(state); - NumWarnings = fmt::to_string(state.dataErrTracking->TotalWarningErrors); + NumWarnings = std::to_string(state.dataErrTracking->TotalWarningErrors); strip(NumWarnings); - NumSevere = fmt::to_string(state.dataErrTracking->TotalSevereErrors); + NumSevere = std::to_string(state.dataErrTracking->TotalSevereErrors); strip(NumSevere); - NumWarningsDuringWarmup = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringWarmup); + NumWarningsDuringWarmup = std::to_string(state.dataErrTracking->TotalWarningErrorsDuringWarmup); strip(NumWarningsDuringWarmup); - NumSevereDuringWarmup = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringWarmup); + NumSevereDuringWarmup = std::to_string(state.dataErrTracking->TotalSevereErrorsDuringWarmup); strip(NumSevereDuringWarmup); - NumWarningsDuringSizing = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringSizing); + NumWarningsDuringSizing = std::to_string(state.dataErrTracking->TotalWarningErrorsDuringSizing); strip(NumWarningsDuringSizing); - NumSevereDuringSizing = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringSizing); + NumSevereDuringSizing = std::to_string(state.dataErrTracking->TotalSevereErrorsDuringSizing); strip(NumSevereDuringSizing); state.dataSysVars->runtimeTimer.tock(); diff --git a/src/EnergyPlus/WaterThermalTanks.cc b/src/EnergyPlus/WaterThermalTanks.cc index 062ecd008ee..760206f00ee 100644 --- a/src/EnergyPlus/WaterThermalTanks.cc +++ b/src/EnergyPlus/WaterThermalTanks.cc @@ -9708,7 +9708,6 @@ void WaterThermalTankData::CalcHeatPumpWaterHeater(EnergyPlusData &state, bool c if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation) { if ((HPSetPointTemp - DeadBandTempDiff) <= this->SetPointTemp) { Real64 HPMinTemp = HPSetPointTemp - DeadBandTempDiff; - const std::string HPMinTempChar = fmt::to_string(HPMinTemp); ++HeatPump.HPSetPointError; // add logic for warmup, DataGlobals::KickOffSimulation and doing sizing here if (HeatPump.HPSetPointError == 1) { @@ -9718,7 +9717,7 @@ void WaterThermalTankData::CalcHeatPumpWaterHeater(EnergyPlusData &state, bool c "the heat pump water heater. Heat Pump will be disabled and simulation continues.", HeatPump.Type, HeatPump.Name)); - ShowContinueErrorTimeStamp(state, std::format(" ...Heat Pump cut-in temperature={}", HPMinTempChar)); + ShowContinueErrorTimeStamp(state, std::format(" ...Heat Pump cut-in temperature={}", HPMinTemp)); } else { ShowRecurringWarningErrorAtEnd(state, HeatPump.Type + " \"" + HeatPump.Name + diff --git a/src/EnergyPlus/WeatherManager.cc b/src/EnergyPlus/WeatherManager.cc index 13121955bd9..4507554ae8b 100644 --- a/src/EnergyPlus/WeatherManager.cc +++ b/src/EnergyPlus/WeatherManager.cc @@ -784,7 +784,7 @@ namespace Weather { state.dataEnvrn->DayOfYear = envCurr.StartJDay; state.dataEnvrn->DayOfMonth = envCurr.StartDay; state.dataGlobal->CalendarYear = envCurr.StartYear; - state.dataGlobal->CalendarYearChr = fmt::to_string(state.dataGlobal->CalendarYear); + state.dataGlobal->CalendarYearChr = std::to_string(state.dataGlobal->CalendarYear); state.dataEnvrn->Month = envCurr.StartMonth; state.dataGlobal->NumOfDayInEnvrn = envCurr.TotalDays; // Set day loop maximum from DataGlobals @@ -1023,7 +1023,7 @@ namespace Weather { StDate, EnDate, Sched::dayTypeNames[TWeekDay], - fmt::to_string(envCurr.TotalDays), + std::to_string(envCurr.TotalDays), "Use RunPeriod Specified Day", AlpUseDST, AlpUseSpec, @@ -2400,9 +2400,9 @@ namespace Weather { LiquidPrecip); } else if (WeatherDataLine.eof) { if (NumRewinds > 0) { - std::string date = fmt::to_string(thisEnviron.StartMonth) + '/' + fmt::to_string(thisEnviron.StartDay); + std::string date = std::to_string(thisEnviron.StartMonth) + '/' + std::to_string(thisEnviron.StartDay); if (thisEnviron.MatchYear) { - date += '/' + fmt::to_string(thisEnviron.StartYear); + date += '/' + std::to_string(thisEnviron.StartYear); } ShowSevereError(state, std::format("Multiple rewinds on EPW while searching for first day {}", date)); } else { @@ -4638,7 +4638,7 @@ namespace Weather { if (state.dataWeather->EnvironmentReportNbr != 1) { // problem ShowFatalError(state, "ReportOutputFileHeaders: Assigned report number for Environment title is not 1. Contact Support."); } - state.dataWeather->EnvironmentReportChr = fmt::to_string(state.dataWeather->EnvironmentReportNbr); + state.dataWeather->EnvironmentReportChr = std::to_string(state.dataWeather->EnvironmentReportNbr); strip(state.dataWeather->EnvironmentReportChr); print(state.files.eso, "{}{}\n", state.dataWeather->EnvironmentReportChr, EnvironmentString); print(state.files.mtr, "{}{}\n", state.dataWeather->EnvironmentReportChr, EnvironmentString); From 198ab457a3ad524083b74c42b9f24d22ce9e32cb Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 18:49:34 +0200 Subject: [PATCH 11/18] Remove unused OpenFmtStreamFile --- src/EnergyPlus/SimulationManager.cc | 19 ------------------- src/EnergyPlus/SimulationManager.hh | 2 -- 2 files changed, 21 deletions(-) diff --git a/src/EnergyPlus/SimulationManager.cc b/src/EnergyPlus/SimulationManager.cc index 1490e3dbd67..2a053402046 100644 --- a/src/EnergyPlus/SimulationManager.cc +++ b/src/EnergyPlus/SimulationManager.cc @@ -1785,25 +1785,6 @@ namespace SimulationManager { return result; } - std::unique_ptr OpenFmtStreamFile(EnergyPlusData &state, const fs::path &filePath) - { - std::unique_ptr result = nullptr; -#ifdef _WIN32 - std::string filePathStr = FileSystem::toString(filePath); - const char *path = filePathStr.c_str(); -#else - const char *path = filePath.c_str(); -#endif - try { - auto f = fmt::output_file(path, fmt::buffer_size = (2 << 17)); // (AUTO_OK_OBJ) - result = std::make_unique(std::move(f)); - } catch (const std::system_error &error) { - ShowSevereError(state, error.what()); - ShowFatalError(state, std::format("OpenOutputFiles: Could not open file {} for output (write).", filePath)); - } - return result; - } - void OpenOutputFiles(EnergyPlusData &state) { diff --git a/src/EnergyPlus/SimulationManager.hh b/src/EnergyPlus/SimulationManager.hh index 3400eb20fab..cfa39eee7ff 100644 --- a/src/EnergyPlus/SimulationManager.hh +++ b/src/EnergyPlus/SimulationManager.hh @@ -75,8 +75,6 @@ namespace SimulationManager { std::unique_ptr OpenStreamFile(EnergyPlusData &state, const fs::path &fileName, std::ios_base::openmode mode = (std::ios_base::out | std::ios_base::trunc)); - std::unique_ptr OpenFmtStreamFile(EnergyPlusData &state, const fs::path &filePath); - void OpenOutputFiles(EnergyPlusData &state); void CloseOutputFiles(EnergyPlusData &state); From 7434d5adb7c53c0966470799b617bbc45a4bfb3f Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 20:35:25 +0200 Subject: [PATCH 12/18] revert 25c60c2bb3aad4b5fcbadd67ad27ec5c9de08c2a: I had ommited it on purpose, so I don't have to publicly expose Formatters.hh 25c60c2bb3aad4b5fcbadd67ad27ec5c9de08c2a --- src/EnergyPlus/FileSystem.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EnergyPlus/FileSystem.hh b/src/EnergyPlus/FileSystem.hh index 073051e85d8..354534cc47c 100644 --- a/src/EnergyPlus/FileSystem.hh +++ b/src/EnergyPlus/FileSystem.hh @@ -236,7 +236,7 @@ namespace FileSystem { auto close_file = [](FILE *f) { fclose(f); }; auto holder = std::unique_ptr(fopen(path, "wb"), close_file); if (!holder) { - throw FatalError(std::format("Could not open file: {}", filePath)); + throw FatalError(std::format("Could not open file: {}", filePath.string())); } auto f = holder.get(); From d2fa2fd25f3bf04f96120ffaa2bf2d8a087e35e9 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 22:48:43 +0200 Subject: [PATCH 13/18] For older clang/apple-clang, use a templated FormatContext and no trailing return cf https://github.com/llvm/llvm-project/issues/66466#issuecomment-1720807809 CI test_pull_requests.yml uses macos-14, with XCode 15.4, so that's like around Clang 16 or 17... --- src/EnergyPlus/FileSystem.hh | 7 +++++-- src/EnergyPlus/Formatters.hh | 4 ++-- src/EnergyPlus/PluginManager.cc | 2 +- src/EnergyPlus/PythonEngine.cc | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/EnergyPlus/FileSystem.hh b/src/EnergyPlus/FileSystem.hh index 354534cc47c..fcab824294c 100644 --- a/src/EnergyPlus/FileSystem.hh +++ b/src/EnergyPlus/FileSystem.hh @@ -335,14 +335,17 @@ template <> struct std::formatter // Check if reached the end of the range: if (it != end && *it != '}') { - throw format_error("invalid format"); + throw std::format_error("invalid format"); }; // Return an iterator past the end of the parsed range: return it; } - auto format(const fs::path &p, std::format_context &ctx) const -> std::format_context::iterator + // For older clang/apple-clang, use a templated FormatContext and no trailing return + // https://github.com/llvm/llvm-project/issues/66466#issuecomment-1720807809 + // auto format(const fs::path &p, std::format_context &ctx) const -> std::format_context::iterator + template auto format(const fs::path &p, FormatContext &ctx) const { return std::format_to(ctx.out(), "{}", generic_string ? EnergyPlus::FileSystem::toGenericString(p) : EnergyPlus::FileSystem::toString(p)); } diff --git a/src/EnergyPlus/Formatters.hh b/src/EnergyPlus/Formatters.hh index 1279558235f..2ade4245218 100644 --- a/src/EnergyPlus/Formatters.hh +++ b/src/EnergyPlus/Formatters.hh @@ -91,7 +91,7 @@ template struct std::formatter return element_formatter.parse(ctx); } - auto format(const Container &v, std::format_context &ctx) const -> std::format_context::iterator + template auto format(const Container &v, FormatContext &ctx) const { constexpr char open = set_like ? '{' : '['; constexpr char close = set_like ? '}' : ']'; @@ -152,7 +152,7 @@ template struct std::formatter<::detail::format_join_view> return element_formatter.parse(ctx); } - auto format(const ::detail::format_join_view &jv, std::format_context &ctx) const -> std::format_context::iterator + template auto format(const ::detail::format_join_view &jv, FormatContext &ctx) const { auto it = ctx.out(); bool first = true; diff --git a/src/EnergyPlus/PluginManager.cc b/src/EnergyPlus/PluginManager.cc index 98547e961ce..6c84695d210 100644 --- a/src/EnergyPlus/PluginManager.cc +++ b/src/EnergyPlus/PluginManager.cc @@ -86,7 +86,7 @@ template <> struct std::formatter return ctx.begin(); } - auto format(const PyStatus &status, std::format_context &ctx) const -> std::format_context::iterator + template auto format(const PyStatus &status, FormatContext &ctx) const { if (PyStatus_Exception(status) == 0) { return ctx.out(); diff --git a/src/EnergyPlus/PythonEngine.cc b/src/EnergyPlus/PythonEngine.cc index 2c6d73c1ea6..075d410007a 100644 --- a/src/EnergyPlus/PythonEngine.cc +++ b/src/EnergyPlus/PythonEngine.cc @@ -80,7 +80,7 @@ template <> struct std::formatter return ctx.begin(); } - auto format(const PyStatus &status, std::format_context &ctx) const -> std::format_context::iterator + template auto format(const PyStatus &status, FormatContext &ctx) const { if (PyStatus_Exception(status) == 0) { return ctx.out(); From 3755a547ebdb05254f66756267353b3f8be65da2 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 23:01:11 +0200 Subject: [PATCH 14/18] Messed up the logic in one test --- tst/EnergyPlus/unit/Formatters.unit.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/EnergyPlus/unit/Formatters.unit.cc b/tst/EnergyPlus/unit/Formatters.unit.cc index dee9071d65a..b9a2ad06cde 100644 --- a/tst/EnergyPlus/unit/Formatters.unit.cc +++ b/tst/EnergyPlus/unit/Formatters.unit.cc @@ -72,7 +72,7 @@ TEST(Formatters, Formatters_Path) EXPECT_EQ("foo\\bar\\baz", std::format("{}", fs::path("foo\\bar\\baz"))); EXPECT_EQ("foo/bar/baz", std::format("{:g}", fs::path("foo/bar/baz"))); #ifdef _WIN32 - EXPECT_EQ("foo\\bar\\baz", std::format("{:g}", fs::path("foo/bar/baz"))); + EXPECT_EQ("foo/bar/baz", std::format("{:g}", fs::path("foo\\bar\\baz"))); #endif } From efd49216361a8b28c84ba1eaf488ca2a4ec460cb Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 23:29:31 +0200 Subject: [PATCH 15/18] Botched one replacement in be3813a6adc22730dbf72f987cdd39170c7f2fc3: forgot a comma --- src/EnergyPlus/ResultsFramework.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EnergyPlus/ResultsFramework.cc b/src/EnergyPlus/ResultsFramework.cc index 15bdbb9c8b1..9c38ae2dfba 100644 --- a/src/EnergyPlus/ResultsFramework.cc +++ b/src/EnergyPlus/ResultsFramework.cc @@ -857,7 +857,7 @@ namespace ResultsFramework { last = (result + 1).base(); } - print(outputFile, "{}", std::format("{}", EnergyPlus::join(std::ranges::subrange(item.second.begin(), last), ","))); + print(outputFile, "{},", std::format("{}", EnergyPlus::join(std::ranges::subrange(item.second.begin(), last), ","))); print(outputFile, "{}\n", *last); } From 7d63892c459c032b572736b6ae075fb26c921b59 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 8 Jun 2026 23:34:51 +0200 Subject: [PATCH 16/18] remove some unused fmt headers --- src/EnergyPlus/InputProcessing/CsvParser.cc | 1 - src/EnergyPlus/InputProcessing/InputProcessor.cc | 1 - src/EnergyPlus/Timer.cc | 3 --- 3 files changed, 5 deletions(-) diff --git a/src/EnergyPlus/InputProcessing/CsvParser.cc b/src/EnergyPlus/InputProcessing/CsvParser.cc index 747558ecb85..a57be755889 100644 --- a/src/EnergyPlus/InputProcessing/CsvParser.cc +++ b/src/EnergyPlus/InputProcessing/CsvParser.cc @@ -50,7 +50,6 @@ // Third Party Headers #include -#include // EnergyPlus Headers #include diff --git a/src/EnergyPlus/InputProcessing/InputProcessor.cc b/src/EnergyPlus/InputProcessing/InputProcessor.cc index 235d32ed168..77e54754110 100644 --- a/src/EnergyPlus/InputProcessing/InputProcessor.cc +++ b/src/EnergyPlus/InputProcessing/InputProcessor.cc @@ -59,7 +59,6 @@ // Third Party Headers #include -#include #include #include diff --git a/src/EnergyPlus/Timer.cc b/src/EnergyPlus/Timer.cc index 5f6478c8e66..5335b61172e 100644 --- a/src/EnergyPlus/Timer.cc +++ b/src/EnergyPlus/Timer.cc @@ -51,9 +51,6 @@ #endif #include -// Third Party Headers -#include - // EnergyPlus Headers #include From 2261b52e6736e529391a5bd68f22f4fe546fce59 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Tue, 9 Jun 2026 03:06:32 +0200 Subject: [PATCH 17/18] u64toa caveat issue explaining the arm64 test failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit u64toa writes digits into the buffer but does NOT null-terminate — it relies on the = {} zero-initialization. So s IS a valid null-terminated string. The bug is that std::format("{}", s) where s is char[129] — on Apple's libc++ (arm64) the char[N] array type isn't decaying to const char*, it's being matched as a range and outputting all 129 bytes including the null padding. --- src/EnergyPlus/InputProcessing/IdfParser.cc | 6 ++---- src/EnergyPlus/InputProcessing/InputProcessor.cc | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/EnergyPlus/InputProcessing/IdfParser.cc b/src/EnergyPlus/InputProcessing/IdfParser.cc index 9442f7c9c59..7ea55960b3a 100644 --- a/src/EnergyPlus/InputProcessing/IdfParser.cc +++ b/src/EnergyPlus/InputProcessing/IdfParser.cc @@ -279,8 +279,7 @@ json IdfParser::parse_idf(std::string_view idf, size_t &index, bool &success, js success = false; continue; } - u64toa(root[obj_name].size() + 1, s); - std::string name = std::format("{} {}", obj_name, s); + std::string name = std::format("{} {}", obj_name, root[obj_name].size() + 1); if (!obj.is_null()) { auto const name_iter = obj.find("name"); @@ -445,8 +444,7 @@ json IdfParser::parse_object( if (field == "name") { root[field] = parse_string(idf, index); } else { - u64toa(cur_line_num, s); - errors_.emplace_back(std::format("Line: {} - Field \"{}\" was not found.", s, field)); + errors_.emplace_back(std::format("Line: {} - Field \"{}\" was not found.", cur_line_num, field)); } } else { json val = parse_value(idf, index, success, find_field_iter.value()); diff --git a/src/EnergyPlus/InputProcessing/InputProcessor.cc b/src/EnergyPlus/InputProcessing/InputProcessor.cc index 77e54754110..b593c4506d7 100644 --- a/src/EnergyPlus/InputProcessing/InputProcessor.cc +++ b/src/EnergyPlus/InputProcessing/InputProcessor.cc @@ -1730,8 +1730,7 @@ void InputProcessor::reportOrphanRecordObjects(EnergyPlusData &state) } if ((!unusedInputs.empty()) && !state.dataGlobal->DisplayUnusedObjects) { - u64toa(unusedInputs.size(), s); - ShowMessage(state, "There are " + std::string(s) + " unused objects in input."); + ShowMessage(state, std::format("There are {} unused objects in input.", unusedInputs.size())); ShowMessage(state, "Use Output:Diagnostics,DisplayUnusedObjects; to see them."); } } From 2201844121f86a13c28fb8e8826dd3932449f754 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 10 Jun 2026 22:58:59 +0200 Subject: [PATCH 18/18] Add cstring include for std::memmove in dtoa.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit decent CI has error third_party/milo/dtoa.h:161:14 ‘memmove’ is not a member of ‘std’; did you mean ‘wmemmove’? --- third_party/milo/dtoa.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/third_party/milo/dtoa.h b/third_party/milo/dtoa.h index 7898b16e62c..d4575ff08fb 100644 --- a/third_party/milo/dtoa.h +++ b/third_party/milo/dtoa.h @@ -23,6 +23,8 @@ #include "diyfp.h" #include "ieee754.h" +#include // std::memmove + inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { while (rest < wp_w && delta - rest >= ten_kappa && (rest + ten_kappa < wp_w || /// closer