cake
/
libp7
Archived
1
0
Fork 1
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libp7/src/core/log.c

246 lines
6.4 KiB
C

/* *****************************************************************************
* core/log.c -- libp7 logging utilities.
* Copyright (C) 2016-2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libp7.
* libp7 is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libp7 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libp7; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libp7/internals.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#define should_log(LEVEL) (log_setting <= (LEVEL))
/* ************************************************************************** */
/* Interact with the log settings at runtime */
/* ************************************************************************** */
/* The log setting */
static p7_loglevel_t log_setting = LOGLEVEL;
/**
* p7_setlog:
* Set the log level at runtime.
*
* @arg level the level to set.
*/
p7_define_func(p7_setlog, void, p7_attrs_setlog,
p7_loglevel_t level)
{
log_setting = level;
}
/**
* p7_getlog:
* Get the log level at runtime.
*
* @return the current level.
*/
p7_define_func(p7_getlog, p7_loglevel_t, p7_attrs_getlog, void)
{
return (log_setting);
}
/* ************************************************************************** */
/* Make conversions between settings values and strings, list settings */
/* ************************************************************************** */
/**
* p7_loglevel_tostring:
* Make a string out of a log level.
*
* @arg level the log level.
* @return the string.
*/
p7_define_func(p7_loglevel_tostring, const char*,
p7_attrs_loglevel_tostring,
p7_loglevel_t level)
{
if (level >= 0 && level < 10)
return ("info");
if (level >= 10 && level < 20)
return ("warn");
if (level >= 20 && level < 30)
return ("error");
if (level >= 30 && level < 40)
return ("fatal");
return ("none");
}
/**
* p7_loglevel_fromstring:
* Make a log level out of a string.
*
* @arg string the string.
* @return the log level.
*/
p7_define_func(p7_loglevel_fromstring, p7_loglevel_t,
p7_attrs_loglevel_fromstring,
const char *string)
{
if (!strcmp(string, "info"))
return (p7_loglevel_info);
if (!strcmp(string, "warn"))
return (p7_loglevel_warn);
if (!strcmp(string, "error"))
return (p7_loglevel_error);
if (!strcmp(string, "fatal"))
return (p7_loglevel_fatal);
return (p7_loglevel_none);
}
/**
* p7_loglevel_list:
* List log levels.
*
* @arg callback the callback.
* @arg cookie the callback cookie.
*/
p7_define_func(p7_loglevel_list, void,
p7_attrs_loglevel_list,
p7_liststr_t *callback, void *cookie)
{
(*callback)(cookie, "info");
(*callback)(cookie, "warn");
(*callback)(cookie, "error");
(*callback)(cookie, "fatal");
}
/* ************************************************************************** */
/* Log simple messages */
/* ************************************************************************** */
/**
* p7_log:
* Log a simple message.
*
* @arg name the handle name.
* @arg loglevel the log level.
* @arg format the format.
* @arg ... the arguments.
*/
void p7_log(const char *name, int loglevel, const char *format, ...)
{
va_list args;
/* put the prefix */
name = name ? name : "";
if (should_log(loglevel)) fprintf(stderr, "[libp7 %s%s] ",
name, p7_loglevel_tostring(loglevel));
/* put the main part */
va_start(args, format);
if (should_log(loglevel)) {
vfprintf(stderr, format, args);
fputc('\n', stderr);
}
va_end(args);
}
/* ************************************************************************** */
/* Log memory */
/* ************************************************************************** */
/**
* log_mem_hex:
* Prints the octal interpretation of a max of two octets.
*
* @arg s the string where to put it
* @arg m the memory zone to print
* @arg n the size of the memory zone
*/
static void log_mem_hex(char *s, const unsigned char *m, size_t n)
{
size_t l = 0;
while (l < 16) {
/* put the hex number */
if (n) { p7_putascii((unsigned char*)s, *m++, 2); s += 2; }
else { *s++ = ' '; *s++ = ' '; }
/* decrement size of the memory zone to go */
n -= !!n;
/* go to next character if s is at the ending of a group */
if (l++ % 2) s++;
}
}
/**
* log_mem_asc:
* Prints the ascii interpretation of a max of two octets.
*
* @arg s the string where to put it
* @arg m the memory zone to print
* @arg n the size of the memory zone
*/
static void log_mem_asc(char *s, const unsigned char *m, size_t n)
{
size_t l = 0;
/* for each byte */
while (n-- && l++ < 16) {
/* put the character (or a dot if non printable) */
if (isprint(*m++)) *s++ = *((const char*)m - 1);
else *s++ = '.';
}
/* put the line ending */
*s++ = '\n';
*s = '\0';
}
/**
* p7_log_mem:
* Print memory zone.
*
* @arg name the handle name.
* @arg loglevel the message log level.
* @arg m the memory zone to print.
* @arg n the size of the memory zone.
*/
void p7_log_mem(const char *name, p7_loglevel_t loglevel,
const void *m, size_t n)
{
char linebuf[58];
const unsigned char *p;
/* check if the log level is good */
if (!should_log(loglevel)) return ;
/* if nothing, print it directly */
name = name ? name : "";
if (!n) {
fprintf(stderr, "[libp7 %s%s] (nothing)\n",
name, p7_loglevel_tostring(loglevel));
return ;
}
/* prepare line buffer, and loop-loop-loop-loop-loop */
memcpy(linebuf, "0000 0000 0000 0000 0000 0000 0000 0000 ", 40);
for (p = m; n > 0;) {
/* fill in ascii-hex part */
log_mem_hex(&linebuf[0], p, n);
/* fill in ascii part */
log_mem_asc(&linebuf[40], p, n);
/* then print line */
fprintf(stderr, "[libp7 %s%s] ",
name, p7_loglevel_tostring(loglevel));
fputs(linebuf, stderr);
/* and increment pointer */
p += 16;
n -= min(16, n);
}
}