OGS
MediaCreation.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include <spdlog/fmt/ranges.h>
5
6#include <range/v3/action/sort.hpp>
7#include <range/v3/action/unique.hpp>
8#include <range/v3/range/conversion.hpp>
9#include <range/v3/view/iota.hpp>
10#include <range/v3/view/unique.hpp>
11
12#include "BaseLib/Logging.h"
13#include "BaseLib/StringTools.h"
15
16namespace MaterialLib
17{
18
21void checkForWhitespaces(std::string_view part)
22{
23 if (std::ranges::any_of(
24 part,
25 [](char c) { return std::isspace(static_cast<unsigned char>(c)); }))
26 {
28 "Whitespace is not allowed in ranges. Use 'start:end' without "
29 "spaces around the colon.");
30 }
31}
32
35auto expandRange(int start, int end)
36{
37 if (end < start)
38 {
40 "Invalid range '{}:{}'. The end must be greater than or equal "
41 "to the start.",
42 start, end);
43 }
44 return ranges::views::iota(start, end + 1);
45}
46
47std::vector<int> splitMaterialIdString(std::string const& material_id_string)
48{
49 auto const material_ids_strings =
50 BaseLib::splitString(material_id_string, ',');
51
52 // Pre-allocate with estimated capacity (simplified heuristic)
53 std::vector<int> material_ids;
54 material_ids.reserve(material_ids_strings.size());
55
56 for (std::string mid_str : material_ids_strings)
57 {
58 // Trim leading and trailing whitespace
59 BaseLib::trim(mid_str);
60
61 auto const parts =
62 BaseLib::splitString(mid_str, ':') | ranges::to_vector;
63 if (parts.size() == 2)
64 {
65 checkForWhitespaces(parts[0]);
66 auto const start_id = BaseLib::parseInteger(parts[0]);
67 if (!start_id)
68 {
69 OGS_FATAL("Could not parse material ID: {}", start_id.error());
70 }
71 checkForWhitespaces(parts[1]);
72 auto const end_id = BaseLib::parseInteger(parts[1]);
73 if (!end_id)
74 {
75 OGS_FATAL("Could not parse material ID: {}", end_id.error());
76 }
77 ranges::copy(expandRange(*start_id, *end_id),
78 std::back_inserter(material_ids));
79 }
80 else if (parts.size() == 1)
81 {
82 auto const material_id = BaseLib::parseInteger(mid_str);
83 if (!material_id)
84 {
85 OGS_FATAL("Could not parse material ID: {}",
86 material_id.error());
87 }
88 material_ids.push_back(*material_id);
89 }
90 else
91 {
93 "Could not parse material ID from '{}'. Invalid range format. "
94 "Use 'start:end' for ranges or a single integer.",
95 mid_str);
96 }
97 }
98
99 return material_ids;
100}
101
102std::vector<int> parseMaterialIdString(
103 std::string const& material_id_string,
104 MeshLib::PropertyVector<int> const* const material_ids)
105{
106 if (material_id_string == "*")
107 {
108 if (material_ids == nullptr)
109 {
110 OGS_FATAL(
111 "MaterialIDs property is not defined in the mesh but it is "
112 "required to parse '*' definition.");
113 }
114
115 std::vector<int> const material_ids_of_this_medium =
116 *material_ids | ranges::views::unique | ranges::to_vector |
117 ranges::actions::sort | ranges::actions::unique |
118 ranges::to<std::vector>;
119 DBUG("Catch all medium definition for material ids {}.",
120 fmt::join(material_ids_of_this_medium, ", "));
121 return material_ids_of_this_medium;
122 }
123
124 // Usual case of ids or ranges separated by comma.
125 return splitMaterialIdString(material_id_string);
126}
127
128} // namespace MaterialLib
#define OGS_FATAL(...)
Definition Error.h:19
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
std::expected< int, std::string > parseInteger(std::string_view str)
void trim(std::string &str, char ch)
std::vector< std::string > splitString(std::string const &str)
void checkForWhitespaces(std::string_view part)
auto expandRange(int start, int end)
std::vector< int > splitMaterialIdString(std::string const &material_id_string)
std::vector< int > parseMaterialIdString(std::string const &material_id_string, MeshLib::PropertyVector< int > const *const material_ids)