Skip to content

Commit

Permalink
[GRM] Export an internal attribute in XML containing internals
Browse files Browse the repository at this point in the history
  • Loading branch information
IngoMeyer441 committed Jul 21, 2024
1 parent d11302b commit 120e699
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 10 deletions.
5 changes: 4 additions & 1 deletion lib/grm/grplot/grplot_widget.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,10 @@ void GRPlotWidget::AttributeEditEvent()
clicked.clear();
if (getenv("GRM_DEBUG"))
{
std::cerr << toXML(grm_get_document_root(), GRM::SerializerOptions{std::string(2, ' '), true}) << "\n";
std::cerr << toXML(grm_get_document_root(),
GRM::SerializerOptions{std::string(2, ' '),
GRM::SerializerOptions::InternalAttributesFormat::Plain})
<< "\n";
}
reset_pixmap();
}
Expand Down
12 changes: 10 additions & 2 deletions lib/grm/include/grm/dom_render/graphics_tree/util.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@ class Node;

struct EXPORT SerializerOptions
{
enum class InternalAttributesFormat
{
None, // Hide internal attributes
Plain, // Export internal attributes like public attributes
Obfuscated, // Collect internal attributes and store them into a special `internal` attribute, BSON+Base64 encoded
};

std::string indent = "";
bool show_hidden = false;
InternalAttributesFormat internal_attribute_format = InternalAttributesFormat::None;
};
EXPORT std::string
toXML(const std::shared_ptr<const Node> &node, const SerializerOptions &options = {"", false},
toXML(const std::shared_ptr<const Node> &node,
const SerializerOptions &options = {"", SerializerOptions::InternalAttributesFormat::None},
std::optional<std::function<bool(const std::string &attribute_name, const GRM::Element &element,
std::optional<std::string> &new_attribute_name)>>
attribute_filter = std::nullopt);
Expand Down
61 changes: 60 additions & 1 deletion lib/grm/src/grm/dom_render/graphics_tree/util.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include <sstream>
#include <algorithm>
#include <cmath>
#include "grm/base64_int.h"
#include "grm/bson_int.h"
#include "grm/memwriter_int.h"
#include "grm/utilcpp_int.hxx"

static std::string escapeXMLAttribute(std::string_view attribute)
Expand Down Expand Up @@ -61,6 +64,7 @@ elementToXML(std::stringstream &os, const std::shared_ptr<const GRM::Element> &e
std::optional<std::string> &new_attribute_name)>>
attribute_filter)
{
std::map<std::string, GRM::Value> internal_attributes;
os << indent << "<" << element->localName();
auto attribute_names_set = element->getAttributeNames();
std::vector<std::string> attribute_names{attribute_names_set.begin(), attribute_names_set.end()};
Expand All @@ -82,7 +86,19 @@ elementToXML(std::stringstream &os, const std::shared_ptr<const GRM::Element> &e
{
attribute_name = *new_attribute_name;
}
if (!options.show_hidden && starts_with(attribute_name.get(), "_")) continue;
if (starts_with(attribute_name.get(), "_"))
{
switch (options.internal_attribute_format)
{
case GRM::SerializerOptions::InternalAttributesFormat::None:
continue;
case GRM::SerializerOptions::InternalAttributesFormat::Obfuscated:
internal_attributes[attribute_name.get()] = element->getAttribute(original_attribute_name);
continue;
default:
break;
}
}

auto value = (std::string)element->getAttribute(original_attribute_name);
if (value == "nan")
Expand All @@ -108,6 +124,49 @@ elementToXML(std::stringstream &os, const std::shared_ptr<const GRM::Element> &e
os << " " << attribute_name.get() << "=\"" << escapeXMLAttribute(value) << "\"";
}
}
if (options.internal_attribute_format == GRM::SerializerOptions::InternalAttributesFormat::Obfuscated &&
!internal_attributes.empty())
{
auto memwriter = std::unique_ptr<memwriter_t, void (*)(memwriter_t *)>(memwriter_new(), memwriter_delete);
if (!memwriter)
{
throw std::bad_alloc();
}
tobson_write(memwriter.get(), "o(");
for (const auto &attribute : internal_attributes)
{
std::stringstream format_stream;
format_stream << attribute.first;
switch (attribute.second.type())
{
case GRM::Value::Type::DOUBLE:
format_stream << ":d";
tobson_write(memwriter.get(), format_stream.str().c_str(), static_cast<double>(attribute.second));
break;
case GRM::Value::Type::INT:
format_stream << ":i";
tobson_write(memwriter.get(), format_stream.str().c_str(), static_cast<int>(attribute.second));
break;
case GRM::Value::Type::STRING:
format_stream << ":s";
tobson_write(memwriter.get(), format_stream.str().c_str(),
static_cast<std::string>(attribute.second).c_str());
break;
default:
break;
}
}
tobson_write(memwriter.get(), ")");
err_t error = ERROR_NONE;
auto base64_encoded_cstr = std::unique_ptr<char, void (*)(void *)>(
base64_encode(nullptr, memwriter_buf(memwriter.get()), memwriter_size(memwriter.get()), &error), std::free);
if (error != ERROR_NONE)
{
logger((stderr, "Got error \"%d\" (\"%s\")!\n", error, error_names[error]));
throw std::runtime_error("Got error \"" + std::to_string(error) + "\" (\"" + error_names[error] + "\")!");
}
os << " internal=\"" << base64_encoded_cstr.get() << "\"";
}
if (element->hasChildNodes())
{
os << ">\n";
Expand Down
8 changes: 6 additions & 2 deletions lib/grm/src/grm/dom_render/render.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -15211,7 +15211,9 @@ void GRM::Render::render()
applyRootDefaults(root);
if (logger_enabled())
{
std::cerr << toXML(root, GRM::SerializerOptions{std::string(indent, ' '), true}) << "\n";
std::cerr << toXML(root, GRM::SerializerOptions{std::string(indent, ' '),
GRM::SerializerOptions::InternalAttributesFormat::Plain})
<< "\n";
}
if (static_cast<int>(root->getAttribute("clear_ws"))) gr_clearws();
root->setAttribute("_modified", true);
Expand All @@ -15232,7 +15234,9 @@ void GRM::Render::render()
}
if (logger_enabled())
{
std::cerr << toXML(root, GRM::SerializerOptions{std::string(indent, ' '), true}) << "\n";
std::cerr << toXML(root, GRM::SerializerOptions{std::string(indent, ' '),
GRM::SerializerOptions::InternalAttributesFormat::Plain})
<< "\n";
}
redraw_ws = false;
// reset marker types
Expand Down
14 changes: 10 additions & 4 deletions lib/grm/src/grm/plot.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -4702,7 +4702,9 @@ char *dump_context_str(dump_encoding_t dump_encoding, const std::unordered_set<s
void dump_context_as_xml_comment(FILE *f, const std::unordered_set<std::string> *context_keys_to_discard)
{
#ifndef NDEBUG
auto dump_encoding = DUMP_JSON_ESCAPE_DOUBLE_MINUS;
// TODO: Undo
// auto dump_encoding = DUMP_JSON_ESCAPE_DOUBLE_MINUS;
auto dump_encoding = DUMP_BSON_BASE64;
#else
auto dump_encoding = DUMP_BSON_BASE64;
#endif
Expand All @@ -4724,7 +4726,9 @@ char *dump_context_as_xml_comment_str(const std::unordered_set<std::string> *con
char *xml_comment = nullptr;

#ifndef NDEBUG
auto dump_encoding = DUMP_JSON_ESCAPE_DOUBLE_MINUS;
// TODO: Undo
// auto dump_encoding = DUMP_JSON_ESCAPE_DOUBLE_MINUS;
auto dump_encoding = DUMP_BSON_BASE64;
#else
auto dump_encoding = DUMP_BSON_BASE64;
#endif
Expand Down Expand Up @@ -5717,7 +5721,9 @@ void grm_dump_graphics_tree(FILE *f)
const unsigned int indent = 2;
// Use a lambda around `restore_backup_attribute_filter` to make sure it is used by reference.
fprintf(f, "%s",
toXML(global_root, GRM::SerializerOptions{std::string(indent, ' ')},
toXML(global_root,
GRM::SerializerOptions{std::string(indent, ' '),
GRM::SerializerOptions::InternalAttributesFormat::Obfuscated},
[&restore_backup_attribute_filter](const std::string &attribute_name, const GRM::Element &element,
std::optional<std::string> &new_attribute_name) -> bool {
return restore_backup_attribute_filter(attribute_name, element, new_attribute_name);
Expand All @@ -5743,7 +5749,7 @@ char *grm_dump_graphics_tree_str(void)
internal::RestoreBackupAttributeFilter restore_backup_attribute_filter;
// Use a lambda around `restore_backup_attribute_filter` to make sure it is used by reference.
std::string graphics_tree_str =
toXML(global_root, GRM::SerializerOptions{},
toXML(global_root, GRM::SerializerOptions{"", GRM::SerializerOptions::InternalAttributesFormat::Obfuscated},
[&restore_backup_attribute_filter](const std::string &attribute_name, const GRM::Element &element,
std::optional<std::string> &new_attribute_name) -> bool {
return restore_backup_attribute_filter(attribute_name, element, new_attribute_name);
Expand Down

0 comments on commit 120e699

Please sign in to comment.