Thu, 04 Jul 2019 20:07:31 +0200
adds array interface and tests
universe@103 | 1 | /* |
universe@103 | 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
universe@103 | 3 | * |
universe@259 | 4 | * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. |
universe@103 | 5 | * |
universe@103 | 6 | * Redistribution and use in source and binary forms, with or without |
universe@103 | 7 | * modification, are permitted provided that the following conditions are met: |
universe@103 | 8 | * |
universe@103 | 9 | * 1. Redistributions of source code must retain the above copyright |
universe@103 | 10 | * notice, this list of conditions and the following disclaimer. |
universe@103 | 11 | * |
universe@103 | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
universe@103 | 13 | * notice, this list of conditions and the following disclaimer in the |
universe@103 | 14 | * documentation and/or other materials provided with the distribution. |
universe@103 | 15 | * |
universe@103 | 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
universe@103 | 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
universe@103 | 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
universe@103 | 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
universe@103 | 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
universe@103 | 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
universe@103 | 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
universe@103 | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
universe@103 | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
universe@103 | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
universe@103 | 26 | * POSSIBILITY OF SUCH DAMAGE. |
universe@103 | 27 | */ |
universe@103 | 28 | |
universe@251 | 29 | #include "ucx/logging.h" |
universe@251 | 30 | |
olaf@57 | 31 | #include <stdlib.h> |
universe@80 | 32 | #include <string.h> |
universe@81 | 33 | #include <stdarg.h> |
universe@82 | 34 | #include <time.h> |
olaf@57 | 35 | |
universe@83 | 36 | UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask) { |
olaf@57 | 37 | UcxLogger *logger = (UcxLogger*) malloc(sizeof(UcxLogger)); |
olaf@57 | 38 | if (logger != NULL) { |
olaf@57 | 39 | logger->stream = stream; |
universe@82 | 40 | logger->writer = (write_func)fwrite; |
universe@95 | 41 | logger->dateformat = (char*) "%F %T %z "; |
olaf@57 | 42 | logger->level = level; |
universe@80 | 43 | logger->mask = mask; |
universe@80 | 44 | logger->levels = ucx_map_new(8); |
universe@80 | 45 | |
universe@80 | 46 | unsigned int l; |
universe@80 | 47 | l = UCX_LOGGER_ERROR; |
universe@95 | 48 | ucx_map_int_put(logger->levels, l, (void*) "[ERROR]"); |
universe@80 | 49 | l = UCX_LOGGER_WARN; |
universe@95 | 50 | ucx_map_int_put(logger->levels, l, (void*) "[WARNING]"); |
universe@80 | 51 | l = UCX_LOGGER_INFO; |
universe@95 | 52 | ucx_map_int_put(logger->levels, l, (void*) "[INFO]"); |
universe@295 | 53 | l = UCX_LOGGER_DEBUG; |
universe@295 | 54 | ucx_map_int_put(logger->levels, l, (void*) "[DEBUG]"); |
universe@80 | 55 | l = UCX_LOGGER_TRACE; |
universe@95 | 56 | ucx_map_int_put(logger->levels, l, (void*) "[TRACE]"); |
olaf@57 | 57 | } |
olaf@57 | 58 | |
olaf@57 | 59 | return logger; |
olaf@57 | 60 | } |
olaf@57 | 61 | |
universe@80 | 62 | void ucx_logger_free(UcxLogger *logger) { |
universe@80 | 63 | ucx_map_free(logger->levels); |
universe@80 | 64 | free(logger); |
universe@80 | 65 | } |
universe@80 | 66 | |
universe@152 | 67 | // estimated max. message length (documented) |
universe@152 | 68 | #define UCX_LOGGER_MSGMAX 4096 |
universe@152 | 69 | |
universe@81 | 70 | void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file, |
universe@81 | 71 | const unsigned int line, const char *format, ...) { |
olaf@57 | 72 | if (level <= logger->level) { |
universe@152 | 73 | char msg[UCX_LOGGER_MSGMAX]; |
universe@328 | 74 | const char *text; |
universe@81 | 75 | size_t k = 0; |
universe@81 | 76 | size_t n; |
universe@80 | 77 | |
universe@80 | 78 | if ((logger->mask & UCX_LOGGER_LEVEL) > 0) { |
universe@328 | 79 | text = (const char*) ucx_map_int_get(logger->levels, level); |
universe@295 | 80 | if (!text) { |
universe@295 | 81 | text = "[UNKNOWN]"; |
universe@295 | 82 | } |
universe@81 | 83 | n = strlen(text); |
universe@171 | 84 | n = n > 256 ? 256 : n; |
universe@81 | 85 | memcpy(msg+k, text, n); |
universe@81 | 86 | k += n; |
universe@81 | 87 | msg[k++] = ' '; |
universe@80 | 88 | } |
universe@82 | 89 | if ((logger->mask & UCX_LOGGER_TIMESTAMP) > 0) { |
universe@82 | 90 | time_t now = time(NULL); |
universe@82 | 91 | k += strftime(msg+k, 128, logger->dateformat, localtime(&now)); |
universe@82 | 92 | } |
universe@80 | 93 | if ((logger->mask & UCX_LOGGER_SOURCE) > 0) { |
universe@81 | 94 | n = strlen(file); |
universe@81 | 95 | memcpy(msg+k, file, n); |
universe@81 | 96 | k += n; |
universe@171 | 97 | k += sprintf(msg+k, ":%u ", line); |
universe@80 | 98 | } |
universe@80 | 99 | |
universe@324 | 100 | if (k > 0) { |
universe@324 | 101 | msg[k++] = '-'; msg[k++] = ' '; |
universe@324 | 102 | } |
universe@81 | 103 | |
universe@81 | 104 | va_list args; |
universe@81 | 105 | va_start (args, format); |
universe@152 | 106 | k += vsnprintf(msg+k, UCX_LOGGER_MSGMAX-k-1, format, args); |
universe@81 | 107 | va_end (args); |
universe@81 | 108 | |
universe@80 | 109 | msg[k++] = '\n'; |
universe@80 | 110 | |
universe@81 | 111 | logger->writer(msg, 1, k, logger->stream); |
olaf@57 | 112 | } |
olaf@57 | 113 | } |