category.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /*
  2. * category.c
  3. *
  4. * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
  5. *
  6. * See the COPYING file for the terms of usage and distribution.
  7. */
  8. #ifdef HAVE_CONFIG_H
  9. #include "config.h"
  10. #endif
  11. #include <tchar.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #ifdef HAVE_ALLOCA_H
  15. #include <alloca.h>
  16. #endif
  17. #include "sd/sprintf.h"
  18. #include "sd/malloc.h"
  19. #include "sd/factory.h"
  20. #include "log4c/appender.h"
  21. #include "log4c/priority.h"
  22. #include "log4c/logging_event.h"
  23. #include "log4c/category.h"
  24. #include "log4c/rc.h"
  25. #include "sd/error.h"
  26. #include "sd/sd_xplatform.h"
  27. static const TCHAR version[] = _T("$Id$");
  28. struct __log4c_category {
  29. TCHAR* cat_name;
  30. int cat_priority;
  31. int cat_additive;
  32. const log4c_category_t* cat_parent;
  33. log4c_appender_t* cat_appender;
  34. };
  35. sd_factory_t* log4c_category_factory = NULL;
  36. static const TCHAR LOG4C_CATEGORY_DEFAULT[] = _T("root");
  37. /**
  38. * @bug the root category name should be "" not "root". *
  39. */
  40. /*******************************************************************************/
  41. extern log4c_category_t* log4c_category_get(const TCHAR* a_name)
  42. {
  43. static const sd_factory_ops_t log4c_category_factory_ops = {
  44. /*(void*) log4c_category_new,
  45. (void*) log4c_category_delete,
  46. (void*) log4c_category_print,*/
  47. (void *( *)(const TCHAR *))log4c_category_new,
  48. (void ( *)(void *))log4c_category_delete,
  49. (void ( *)(void *,FILE *))log4c_category_print
  50. };
  51. if (!log4c_category_factory) {
  52. log4c_category_factory = sd_factory_new(_T("log4c_category_factory"),
  53. &log4c_category_factory_ops);
  54. }
  55. return (log4c_category_t *)sd_factory_get(log4c_category_factory, a_name);
  56. }
  57. /*******************************************************************************/
  58. extern int log4c_category_list(log4c_category_t** a_cats, int a_ncats)
  59. {
  60. return sd_factory_list(log4c_category_factory, (void**) a_cats, a_ncats);
  61. }
  62. /*******************************************************************************/
  63. static const TCHAR* dot_dirname(TCHAR* a_string);
  64. extern log4c_category_t* log4c_category_new(const TCHAR* a_name)
  65. {
  66. log4c_category_t* ptrThis;
  67. if (!a_name)
  68. return NULL;
  69. ptrThis = (log4c_category_t *)sd_calloc(1, sizeof(log4c_category_t));
  70. ptrThis->cat_name = sd_strdup(a_name);
  71. ptrThis->cat_priority = LOG4C_PRIORITY_NOTSET;
  72. ptrThis->cat_additive = 1;
  73. ptrThis->cat_appender = NULL;
  74. ptrThis->cat_parent = NULL;
  75. /* skip root category because it has a NULL parent */
  76. if (_tccmp(LOG4C_CATEGORY_DEFAULT, a_name)) {
  77. TCHAR* tmp = sd_strdup(ptrThis->cat_name);
  78. ptrThis->cat_parent = log4c_category_get(dot_dirname(tmp));
  79. free(tmp);
  80. }
  81. return ptrThis;
  82. }
  83. /*******************************************************************************/
  84. extern void log4c_category_delete(log4c_category_t* ptrThis)
  85. {
  86. if (!ptrThis)
  87. return;
  88. free(ptrThis->cat_name);
  89. free(ptrThis);
  90. }
  91. /*******************************************************************************/
  92. extern const TCHAR* log4c_category_get_name(const log4c_category_t* ptrThis)
  93. {
  94. return (ptrThis ? ptrThis->cat_name : _T("(nil)"));
  95. }
  96. /*******************************************************************************/
  97. extern int log4c_category_get_priority(const log4c_category_t* ptrThis)
  98. {
  99. return (ptrThis ? ptrThis->cat_priority : LOG4C_PRIORITY_UNKNOWN);
  100. }
  101. /*******************************************************************************/
  102. extern int log4c_category_get_chainedpriority(const log4c_category_t* ptrThis)
  103. {
  104. const log4c_category_t* cat = ptrThis;
  105. if (!ptrThis)
  106. return LOG4C_PRIORITY_UNKNOWN;
  107. while (cat->cat_priority == LOG4C_PRIORITY_NOTSET && cat->cat_parent)
  108. cat = cat->cat_parent;
  109. return cat->cat_priority;
  110. }
  111. /*******************************************************************************/
  112. extern const log4c_appender_t* log4c_category_get_appender(const log4c_category_t* ptrThis)
  113. {
  114. return (ptrThis ? ptrThis->cat_appender : NULL);
  115. }
  116. /*******************************************************************************/
  117. extern int log4c_category_get_additivity(const log4c_category_t* ptrThis)
  118. {
  119. return (ptrThis ? ptrThis->cat_additive : -1);
  120. }
  121. /*******************************************************************************/
  122. extern int log4c_category_set_priority(log4c_category_t* ptrThis, int a_priority)
  123. {
  124. int previous;
  125. if (!ptrThis)
  126. return LOG4C_PRIORITY_UNKNOWN;
  127. previous = ptrThis->cat_priority;
  128. ptrThis->cat_priority = a_priority;
  129. return previous;
  130. }
  131. /**
  132. * @todo need multiple appenders per category
  133. */
  134. /*******************************************************************************/
  135. extern const log4c_appender_t* log4c_category_set_appender(
  136. log4c_category_t* ptrThis,
  137. log4c_appender_t* a_appender)
  138. {
  139. log4c_appender_t* previous;
  140. if (!ptrThis)
  141. return NULL;
  142. previous = ptrThis->cat_appender;
  143. ptrThis->cat_appender = a_appender;
  144. return previous;
  145. }
  146. /*******************************************************************************/
  147. extern int log4c_category_set_additivity(log4c_category_t* ptrThis, int a_additivity)
  148. {
  149. int previous;
  150. if (!ptrThis)
  151. return -1;
  152. previous = ptrThis->cat_additive;
  153. ptrThis->cat_additive = a_additivity;
  154. return previous;
  155. }
  156. /*******************************************************************************/
  157. extern void log4c_category_print(const log4c_category_t* ptrThis, FILE* a_stream)
  158. {
  159. if (!ptrThis)
  160. return;
  161. _ftprintf(a_stream, _T("{ name:'%s' priority:%s additive:%d appender:'%s' parent:'%s' }"),
  162. ptrThis->cat_name,
  163. log4c_priority_to_string(ptrThis->cat_priority),
  164. ptrThis->cat_additive,
  165. log4c_appender_get_name(ptrThis->cat_appender),
  166. log4c_category_get_name(ptrThis->cat_parent)
  167. );
  168. }
  169. /*******************************************************************************/
  170. extern void __log4c_category_vlog(const log4c_category_t* ptrThis,
  171. const log4c_location_info_t* a_locinfo,
  172. int a_priority,
  173. const TCHAR* a_format,
  174. va_list a_args)
  175. {
  176. TCHAR* message;
  177. log4c_logging_event_t evt;
  178. const log4c_category_t* cat;
  179. int yes = 0;
  180. if (!ptrThis)
  181. return;
  182. /* check if an appender is defined in the category hierarchy */
  183. for (cat = ptrThis; cat; cat = cat->cat_parent)
  184. {
  185. if (cat->cat_appender)
  186. yes++;
  187. }
  188. if (!yes)
  189. return;
  190. log4c_reread();
  191. /* when there is no limit on the buffer size, we use malloc() to
  192. * give the user the possiblity to reallocate if necessary. When
  193. * the buffer is limited in size, we use alloca() for more
  194. * efficiency.
  195. */
  196. evt.evt_buffer.buf_maxsize = log4c_rc->config.bufsize;
  197. if (!evt.evt_buffer.buf_maxsize)
  198. {
  199. evt.evt_buffer.buf_size = LOG4C_BUFFER_SIZE_DEFAULT;
  200. evt.evt_buffer.buf_data = (TCHAR*)sd_malloc(evt.evt_buffer.buf_size);
  201. message = sd_vsprintf(a_format, a_args);
  202. }
  203. else
  204. {
  205. size_t n;
  206. evt.evt_buffer.buf_size = evt.evt_buffer.buf_maxsize;
  207. evt.evt_buffer.buf_data = (TCHAR*)alloca(evt.evt_buffer.buf_size);
  208. message = (TCHAR*)alloca(evt.evt_buffer.buf_size);
  209. if ( (n = (size_t)_vsntprintf(message, evt.evt_buffer.buf_size, a_format, a_args)) >= evt.evt_buffer.buf_size)
  210. sd_error(_T("truncating message of %d bytes (bufsize = %d)"), n, evt.evt_buffer.buf_size);
  211. }
  212. evt.evt_category = ptrThis->cat_name;
  213. evt.evt_priority = a_priority;
  214. evt.evt_msg = message;
  215. evt.evt_loc = a_locinfo;
  216. SD_GETTIMEOFDAY(&evt.evt_timestamp, NULL);
  217. for (cat = ptrThis; cat; cat = cat->cat_parent)
  218. {
  219. if (cat->cat_appender)
  220. log4c_appender_append(cat->cat_appender, &evt);
  221. if (!cat->cat_additive) break;
  222. }
  223. if (!evt.evt_buffer.buf_maxsize)
  224. {
  225. free(message);
  226. free(evt.evt_buffer.buf_data);
  227. }
  228. }
  229. /*******************************************************************************/
  230. extern void __log4c_category_vlog_no_file_num_no_layout(
  231. const log4c_category_t* ptrThis,
  232. const log4c_location_info_t* a_locinfo,
  233. int a_priority,
  234. const TCHAR* a_format,
  235. va_list a_args)
  236. {
  237. TCHAR* message;
  238. log4c_logging_event_t evt;
  239. const log4c_category_t* cat;
  240. int yes = 0;
  241. if (!ptrThis)
  242. return;
  243. /* check if an appender is defined in the category hierarchy */
  244. for (cat = ptrThis; cat; cat = cat->cat_parent) {
  245. if (cat->cat_appender)
  246. yes++;
  247. }
  248. if (!yes)
  249. return;
  250. log4c_reread();
  251. /* when there is no limit on the buffer size, we use malloc() to
  252. * give the user the possiblity to reallocate if necessary. When
  253. * the buffer is limited in size, we use alloca() for more
  254. * efficiency.
  255. */
  256. evt.evt_buffer.buf_maxsize = log4c_rc->config.bufsize;
  257. if (!evt.evt_buffer.buf_maxsize) {
  258. evt.evt_buffer.buf_size = LOG4C_BUFFER_SIZE_DEFAULT;
  259. evt.evt_buffer.buf_data = (TCHAR*)sd_malloc(evt.evt_buffer.buf_size);
  260. message = sd_vsprintf(a_format, a_args);
  261. }
  262. else {
  263. size_t n;
  264. evt.evt_buffer.buf_size = evt.evt_buffer.buf_maxsize;
  265. evt.evt_buffer.buf_data = (TCHAR*)alloca(evt.evt_buffer.buf_size);
  266. message = (TCHAR*)alloca(evt.evt_buffer.buf_size);
  267. if ( (n = (size_t)_vsntprintf(message, evt.evt_buffer.buf_size, a_format, a_args))
  268. >= evt.evt_buffer.buf_size)
  269. sd_error(_T("truncating message of %d bytes (bufsize = %d)"), n,
  270. evt.evt_buffer.buf_size);
  271. }
  272. evt.evt_category = ptrThis->cat_name;
  273. evt.evt_priority = a_priority;
  274. evt.evt_msg = message;
  275. evt.evt_loc = a_locinfo;
  276. SD_GETTIMEOFDAY(&evt.evt_timestamp, NULL);
  277. for (cat = ptrThis; cat; cat = cat->cat_parent) {
  278. if (cat->cat_appender)
  279. log4c_appender_append_no_file_num_no_layout(cat->cat_appender, &evt);
  280. if (!cat->cat_additive) break;
  281. }
  282. if (!evt.evt_buffer.buf_maxsize) {
  283. free(message);
  284. free(evt.evt_buffer.buf_data);
  285. }
  286. }
  287. /*******************************************************************************/
  288. static const TCHAR* dot_dirname(TCHAR* a_string)
  289. {
  290. TCHAR* p;
  291. if (!a_string)
  292. return NULL;
  293. if ( (p = _tcsrchr(a_string, _T('.'))) == NULL)
  294. return LOG4C_CATEGORY_DEFAULT;
  295. *p = _T('\0');
  296. return a_string;
  297. }