Created
November 13, 2024 19:11
-
-
Save adamkewley/ea5ede7f675ce5e1b834d0887f27bde4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <oscar/oscar.h> | |
#include <charconv> | |
#include <filesystem> | |
#include <fstream> | |
#include <regex> | |
#include <sstream> | |
#include <stdexcept> | |
#include <string_view> | |
#include <span> | |
using namespace osc; | |
namespace | |
{ | |
struct State final { | |
std::regex data_array_opening_pattern{R"(<DataArray type="Float32"[^>]+>)"}; | |
std::regex data_array_closing_pattern{R"(</DataArray>)"}; | |
}; | |
std::string slurp(const std::filesystem::path& p) | |
{ | |
std::ifstream f{p, std::ios_base::binary}; | |
f.exceptions(std::istream::failbit | std::istream::badbit); | |
std::string rv; | |
// reserve memory | |
f.seekg(0, std::ios::end); | |
if (const auto pos = f.tellg(); pos > 0) { | |
rv.reserve(static_cast<size_t>(pos)); | |
} | |
f.seekg(0, std::ios::beg); | |
// then assign to it via an iterator | |
rv.assign((std::istreambuf_iterator<char>{f}), std::istreambuf_iterator<char>{}); | |
return rv; | |
} | |
void write_to_file(const std::filesystem::path& p, std::string_view sv) | |
{ | |
std::ofstream f{p, std::ios_base::binary}; | |
f.exceptions(std::istream::failbit | std::istream::badbit); | |
f << sv; | |
} | |
void emit_reparsed_dataarray_content(std::string_view sv, std::stringstream& out) | |
{ | |
while (not sv.empty()) { | |
if (std::isspace(sv.front())) { | |
// skip whitespace | |
out << sv.front(); | |
sv = sv.substr(1); | |
} | |
else { | |
// parse as floating-point number | |
float value = 0.0f; | |
std::from_chars_result fromchars_result = std::from_chars(sv.data(), sv.data() + sv.size(), value); | |
if (fromchars_result.ec != std::errc{}) { | |
throw std::runtime_error{"parsing error"}; | |
} | |
std::array<char, 128> buffer{}; | |
std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); | |
out << buffer.data(); | |
sv = sv.substr(fromchars_result.ptr - sv.data()); | |
} | |
} | |
} | |
void process_vtp(const State& s, const std::filesystem::path& vtp_path) | |
{ | |
log_info("processing %s", vtp_path.string().c_str()); | |
std::stringstream out; | |
const std::string content = slurp(vtp_path); | |
int count = 0; | |
for (auto it = std::sregex_iterator{content.begin(), content.end(), s.data_array_opening_pattern}; it != std::sregex_iterator{}; ++it) { | |
const std::smatch opening_tag_match = *it; | |
std::smatch closing_tag_match; | |
if (not std::regex_search(opening_tag_match.suffix().first, opening_tag_match.suffix().second, closing_tag_match, s.data_array_closing_pattern)) { | |
throw std::runtime_error{"cannot find closing tag"}; | |
} | |
// this is the bit that needs to be replaced | |
std::string_view content_span{&*opening_tag_match.suffix().first, &*&*closing_tag_match[0].first}; | |
out << opening_tag_match.prefix(); | |
out << opening_tag_match.str(); | |
emit_reparsed_dataarray_content(content_span, out); | |
out << closing_tag_match.str(); | |
out << closing_tag_match.suffix(); | |
++count; | |
} | |
if (count != 1) { | |
throw std::runtime_error{"unexpected number of <DataArray> elements"}; | |
} | |
write_to_file(vtp_path, std::move(out).str()); | |
} | |
} | |
int main(int argc, char** argv) | |
{ | |
try { | |
State state; | |
for (int i = 1; i < argc; ++i) { | |
process_vtp(state, argv[i]); | |
} | |
return 0; | |
} | |
catch (std::exception& ex) { | |
std::cerr << ex.what() << std::endl; | |
throw; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment