Commit | Line | Data |
---|---|---|
15c988f7 JB |
1 | /** |
2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua | |
3 | * | |
4 | * This library is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU Lesser General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2.1 of the License, or (at your option) any later version. | |
8 | * | |
9 | * This library is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Lesser General Public License for more details. | |
13 | */ | |
14 | ||
15 | #include <stdlib.h> | |
16 | #include <stdio.h> | |
17 | #include <stdarg.h> | |
18 | #include <assert.h> | |
19 | ||
20 | #include "logger.h" | |
21 | #include "compat.h" | |
22 | ||
23 | struct logger_s { | |
24 | mutex_handle_t lvl_mutex; | |
25 | mutex_handle_t cb_mutex; | |
26 | ||
27 | int level; | |
28 | void *cls; | |
29 | logger_callback_t callback; | |
30 | }; | |
31 | ||
32 | logger_t * | |
33 | logger_init() | |
34 | { | |
35 | logger_t *logger = calloc(1, sizeof(logger_t)); | |
36 | assert(logger); | |
37 | ||
38 | MUTEX_CREATE(logger->lvl_mutex); | |
39 | MUTEX_CREATE(logger->cb_mutex); | |
40 | ||
41 | logger->level = LOGGER_WARNING; | |
42 | logger->callback = NULL; | |
43 | return logger; | |
44 | } | |
45 | ||
46 | void | |
47 | logger_destroy(logger_t *logger) | |
48 | { | |
49 | MUTEX_DESTROY(logger->lvl_mutex); | |
50 | MUTEX_DESTROY(logger->cb_mutex); | |
51 | free(logger); | |
52 | } | |
53 | ||
54 | void | |
55 | logger_set_level(logger_t *logger, int level) | |
56 | { | |
57 | assert(logger); | |
58 | ||
59 | MUTEX_LOCK(logger->lvl_mutex); | |
60 | logger->level = level; | |
61 | MUTEX_UNLOCK(logger->lvl_mutex); | |
62 | } | |
63 | ||
64 | void | |
65 | logger_set_callback(logger_t *logger, logger_callback_t callback, void *cls) | |
66 | { | |
67 | assert(logger); | |
68 | ||
69 | MUTEX_LOCK(logger->cb_mutex); | |
70 | logger->cls = cls; | |
71 | logger->callback = callback; | |
72 | MUTEX_UNLOCK(logger->cb_mutex); | |
73 | } | |
74 | ||
75 | static char * | |
76 | logger_utf8_to_local(const char *str) | |
77 | { | |
78 | char *ret = NULL; | |
79 | ||
80 | /* FIXME: This is only implemented on Windows for now */ | |
81 | #if defined(_WIN32) || defined(_WIN64) | |
82 | int wclen, mblen; | |
83 | WCHAR *wcstr; | |
84 | BOOL failed; | |
85 | ||
86 | wclen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); | |
87 | wcstr = malloc(sizeof(WCHAR) * wclen); | |
88 | MultiByteToWideChar(CP_UTF8, 0, str, -1, wcstr, wclen); | |
89 | ||
90 | mblen = WideCharToMultiByte(CP_ACP, 0, wcstr, wclen, NULL, 0, NULL, &failed); | |
91 | if (failed) { | |
92 | /* Invalid characters in input, conversion failed */ | |
93 | free(wcstr); | |
94 | return NULL; | |
95 | } | |
96 | ||
97 | ret = malloc(sizeof(CHAR) * mblen); | |
98 | WideCharToMultiByte(CP_ACP, 0, wcstr, wclen, ret, mblen, NULL, NULL); | |
99 | free(wcstr); | |
100 | #endif | |
101 | ||
102 | return ret; | |
103 | } | |
104 | ||
105 | void | |
106 | logger_log(logger_t *logger, int level, const char *fmt, ...) | |
107 | { | |
108 | char buffer[4096]; | |
109 | va_list ap; | |
110 | ||
111 | MUTEX_LOCK(logger->lvl_mutex); | |
112 | if (level > logger->level) { | |
113 | MUTEX_UNLOCK(logger->lvl_mutex); | |
114 | return; | |
115 | } | |
116 | MUTEX_UNLOCK(logger->lvl_mutex); | |
117 | ||
118 | buffer[sizeof(buffer)-1] = '\0'; | |
119 | va_start(ap, fmt); | |
120 | vsnprintf(buffer, sizeof(buffer)-1, fmt, ap); | |
121 | va_end(ap); | |
122 | ||
123 | MUTEX_LOCK(logger->cb_mutex); | |
124 | if (logger->callback) { | |
125 | logger->callback(logger->cls, level, buffer); | |
126 | MUTEX_UNLOCK(logger->cb_mutex); | |
127 | } else { | |
128 | char *local; | |
129 | MUTEX_UNLOCK(logger->cb_mutex); | |
130 | local = logger_utf8_to_local(buffer); | |
131 | if (local) { | |
132 | fprintf(stderr, "%s\n", local); | |
133 | free(local); | |
134 | } else { | |
135 | fprintf(stderr, "%s\n", buffer); | |
136 | } | |
137 | } | |
138 | } | |
139 |