blob: 2077fc950bb3386608f4362b8263b160c0bcb41a [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/types.h>
20#include <pj/log.h>
21#include <pj/string.h>
22#include <pj/os.h>
23#include <pj/compat/vsprintf.h>
24#include <pj/compat/stdarg.h>
25
26#if PJ_LOG_MAX_LEVEL >= 1
27
28static int log_max_level = PJ_LOG_MAX_LEVEL;
29static pj_log_func *log_writer = &pj_log_write;
30static unsigned log_decor = PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC |
31 PJ_LOG_HAS_SENDER | PJ_LOG_HAS_NEWLINE;
32
33#if PJ_LOG_USE_STACK_BUFFER==0
34static char log_buffer[PJ_LOG_MAX_SIZE];
35#endif
36
37PJ_DEF(void) pj_log_set_decor(unsigned decor)
38{
39 log_decor = decor;
40}
41
42PJ_DEF(unsigned) pj_log_get_decor(void)
43{
44 return log_decor;
45}
46
47PJ_DEF(void) pj_log_set_level(int level)
48{
49 log_max_level = level;
50}
51
52PJ_DEF(int) pj_log_get_level(void)
53{
54 return log_max_level;
55}
56
57PJ_DEF(void) pj_log_set_log_func( pj_log_func *func )
58{
59 log_writer = func;
60}
61
62PJ_DEF(pj_log_func*) pj_log_get_log_func(void)
63{
64 return log_writer;
65}
66
67PJ_DEF(void) pj_log( const char *sender, int level,
68 const char *format, va_list marker)
69{
70 pj_time_val now;
71 pj_parsed_time ptime;
72 char *pre;
73#if PJ_LOG_USE_STACK_BUFFER
74 char log_buffer[PJ_LOG_MAX_SIZE];
75#endif
76 int len;
77
78 PJ_CHECK_STACK();
79
80 if (level > log_max_level)
81 return;
82
83 /* Get current date/time. */
84 pj_gettimeofday(&now);
85 pj_time_decode(&now, &ptime);
86
87 pre = log_buffer;
88 if (log_decor & PJ_LOG_HAS_DAY_NAME) {
89 static const char *wdays[] = { "Sun", "Mon", "Tue", "Wed",
90 "Thu", "Fri", "Sat"};
91 strcpy(pre, wdays[ptime.wday]);
92 pre += 3;
93 }
94 if (log_decor & PJ_LOG_HAS_YEAR) {
95 *pre++ = ' ';
96 pre += pj_utoa(ptime.year, pre);
97 }
98 if (log_decor & PJ_LOG_HAS_MONTH) {
99 *pre++ = '-';
100 pre += pj_utoa_pad(ptime.mon, pre, 2, '0');
101 }
102 if (log_decor & PJ_LOG_HAS_DAY_OF_MON) {
103 *pre++ = ' ';
104 pre += pj_utoa_pad(ptime.day, pre, 2, '0');
105 }
106 if (log_decor & PJ_LOG_HAS_TIME) {
107 *pre++ = ' ';
108 pre += pj_utoa_pad(ptime.hour, pre, 2, '0');
109 *pre++ = ':';
110 pre += pj_utoa_pad(ptime.min, pre, 2, '0');
111 *pre++ = ':';
112 pre += pj_utoa_pad(ptime.sec, pre, 2, '0');
113 }
114 if (log_decor & PJ_LOG_HAS_MICRO_SEC) {
115 *pre++ = '.';
116 pre += pj_utoa_pad(ptime.msec, pre, 3, '0');
117 }
118 if (log_decor & PJ_LOG_HAS_SENDER) {
119 enum { SENDER_WIDTH = 12 };
120 int sender_len = strlen(sender);
121 *pre++ = ' ';
122 if (sender_len <= SENDER_WIDTH) {
123 while (sender_len < SENDER_WIDTH)
124 *pre++ = ' ', ++sender_len;
125 while (*sender)
126 *pre++ = *sender++;
127 } else {
128 int i;
129 for (i=0; i<SENDER_WIDTH; ++i)
130 *pre++ = *sender++;
131 }
132 }
133
134 if (log_decor != 0 && log_decor != PJ_LOG_HAS_NEWLINE)
135 *pre++ = ' ';
136
137 len = pre - log_buffer;
138
139 /* Print the whole message to the string log_buffer. */
140 len = len + vsnprintf(pre, sizeof(log_buffer)-len, format, marker);
141 if (len > 0 && len < sizeof(log_buffer)-1) {
142 if (log_decor & PJ_LOG_HAS_NEWLINE) {
143 log_buffer[len++] = '\n';
144 }
145 log_buffer[len++] = '\0';
146 } else {
147 len = sizeof(log_buffer)-1;
148 if (log_decor & PJ_LOG_HAS_NEWLINE) {
149 log_buffer[sizeof(log_buffer)-2] = '\n';
150 }
151 log_buffer[sizeof(log_buffer)-1] = '\0';
152 }
153
154 if (log_writer)
155 (*log_writer)(level, log_buffer, len);
156}
157
158PJ_DEF(void) pj_log_0(const char *obj, const char *format, ...)
159{
160 va_list arg;
161 va_start(arg, format);
162 pj_log(obj, 0, format, arg);
163 va_end(arg);
164}
165
166PJ_DEF(void) pj_log_1(const char *obj, const char *format, ...)
167{
168 va_list arg;
169 va_start(arg, format);
170 pj_log(obj, 1, format, arg);
171 va_end(arg);
172}
173#endif /* PJ_LOG_MAX_LEVEL >= 1 */
174
175#if PJ_LOG_MAX_LEVEL >= 2
176PJ_DEF(void) pj_log_2(const char *obj, const char *format, ...)
177{
178 va_list arg;
179 va_start(arg, format);
180 pj_log(obj, 2, format, arg);
181 va_end(arg);
182}
183#endif
184
185#if PJ_LOG_MAX_LEVEL >= 3
186PJ_DEF(void) pj_log_3(const char *obj, const char *format, ...)
187{
188 va_list arg;
189 va_start(arg, format);
190 pj_log(obj, 3, format, arg);
191 va_end(arg);
192}
193#endif
194
195#if PJ_LOG_MAX_LEVEL >= 4
196PJ_DEF(void) pj_log_4(const char *obj, const char *format, ...)
197{
198 va_list arg;
199 va_start(arg, format);
200 pj_log(obj, 4, format, arg);
201 va_end(arg);
202}
203#endif
204
205#if PJ_LOG_MAX_LEVEL >= 5
206PJ_DEF(void) pj_log_5(const char *obj, const char *format, ...)
207{
208 va_list arg;
209 va_start(arg, format);
210 pj_log(obj, 5, format, arg);
211 va_end(arg);
212}
213#endif
214
215#if PJ_LOG_MAX_LEVEL >= 6
216PJ_DEF(void) pj_log_6(const char *obj, const char *format, ...)
217{
218 va_list arg;
219 va_start(arg, format);
220 pj_log(obj, 6, format, arg);
221 va_end(arg);
222}
223#endif
224