dynamic log types
[protos/libecoli.git] / lib / ecoli_log.c
1 /*
2  * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #define _GNU_SOURCE /* for vasprintf */
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include <ecoli_malloc.h>
35 #include <ecoli_log.h>
36
37 static ec_log_t ec_log_fct = ec_log_default;
38 static void *ec_log_opaque;
39
40 struct ec_log_type {
41         char *name;
42         unsigned int level;
43 };
44
45 static struct ec_log_type *log_types;
46 static size_t log_types_len;
47
48 int ec_log_default(int type, unsigned int level, void *opaque, const char *str)
49 {
50         (void)opaque;
51
52         return printf("[%d] %-12s %s", level, ec_log_name(type), str);
53 }
54
55 int ec_log_fct_register(ec_log_t usr_log, void *opaque)
56 {
57         if (usr_log == NULL)
58                 return -1;
59
60         ec_log_fct = usr_log;
61         ec_log_opaque = opaque;
62
63         return 0;
64 }
65
66 void ec_log_fct_unregister(void)
67 {
68         ec_log_fct = NULL;
69 }
70
71 static int
72 ec_log_lookup(const char *name)
73 {
74         size_t i;
75
76         for (i = 0; i < log_types_len; i++) {
77                 if (log_types[i].name == NULL)
78                         continue;
79                 if (strcmp(name, log_types[i].name) == 0)
80                         return i;
81         }
82
83         return -1;
84 }
85
86 const char *
87 ec_log_name(int type)
88 {
89         if (type < 0 || (unsigned int)type >= log_types_len)
90                 return "unknown";
91         return log_types[type].name;
92 }
93
94 int
95 ec_log_type_register(const char *name)
96 {
97         struct ec_log_type *new_types;
98         char *copy;
99         int id;
100
101         id = ec_log_lookup(name);
102         if (id >= 0)
103                 return id;
104
105         new_types = ec_realloc(log_types,
106                 sizeof(*new_types) * (log_types_len + 1));
107         if (new_types == NULL)
108                 return -ENOMEM;
109         log_types = new_types;
110
111         copy = ec_strdup(name);
112         if (copy == NULL)
113                 return -ENOMEM;
114
115         id = log_types_len++;
116         log_types[id].name = copy;
117         log_types[id].level = EC_LOG_DEBUG;
118
119         return id;
120 }
121
122 int ec_vlog(int type, unsigned int level, const char *format, va_list ap)
123 {
124         char *s;
125         int ret;
126
127         if (ec_log_fct == NULL) {
128                 errno = ENODEV;
129                 return -1;
130         }
131
132         ret = vasprintf(&s, format, ap);
133         if (ret < 0)
134                 return ret;
135
136         ret = ec_log_fct(type, level, ec_log_opaque, s);
137         free(s);
138
139         return ret;
140 }
141
142 int ec_log(int type, unsigned int level, const char *format, ...)
143 {
144         va_list ap;
145         int ret;
146
147         va_start(ap, format);
148         ret = ec_vlog(type, level, format, ap);
149         va_end(ap);
150
151         return ret;
152 }