hscdio-0.1.0.0: src/c/cdio/compat/logging.c
#include "cdio/compat/logging.h"
#include <stdlib.h>
#include <string.h>
// Avoid unnecessary repeated calls; don't seem to mess anything up, but may as
// well keep clean.
bool replaced_cdio_logger = false;
cdio_log_level_t get_cdio_log_level() {
return cdio_loglevel_default;
}
void set_cdio_log_level(cdio_log_level_t l) {
// The `_default` refers to the default handler, but it has explicitly been
// opened up to alternate implementations as well.
cdio_loglevel_default = l;
}
void haskell_log_handler(cdio_log_level_t lvl, const char* msg) {
if (lvl >= cdio_loglevel_default) {
cdio_log_entry_t* entry = (cdio_log_entry_t*) malloc(sizeof(cdio_log_entry_t));
if (!entry)
return;
// The Haskell garbage collector could easily clean anything logged
// from the bindings before it's read.
char* message = malloc(strlen(msg) + 1);
if (!message) {
free(entry);
return;
}
else
strcpy(message, msg);
entry->level = lvl;
entry->prev = haskell_log;
entry->message = message;
haskell_log = entry;
}
}
void setup_cdio_logger() {
if (!replaced_cdio_logger) {
cdio_log_set_handler(*haskell_log_handler);
haskell_log = NULL;
replaced_cdio_logger = true;
}
}
cdio_log_entry_t** read_cdio_log() {
if (!haskell_log)
return NULL;
// We need the total number of entries for determining allocation size.
int count = 0;
cdio_log_entry_t* entry = haskell_log;
while (entry) {
++count;
entry = entry->prev;
}
cdio_log_entry_t** out = (cdio_log_entry_t**) calloc(count + 1, sizeof(cdio_log_entry_t*));
if (!out)
return NULL;
// ...and since we have the total anyway, may as well reverse the FILO into
// chronological order now.
entry = haskell_log;
for (int i = count - 1; i >= 0; --i) {
out[i] = entry;
entry = entry->prev;
}
return out;
}
void free_cdio_log() {
while (haskell_log) {
cdio_log_entry_t* entry = haskell_log;
haskell_log = entry->prev;
if (entry->message)
free((void *)entry->message);
free(entry);
}
}