diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /src/debug/logger.cpp | |
parent | Initial commit. (diff) | |
download | inkscape-upstream.tar.xz inkscape-upstream.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/debug/logger.cpp')
-rw-r--r-- | src/debug/logger.cpp | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/src/debug/logger.cpp b/src/debug/logger.cpp new file mode 100644 index 0000000..37b8221 --- /dev/null +++ b/src/debug/logger.cpp @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::Logger - debug logging facility + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <cstring> +#include <fstream> +#include <memory> +#include <string> +#include <vector> +#include <glib.h> +#include "inkscape-version.h" +#include "debug/logger.h" +#include "debug/simple-event.h" + +namespace Inkscape { + +namespace Debug { + +bool Logger::_enabled=false; +bool Logger::_category_mask[Event::N_CATEGORIES]; + +namespace { + +static void write_escaped_value(std::ostream &os, char const *value) { + for ( char const *current=value ; *current ; ++current ) { + switch (*current) { + case '&': + os << "&"; + break; + case '"': + os << """; + break; + case '\'': + os << "'"; + break; + case '<': + os << "<"; + break; + case '>': + os << ">"; + break; + default: + os.put(*current); + } + } +} + +static void write_indent(std::ostream &os, unsigned depth) { + for ( unsigned i = 0 ; i < depth ; i++ ) { + os.write(" ", 2); + } +} + +static std::ofstream log_stream; +static bool empty_tag=false; +typedef std::vector<std::shared_ptr<std::string>> TagStack; +static TagStack &tag_stack() { + static TagStack stack; + return stack; +} + +static void do_shutdown() { + Debug::Logger::shutdown(); +} + +static bool equal_range(char const *c_string, + char const *start, char const *end) +{ + return !std::strncmp(start, c_string, end - start) && + !c_string[end - start]; +} + +static void set_category_mask(bool * const mask, char const *filter) { + if (!filter) { + for ( unsigned i = 0 ; i < Event::N_CATEGORIES ; i++ ) { + mask[i] = true; + } + return; + } else { + for ( unsigned i = 0 ; i < Event::N_CATEGORIES ; i++ ) { + mask[i] = false; + } + mask[Event::CORE] = true; + } + + char const *start; + char const *end; + start = end = filter; + while (*end) { + while ( *end && *end != ',' ) { end++; } + if ( start != end ) { + struct CategoryName { + char const *name; + Event::Category category; + }; + static const CategoryName category_names[] = { + { "CORE", Event::CORE }, + { "XML", Event::XML }, + { "SPOBJECT", Event::SPOBJECT }, + { "DOCUMENT", Event::DOCUMENT }, + { "REFCOUNT", Event::REFCOUNT }, + { "EXTENSION", Event::EXTENSION }, + { "FINALIZERS", Event::FINALIZERS }, + { "INTERACTION", Event::INTERACTION }, + { "CONFIGURATION", Event::CONFIGURATION }, + { "OTHER", Event::OTHER }, + { nullptr, Event::OTHER } + }; + CategoryName const *iter; + for ( iter = category_names ; iter->name ; iter++ ) { + if (equal_range(iter->name, start, end)) { + mask[iter->category] = true; + break; + } + } + if (!iter->name) { + g_warning("Unknown debugging category %*s", (int)(end - start), start); + } + } + if (*end) { + start = end = end + 1; + } + } +} + +typedef SimpleEvent<Event::CORE> CoreEvent; + +class SessionEvent : public CoreEvent { +public: + SessionEvent() : CoreEvent("session") { + _addProperty("inkscape-version", Inkscape::version_string); + } +}; + +} + +void Logger::init() { + if (!_enabled) { + char const *log_filename=std::getenv("INKSCAPE_DEBUG_LOG"); + if (log_filename) { + log_stream.open(log_filename); + if (log_stream.is_open()) { + char const *log_filter=std::getenv("INKSCAPE_DEBUG_FILTER"); + set_category_mask(_category_mask, log_filter); + log_stream << "<?xml version=\"1.0\"?>\n"; + log_stream.flush(); + _enabled = true; + start<SessionEvent>(); + std::atexit(&do_shutdown); + } + } + } +} + +void Logger::_start(Event const &event) { + char const *name=event.name(); + + if (empty_tag) { + log_stream << ">\n"; + } + + write_indent(log_stream, tag_stack().size()); + + log_stream << "<" << name; + + unsigned property_count=event.propertyCount(); + for ( unsigned i = 0 ; i < property_count ; i++ ) { + Event::PropertyPair property=event.property(i); + log_stream << " " << property.name << "=\""; + write_escaped_value(log_stream, property.value->c_str()); + log_stream << "\""; + } + + log_stream.flush(); + + tag_stack().push_back(std::make_shared<std::string>(name)); + empty_tag = true; + + event.generateChildEvents(); +} + +void Logger::_skip() { + tag_stack().push_back(nullptr); +} + +void Logger::_finish() { + if (tag_stack().back()) { + if (empty_tag) { + log_stream << "/>\n"; + } else { + write_indent(log_stream, tag_stack().size() - 1); + log_stream << "</" << tag_stack().back()->c_str() << ">\n"; + } + log_stream.flush(); + + empty_tag = false; + } + + tag_stack().pop_back(); +} + +void Logger::shutdown() { + if (_enabled) { + while (!tag_stack().empty()) { + finish(); + } + } +} + +} + +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |