OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
InputParseUtils.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2//
3// Copyright 2026 Caleb Buahin
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
31
32#ifndef OPENSWMM_ENGINE_INPUT_PARSE_UTILS_HPP
33#define OPENSWMM_ENGINE_INPUT_PARSE_UTILS_HPP
34
35#include <string_view>
36#include <string>
37#include <vector>
38#include <charconv>
40#include "../core/DateTime.hpp"
42#include "../data/NameIndex.hpp"
43
44namespace openswmm::input {
45
46// ============================================================================
47// Numeric parsing
48// ============================================================================
49
53inline double to_double(std::string_view sv, double def = 0.0) noexcept {
54 double v = def;
55 openswmm::from_chars_double(sv.data(), sv.data() + sv.size(), v);
56 return v;
57}
58
62inline int to_int(std::string_view sv, int def = 0) noexcept {
63 int v = def;
64 auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), v);
65 if (ec != std::errc{}) return def;
66 return v;
67}
68
69// ============================================================================
70// Date/time parsing
71// ============================================================================
72
76inline double parse_date(std::string_view sv) {
77 unsigned m = 0, d = 0, y = 0;
78 const char* p = sv.data();
79 const char* end = sv.data() + sv.size();
80
81 auto read_uint = [&](unsigned& out) -> bool {
82 auto [np, ec] = std::from_chars(p, end, out);
83 if (ec != std::errc{}) return false;
84 p = np;
85 return true;
86 };
87
88 if (!read_uint(m)) return 0.0;
89 if (p < end && *p == '/') ++p; else return 0.0;
90 if (!read_uint(d)) return 0.0;
91 if (p < end && *p == '/') ++p; else return 0.0;
92 if (!read_uint(y)) return 0.0;
93
94 return datetime::encodeDate(static_cast<int>(y),
95 static_cast<int>(m),
96 static_cast<int>(d));
97}
98
107inline double parse_time_seconds(std::string_view sv) {
108 // Try plain number first
109 double val = 0.0;
110 auto [ptr, ec] = openswmm::from_chars_double(sv.data(), sv.data() + sv.size(), val);
111 if (ec == std::errc{} && ptr == sv.data() + sv.size()) {
112 return val; // plain number = seconds
113 }
114
115 // Try HH:MM:SS or HH:MM
116 unsigned h = 0, m = 0;
117 double s = 0.0;
118 const char* p = sv.data();
119 const char* end = sv.data() + sv.size();
120
121 auto read_uint = [&](unsigned& out) -> bool {
122 auto [np, nec] = std::from_chars(p, end, out);
123 if (nec != std::errc{}) return false;
124 p = np;
125 return true;
126 };
127
128 if (!read_uint(h)) return 0.0;
129 if (p < end && *p == ':') {
130 ++p;
131 if (!read_uint(m)) return static_cast<double>(h);
132 if (p < end && *p == ':') {
133 ++p;
135 }
136 }
137 return h * 3600.0 + m * 60.0 + s;
138}
139
145inline double parse_time_day_fraction(std::string_view sv) {
146 unsigned h = 0, m = 0, s = 0;
147 const char* p = sv.data();
148 const char* end = sv.data() + sv.size();
149
150 auto read_uint = [&](unsigned& out) -> bool {
151 auto [np, ec] = std::from_chars(p, end, out);
152 if (ec != std::errc{}) return false;
153 p = np;
154 return true;
155 };
156
157 if (!read_uint(h)) return 0.0;
158 if (p < end && *p == ':') ++p;
159 read_uint(m);
160 if (p < end && *p == ':') ++p;
161 read_uint(s);
162
163 return datetime::encodeTime(static_cast<int>(h),
164 static_cast<int>(m),
165 static_cast<int>(s));
166}
167
175inline double parse_datetime(std::string_view date_sv, std::string_view time_sv) {
176 return parse_date(date_sv) + parse_time_day_fraction(time_sv);
177}
178
179// ============================================================================
180// Object registration
181// ============================================================================
182
200inline int add_unique(NameIndex& reg, const std::string& name,
201 std::vector<std::string>& errors) {
202 const int idx = reg.try_add(name);
203 if (idx < 0) {
204 const std::string* canon = reg.canonical(name);
205 if (canon != nullptr && *canon != name) {
206 errors.push_back(format_error(ERR_DUP_NAME, name,
207 "(matches existing ID '" + *canon +
208 "'; names are case-insensitive)"));
209 } else {
210 errors.push_back(format_error(ERR_DUP_NAME, name));
211 }
212 }
213 return idx;
214}
215
216} /* namespace openswmm::input */
217
218#endif /* OPENSWMM_ENGINE_INPUT_PARSE_UTILS_HPP */
DateTime utility functions — numerically identical to legacy datetime.c.
Legacy-compatible error and warning codes with description lookup.
O(1) name-to-index lookup for SWMM objects.
Portable from_chars for floating-point types.
Bidirectional name↔index registry for SWMM objects.
Definition NameIndex.hpp:71
int try_add(const std::string &name)
Non-throwing add.
Definition NameIndex.hpp:104
const std::string * canonical(std::string_view name) const noexcept
Stored (original) spelling for a case-insensitive match.
Definition NameIndex.hpp:144
DateTime encodeTime(int hour, int minute, int second)
Encode hour:minute:second to fractional day.
Definition DateTime.hpp:110
DateTime encodeDate(int year, int month, int day)
Encode year-month-day to DateTime.
Definition DateTime.hpp:92
Definition CatchmentHandler.cpp:69
double parse_datetime(std::string_view date_sv, std::string_view time_sv)
Parse a combined date + time pair to a DateTime.
Definition InputParseUtils.hpp:175
double parse_time_day_fraction(std::string_view sv)
Parse a time string HH:MM:SS to a fractional day (DateTime).
Definition InputParseUtils.hpp:145
double to_double(std::string_view sv, double def=0.0) noexcept
Parse a double from a string_view, returning a default on failure.
Definition InputParseUtils.hpp:53
double parse_time_seconds(std::string_view sv)
Parse a time string to seconds.
Definition InputParseUtils.hpp:107
int to_int(std::string_view sv, int def=0) noexcept
Parse an int from a string_view, returning a default on failure.
Definition InputParseUtils.hpp:62
std::string format_error(int code, std::string_view name="")
Format an error message with object name substitution.
Definition ErrorCodes.cpp:276
int add_unique(NameIndex &reg, const std::string &name, std::vector< std::string > &errors)
Register a new object definition, rejecting duplicates like legacy.
Definition InputParseUtils.hpp:200
double parse_date(std::string_view sv)
Parse a date string in MM/DD/YYYY format to a DateTime (decimal days).
Definition InputParseUtils.hpp:76
std::from_chars_result from_chars_double(const char *first, const char *last, double &value) noexcept
Locale-independent parse of a double from a character range.
Definition charconv_compat.hpp:70
@ ERR_DUP_NAME
duplicate ID name s
Definition ErrorCodes.hpp:122
double * y
Definition odesolve.c:28