summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/lib/logger/logger.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/logger/logger.c')
-rw-r--r--Build/source/texk/web2c/mfluadir/otfcc/lib/logger/logger.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/logger/logger.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/logger/logger.c
new file mode 100644
index 00000000000..22091055f26
--- /dev/null
+++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/logger/logger.c
@@ -0,0 +1,171 @@
+#include "support/util.h"
+#include "otfcc/logger.h"
+
+typedef struct Logger {
+ otfcc_ILogger vtable;
+ void *target;
+ uint16_t level;
+ uint16_t lastLoggedLevel;
+ uint16_t levelCap;
+ sds *indents;
+ uint8_t verbosityLimit;
+} Logger;
+
+const char *otfcc_LoggerTypeNames[3] = {"[ERROR]", "[WARNING]", "[NOTE]"};
+
+static void loggerIndent(otfcc_ILogger *_self, const char *segment) {
+ ((otfcc_ILogger *)_self)->indentSDS(_self, sdsnew(segment));
+}
+static void loggerIndentSDS(otfcc_ILogger *_self, MOVE sds segment) {
+ Logger *self = (Logger *)_self;
+ uint8_t newLevel = self->level + 1;
+ if (newLevel > self->levelCap) {
+ self->levelCap += self->levelCap / 2 + 1;
+ RESIZE(self->indents, self->levelCap);
+ }
+ self->level++;
+ self->indents[self->level - 1] = segment;
+}
+
+static void loggerDedent(otfcc_ILogger *_self) {
+ Logger *self = (Logger *)_self;
+ if (!self->level) return;
+ sdsfree(self->indents[self->level - 1]);
+ self->level -= 1;
+ if (self->level < self->lastLoggedLevel) { self->lastLoggedLevel = self->level; }
+}
+static void loggerFinish(otfcc_ILogger *self) {
+ self->logSDS(self, log_vl_progress + ((Logger *)self)->level, log_type_progress, sdsnew("Finish"));
+ self->dedent(self);
+}
+static void loggerStart(otfcc_ILogger *self, const char *segment) {
+ self->indentSDS(self, sdsnew(segment));
+ self->logSDS(self, log_vl_progress + ((Logger *)self)->level, log_type_progress, sdsnew("Begin"));
+}
+static void loggerStartSDS(otfcc_ILogger *self, MOVE sds segment) {
+ self->indentSDS(self, segment);
+ self->logSDS(self, log_vl_progress + ((Logger *)self)->level, log_type_progress, sdsnew("Begin"));
+}
+static void loggerLog(otfcc_ILogger *self, uint8_t verbosity, otfcc_LoggerType type, const char *data) {
+ self->logSDS(self, verbosity, type, sdsnew(data));
+}
+
+static void loggerLogSDS(otfcc_ILogger *_self, uint8_t verbosity, otfcc_LoggerType type, MOVE sds data) {
+ Logger *self = (Logger *)_self;
+ sds demand = sdsempty();
+ for (uint16_t level = 0; level < self->level; level++) {
+ if (level < self->lastLoggedLevel - 1) {
+ for (size_t j = 0; j < sdslen(self->indents[level]); j++) {
+ demand = sdscat(demand, " ");
+ }
+ if (level < self->lastLoggedLevel - 2) {
+ demand = sdscat(demand, " | ");
+ } else {
+ demand = sdscat(demand, " |-");
+ }
+ } else {
+ demand = sdscatfmt(demand, "%S : ", self->indents[level]);
+ }
+ }
+ if (type < 3) {
+ demand = sdscatfmt(demand, "%s %S", otfcc_LoggerTypeNames[type], data);
+ } else {
+ demand = sdscatfmt(demand, "%S", data);
+ }
+ sdsfree(data);
+ if (verbosity <= self->verbosityLimit) {
+ _self->getTarget(_self)->push(self->target, demand);
+ self->lastLoggedLevel = self->level;
+ } else {
+ sdsfree(demand);
+ }
+}
+
+static otfcc_ILoggerTarget *loggerGetTarget(otfcc_ILogger *_self) {
+ Logger *self = (Logger *)_self;
+ return (otfcc_ILoggerTarget *)self->target;
+}
+
+static void loggerSetVerbosity(otfcc_ILogger *_self, uint8_t verbosity) {
+ Logger *self = (Logger *)_self;
+ self->verbosityLimit = verbosity;
+}
+
+static INLINE void loggerDispose(otfcc_ILogger *_self) {
+ Logger *self = (Logger *)_self;
+ if (!self) return;
+ otfcc_ILoggerTarget *target = _self->getTarget(_self);
+ target->dispose(target);
+ for (uint16_t level = 0; level < self->level; level++) {
+ sdsfree(self->indents[level]);
+ }
+ FREE(self->indents);
+ FREE(self);
+}
+
+const otfcc_ILogger VTABLE_LOGGER = {.dispose = loggerDispose,
+ .indent = loggerIndent,
+ .indentSDS = loggerIndentSDS,
+ .start = loggerStart,
+ .startSDS = loggerStartSDS,
+ .log = loggerLog,
+ .logSDS = loggerLogSDS,
+ .dedent = loggerDedent,
+ .finish = loggerFinish,
+ .getTarget = loggerGetTarget,
+ .setVerbosity = loggerSetVerbosity};
+
+otfcc_ILogger *otfcc_newLogger(otfcc_ILoggerTarget *target) {
+ Logger *logger;
+ NEW(logger);
+ logger->target = target;
+ logger->vtable = VTABLE_LOGGER;
+ return (otfcc_ILogger *)logger;
+}
+
+// STDERR logger target
+
+typedef struct StderrTarget { otfcc_ILoggerTarget vtable; } StderrTarget;
+
+static void stderrTargetDispose(otfcc_ILoggerTarget *_self) {
+ StderrTarget *self = (StderrTarget *)_self;
+ if (!self) return;
+ FREE(self);
+}
+
+static void stderrTargetPush(otfcc_ILoggerTarget *_self, MOVE sds data) {
+ fprintf(stderr, "%s", data);
+ if (data[sdslen(data) - 1] != '\n') fprintf(stderr, "\n");
+ sdsfree(data);
+}
+
+const otfcc_ILoggerTarget VTABLE_STDERR_TARGET = {.dispose = stderrTargetDispose, .push = stderrTargetPush};
+
+otfcc_ILoggerTarget *otfcc_newStdErrTarget() {
+ StderrTarget *target;
+ NEW(target);
+ target->vtable = VTABLE_STDERR_TARGET;
+ return (otfcc_ILoggerTarget *)target;
+}
+
+// Empty logger target
+
+typedef struct EmptyTarget { otfcc_ILoggerTarget vtable; } EmptyTarget;
+static void emptyTargetDispose(otfcc_ILoggerTarget *_self) {
+ StderrTarget *self = (StderrTarget *)_self;
+ if (!self) return;
+ FREE(self);
+}
+
+static void emptyTargetPush(otfcc_ILoggerTarget *_self, MOVE sds data) {
+ sdsfree(data);
+}
+
+const otfcc_ILoggerTarget VTABLE_EMPTY_TARGET = {.dispose = emptyTargetDispose, .push = emptyTargetPush};
+
+otfcc_ILoggerTarget *otfcc_newEmptyTarget() {
+ StderrTarget *target;
+ NEW(target);
+ target->vtable = VTABLE_EMPTY_TARGET;
+ return (otfcc_ILoggerTarget *)target;
+}