Skip to content

Commit

Permalink
Preserve type of strings that look like numbers when emitting YAML
Browse files Browse the repository at this point in the history
  • Loading branch information
speth committed Jul 27, 2024
1 parent bfcd50b commit 948daa8
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 2 deletions.
35 changes: 35 additions & 0 deletions src/base/AnyMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,15 @@ YAML::Emitter& operator<<(YAML::Emitter& out, const AnyMap& rhs)
for (const auto& [name, value] : rhs.ordered()) {
string valueStr;
bool foundType = true;
bool needsQuotes = false;
if (value.is<double>()) {
valueStr = formatDouble(value.asDouble(), getPrecision(value));
} else if (value.is<string>()) {
valueStr = value.asString();
if (isFloat(valueStr)) {
// Quote strings that look like numbers to preserve their type
needsQuotes = true;
}
} else if (value.is<long int>()) {
valueStr = fmt::format("{}", value.asInt());
} else if (value.is<bool>()) {
Expand All @@ -303,6 +308,9 @@ YAML::Emitter& operator<<(YAML::Emitter& out, const AnyMap& rhs)
width = 15;
}
out << name;
if (needsQuotes) {
out << YAML::SingleQuoted;
}
out << valueStr;
width += name.size() + valueStr.size() + 4;
} else {
Expand All @@ -327,6 +335,9 @@ YAML::Emitter& operator<<(YAML::Emitter& out, const AnyMap& rhs)
//! Write YAML strings spanning multiple lines if input includes endline '\n'
void emitString(YAML::Emitter& out, const string& str0) {
if (str0.rfind('\n') == string::npos) {
if (isFloat(str0)) {
out << YAML::SingleQuoted;
}
out << str0;
return;
}
Expand Down Expand Up @@ -360,6 +371,30 @@ void emitFlowVector(YAML::Emitter& out, const vector<double>& v, long int precis
out << YAML::EndSeq;
}

//! Write a vector in YAML "flow" style, wrapping lines to avoid exceeding the
//! preferred maximum line length (set by `max_line_length`). Specialized for
//! `vector<string>` to quote strings that look like numeric values
void emitFlowVector(YAML::Emitter& out, const vector<string>& v)
{
out << YAML::Flow;
out << YAML::BeginSeq;
size_t width = 15; // wild guess, but no better value is available
for (const string& x : v) {
// Wrap to the next line if this item would exceed the target line length
if (width + x.size() > max_line_length) {
out << YAML::Newline;
width = 15;
}
if (isFloat(x)) {
out << SingleQuoted;
width += 2;
}
out << x;
width += x.size() + 2;
}
out << YAML::EndSeq;
}

//! Write a vector in YAML "flow" style, wrapping lines to avoid exceeding the
//! preferred maximum line length (set by `max_line_length`).
template <typename T>
Expand Down
15 changes: 13 additions & 2 deletions test/python/test_composite.py
Original file line number Diff line number Diff line change
Expand Up @@ -1222,8 +1222,14 @@ def test_yaml_strings(self):
gas = ct.Solution('h2o2.yaml', transport_model=None)
desc = " Line 1\n Line 2\n Line 3"
note = "First\n\nSecond\n Third"
note2 = "123199" # scalar string
note3 = ["77", "888", "9"] # list with all strings
note4 = ["111213", 444, "5.10"] # mixed types
gas.update_user_header({"description": desc})
gas.species(2).update_user_data({"note": note})
gas.species(1).update_user_data({"note": note})
gas.species(2).update_user_data({"note": note2})
gas.species(3).update_user_data({"note": note3})
gas.species(4).update_user_data({"note": note4})

gas.write_yaml(self.test_work_path / "h2o2-generated-user-header.yaml")
gas2 = ct.Solution(self.test_work_path / "h2o2-generated-user-header.yaml")
Expand All @@ -1232,7 +1238,12 @@ def test_yaml_strings(self):
# (element annotated with '|-' instead of just '|') but this doesn't seem to be
# possible as of yaml-cpp 0.8.0.
assert gas2.input_header["description"].strip() == desc.strip()
assert gas2.species(2).input_data["note"].strip() == note.strip()
assert gas2.species(1).input_data["note"].strip() == note.strip()

# number-like strings should be preserved as strings
assert gas2.species(2).input_data["note"] == note2
assert gas2.species(3).input_data["note"] == note3
assert gas2.species(4).input_data["note"] == note4


class TestSpeciesSerialization(utilities.CanteraTest):
Expand Down

0 comments on commit 948daa8

Please sign in to comment.