| 1 | /* lognestmonster Copyright (c) 2020 Joshua 'joshuas3' Stockin |
| 2 | * <https://joshstock.in> |
| 3 | * <https://github.com/JoshuaS3/lognestmonster> |
| 4 | * |
| 5 | * This software is licensed and distributed under the terms of the MIT License: |
| 6 | * ----- BEGIN LICENSE ----- |
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 8 | * of this software and associated documentation files (the "Software"), to deal |
| 9 | * in the Software without restriction, including without limitation the rights |
| 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 11 | * copies of the Software, and to permit persons to whom the Software is |
| 12 | * furnished to do so, subject to the following conditions: |
| 13 | * |
| 14 | * The above copyright notice and this permission notice shall be included in |
| 15 | * all copies or substantial portions of the Software. |
| 16 | * |
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 23 | * SOFTWARE. |
| 24 | * ----- END LICENSE ----- |
| 25 | * |
| 26 | * This comment block MUST be preserved in all copies of this software's source. |
| 27 | */ |
| 28 |
|
| 29 | // lognestmonster.h |
| 30 | // C header file for implementation of the lognestmonster logging library |
| 31 |
|
| 32 | #ifdef __cplusplus // Linker protection |
| 33 | extern "C" { |
| 34 | #endif |
| 35 |
|
| 36 | // SEMANTICS |
| 37 | // internal definitions: lnm_lower_camel_case |
| 38 | // public definitions: lnmUpperCamelCase |
| 39 |
|
| 40 |
|
| 41 | // Declarations |
| 42 | #ifndef LOGNESTMONSTER_H |
| 43 | #define LOGNESTMONSTER_H 1 |
| 44 |
|
| 45 | // stdc inclusions |
| 46 |
|
| 47 | #include <stdint.h> |
| 48 | #include <inttypes.h> |
| 49 | #include <stdio.h> |
| 50 | #include <stdlib.h> |
| 51 | #include <string.h> |
| 52 |
|
| 53 | // non-universal inclusions |
| 54 |
|
| 55 | #include <sys/time.h> |
| 56 |
|
| 57 |
|
| 58 | enum lnmVerbosityLevel {lnmInfo, lnmDebug, lnmVerbose, lnmVeryVerbose, lnmWarning, lnmError}; |
| 59 | typedef uint8_t * lnmItem; |
| 60 | typedef uint8_t * lnmQueue; |
| 61 |
|
| 62 | lnmQueue lnmQueueInit(char * name, char * out_path); |
| 63 | lnmQueue lnmQueueByName(char * name); |
| 64 | lnmItem lnmStatement(enum lnmVerbosityLevel verbosity, char * tag, char * message); |
| 65 | lnmItem lnmEvent(void); |
| 66 | void lnmEventPush(lnmItem event, lnmItem item); |
| 67 | void lnmEventPushS(lnmItem event, uint8_t verbosity, char * tag, char * message); |
| 68 | lnmItem lnmEventI(lnmItem item); |
| 69 | lnmItem lnmEventS(uint8_t verbosity, char * tag, char * message); |
| 70 |
|
| 71 | #ifdef LNM_ALL // Exposes the private API declarations |
| 72 | |
| 73 | // Pushable utilities |
| 74 | typedef struct lnm_pushable lnm_pushable; |
| 75 |
|
| 76 | void lnm_pushable_realloc(lnm_pushable * pushable); |
| 77 | lnm_pushable * lnm_new_pushable(void); |
| 78 | void lnm_pushable_push(lnm_pushable * pushable, lnmItem item); |
| 79 | int lnm_pushable_indexof(lnm_pushable * pushable, lnmItem item); |
| 80 | void lnm_pushable_pop(lnm_pushable * pushable); |
| 81 | void lnm_pushable_remove(lnm_pushable * pushable, uint32_t index); |
| 82 | void lnm_pushable_free(lnm_pushable * pushable); |
| 83 |
|
| 84 | // Log item and object struct types |
| 85 | typedef struct lnm_log_event lnm_log_event; |
| 86 | typedef struct lnm_log_statement lnm_log_statement; |
| 87 | typedef struct lnm_queue lnm_queue; |
| 88 |
|
| 89 | // General utilities |
| 90 | unsigned long lnm_getus(void); |
| 91 | unsigned long lnm_getms(void); |
| 92 | int lnm_isstatement(lnmItem item); |
| 93 |
|
| 94 | // Registry utilities |
| 95 | void lnm_registry_update(void); |
| 96 |
|
| 97 | // Memory utilities |
| 98 | void lnm_free_item(lnmItem item); |
| 99 | void lnm_free_registry(void); |
| 100 | void lnm_free_queue(lnmQueue queue); |
| 101 |
|
| 102 | // Debug utilities |
| 103 | void lnm_debug_tabs(int count); |
| 104 | void lnm_debug_parse_item(lnmItem item, int tabcount); |
| 105 | void lnm_debug_parse_registry(void); |
| 106 | void lnm_debug_parse_queue(lnmQueue queue); |
| 107 |
|
| 108 | #endif // LNM_ALL, private declarations |
| 109 | #endif // LOGNESTMONSTER_H, public declarations |
| 110 | |
| 111 |
|
| 112 | #ifdef LNM_INIT // one-time definitions |
| 113 | |
| 114 |
|
| 115 | // Pushable structure |
| 116 |
|
| 117 | typedef struct lnm_pushable { |
| 118 | uint32_t capacity; |
| 119 | uint32_t length; |
| 120 | lnmItem * pushed; |
| 121 | } lnm_pushable; |
| 122 |
|
| 123 | void lnm_pushable_realloc(lnm_pushable * pushable) { |
| 124 | if (pushable->length > pushable->capacity) { |
| 125 | if (pushable->capacity * 2 <= pushable->capacity) { |
| 126 | printf("lognestmonster (lnm_pushable_realloc): pushable reached max length of 2^32-1. exiting...\n"); |
| 127 | exit(1); |
| 128 | } |
| 129 | pushable->pushed = realloc(pushable->pushed, sizeof(lnmItem) * (pushable->capacity *= 2)); |
| 130 | } else if (pushable->length < (pushable->capacity / 2)) { |
| 131 | if (pushable->capacity > 8) { |
| 132 | pushable->pushed = realloc(pushable->pushed, sizeof(lnmItem) * (pushable->capacity /= 2)); |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 |
|
| 137 | lnm_pushable * lnm_new_pushable(void) { |
| 138 | lnm_pushable * new_pushable = malloc(sizeof(lnm_pushable)); |
| 139 | new_pushable->capacity = 8; |
| 140 | new_pushable->length = 0; |
| 141 | new_pushable->pushed = malloc(sizeof(lnmItem)*new_pushable->capacity); |
| 142 | return new_pushable; |
| 143 | } |
| 144 |
|
| 145 | void lnm_pushable_push(lnm_pushable * pushable, lnmItem item) { |
| 146 | pushable->length++; |
| 147 | lnm_pushable_realloc(pushable); |
| 148 | pushable->pushed[pushable->length-1] = item; |
| 149 | } |
| 150 |
|
| 151 | int lnm_pushable_indexof(lnm_pushable * pushable, lnmItem item) { |
| 152 | int len = pushable->length; |
| 153 | for (int iter = 0; iter<len; iter++) { |
| 154 | if (item == pushable->pushed[iter]) return iter; |
| 155 | } |
| 156 | printf("lognestmonster (lnm_pushable_indexof): cannot find item in pushable. exiting...\n"); |
| 157 | exit(1); |
| 158 | } |
| 159 |
|
| 160 | void lnm_pushable_pop(lnm_pushable * pushable) { |
| 161 | pushable->length--; |
| 162 | lnm_pushable_realloc(pushable); |
| 163 | } |
| 164 |
|
| 165 | void lnm_pushable_remove(lnm_pushable * pushable, uint32_t index) { |
| 166 | if (index>=pushable->length) { |
| 167 | printf("lognestmonster (lnm_pushable_remove): attempt to remove index out of pushable bounds. exiting...\n"); |
| 168 | exit(1); |
| 169 | } |
| 170 | for (uint32_t iter = index; iter<pushable->length-1; iter++) { |
| 171 | pushable->pushed[iter] = pushable->pushed[iter+1]; |
| 172 | } |
| 173 | pushable->length--; |
| 174 | lnm_pushable_realloc(pushable); |
| 175 | } |
| 176 |
|
| 177 | void lnm_pushable_free(lnm_pushable * pushable) { |
| 178 | free(pushable->pushed); |
| 179 | free(pushable); |
| 180 | } |
| 181 |
|
| 182 |
|
| 183 | // Statement and event structure definitions |
| 184 |
|
| 185 | typedef struct lnm_log_event { |
| 186 | // word 1, 1 byte data 7 bytes padding |
| 187 | uint8_t type:1; // Used internally; 0 = statement, 1 = event |
| 188 | uint8_t boolpushed:1; // whether or not this log item has been pushed |
| 189 | uint8_t verbosity:3; // lnmVerbosityLevel, 0-5 |
| 190 |
|
| 191 | // word 2, 8 bytes data |
| 192 | char * tag; // tag string |
| 193 |
|
| 194 | // word 3, 8 bytes data |
| 195 | lnm_pushable * pushed; // array of memory locations for lnm_log_event and lnm_log_statement structs |
| 196 | } lnm_log_event; |
| 197 |
|
| 198 | typedef struct lnm_log_statement { |
| 199 | // word 1, 4 bytes data 4 bytes padding |
| 200 | uint8_t type:1; // Used internally; 0 = statement, 1 = event |
| 201 | uint8_t boolpushed:1; // whether or not this log item has been pushed |
| 202 | uint8_t verbosity:3; // lnmVerbosityLevel, 0-5 |
| 203 | uint8_t tag_size; // character length of the tag |
| 204 | uint16_t message_size; // character length of the message |
| 205 |
|
| 206 | // word 2, 8 bytes data |
| 207 | uint64_t timestamp; // 64-bit millisecond timestamp |
| 208 |
|
| 209 | // word 3, 8 bytes data |
| 210 | char * log; // tag string + message string |
| 211 | } lnm_log_statement; |
| 212 |
|
| 213 |
|
| 214 | // Queue structure definition |
| 215 |
|
| 216 | typedef struct lnm_queue { |
| 217 | char * name; |
| 218 | char * out_path; |
| 219 | uint64_t timestamp; |
| 220 | lnm_pushable * pushed; |
| 221 | } lnm_queue; |
| 222 |
|
| 223 |
|
| 224 | // Library utilities |
| 225 |
|
| 226 | unsigned long lnm_getus(void) { |
| 227 | struct timeval current_time; |
| 228 | gettimeofday(¤t_time, NULL); |
| 229 | unsigned long ms = (current_time.tv_sec*1000000+current_time.tv_usec); |
| 230 | return ms; |
| 231 | } |
| 232 |
|
| 233 | unsigned long lnm_getms(void) { |
| 234 | return lnm_getus()/1000; |
| 235 | } |
| 236 |
|
| 237 |
|
| 238 | int lnm_isstatement(lnmItem item) { |
| 239 | lnm_log_statement * s = (lnm_log_statement *)item; |
| 240 | return !s->type; |
| 241 | } |
| 242 |
|
| 243 |
|
| 244 | // Item registry utils |
| 245 |
|
| 246 | static lnm_pushable * lnm_registered_queues; |
| 247 | static lnm_pushable * lnm_registered_items; |
| 248 | static int lnm_registry_update_count; |
| 249 |
|
| 250 | void lnm_registry_update(void) { // scan each registered item |
| 251 | for (uint32_t iter = 0; iter < lnm_registered_items->length; iter++) { |
| 252 | lnm_log_statement * s = (lnm_log_statement *)lnm_registered_items->pushed[iter]; |
| 253 | if (s->boolpushed == 1) { // if the registered item has been pushed elsewhere, remove it from the top level of the registry |
| 254 | lnm_registry_update_count++; |
| 255 | lnm_pushable_remove(lnm_registered_items, iter); |
| 256 | iter--; |
| 257 | } |
| 258 | } |
| 259 | } |
| 260 |
|
| 261 |
|
| 262 | // Core library |
| 263 |
|
| 264 | void lnm_free_item(lnmItem item) { |
| 265 | lnm_log_statement * item_cast = (lnm_log_statement *)item; |
| 266 | if (item_cast->boolpushed == 0) { // flush item out of registry |
| 267 | item_cast->boolpushed = 1; |
| 268 | lnm_registry_update(); |
| 269 | } |
| 270 | if (item_cast->type == 0) { |
| 271 | free(item_cast->log); |
| 272 | free(item_cast); |
| 273 | } else if (item_cast->type == 1) { |
| 274 | lnm_log_event * event_cast = (lnm_log_event *)item_cast; |
| 275 |
|
| 276 | lnm_pushable * breadcrumb = lnm_new_pushable(); |
| 277 | lnm_pushable_push(breadcrumb, (lnmItem)event_cast); // add event_cast as the first step down the breadcrumb |
| 278 | while (breadcrumb->length > 0) { // while there are items still in the breadcrumb |
| 279 | lnm_log_statement * breadcrumb_item = (lnm_log_statement *)breadcrumb->pushed[breadcrumb->length-1]; // fetch the last (deepest) item |
| 280 | if (breadcrumb_item->type == 0) { // the item is a statement |
| 281 | lnm_pushable_pop(breadcrumb); // remove it from the breadcrumb |
| 282 | free(breadcrumb_item->log); // and free it |
| 283 | free(breadcrumb_item); |
| 284 | } else if (breadcrumb_item->type == 1) { |
| 285 | lnm_log_event * breadcrumb_item_cast = (lnm_log_event *)breadcrumb_item; // item is an event, cast pointer |
| 286 | if (breadcrumb_item_cast->pushed->length > 0) { // if the event is not empty |
| 287 | lnm_pushable_push(breadcrumb, breadcrumb_item_cast->pushed->pushed[breadcrumb_item_cast->pushed->length-1]); // push the last item of event into the breadcrumb |
| 288 | lnm_pushable_pop(breadcrumb_item_cast->pushed); // and remove it from this event's index |
| 289 | // there is now a new breadcrumb navigation layer. loop back to check the new item... |
| 290 | } else { |
| 291 | lnm_pushable_pop(breadcrumb); // event is finally empty, remove it from the breadcrumb and free it |
| 292 | lnm_pushable_free(breadcrumb_item_cast->pushed); |
| 293 | free(breadcrumb_item_cast); |
| 294 | } |
| 295 | } |
| 296 | } |
| 297 | } else { |
| 298 | printf("lognestmonster (lnm_free_item): non-log item passed to function. exiting...\n"); |
| 299 | exit(1); |
| 300 | } |
| 301 | } |
| 302 |
|
| 303 | void lnm_free_registry() { |
| 304 | for (uint32_t iter = 0; iter < lnm_registered_items->length; iter++) { |
| 305 | lnm_free_item(lnm_registered_items->pushed[iter]); |
| 306 | } |
| 307 | } |
| 308 |
|
| 309 | void lnm_free_queue(lnmQueue queue) { |
| 310 | lnm_queue * queue_cast = (lnm_queue *)queue; |
| 311 | for (uint32_t iter = 0; iter < queue_cast->pushed->length; iter++) { |
| 312 | lnm_free_item(queue_cast->pushed->pushed[iter]); |
| 313 | lnm_pushable_remove(queue_cast->pushed, iter--); |
| 314 | } |
| 315 | } |
| 316 |
|
| 317 |
|
| 318 | lnmQueue lnmQueueInit(char * name, char * out_path) { |
| 319 | if (lnm_registered_queues == NULL) { |
| 320 | lnm_registered_queues = lnm_new_pushable(); |
| 321 | } |
| 322 | if (lnm_registered_items == NULL) { |
| 323 | lnm_registered_items = lnm_new_pushable(); |
| 324 | } |
| 325 |
|
| 326 | lnm_queue * new_queue = malloc(sizeof(lnm_queue)); |
| 327 | new_queue->name = malloc(strlen(name)+1); |
| 328 | new_queue->out_path = malloc(strlen(out_path)+1); |
| 329 | strcpy(new_queue->name, name); |
| 330 | strcpy(new_queue->out_path, out_path); |
| 331 | new_queue->timestamp = lnm_getus(); |
| 332 | new_queue->pushed = lnm_new_pushable(); |
| 333 |
|
| 334 | lnm_pushable_push(lnm_registered_queues, (lnmQueue)new_queue); |
| 335 | return (lnmQueue)new_queue; |
| 336 | } |
| 337 |
|
| 338 | lnmQueue lnmQueueByName(char * name) { |
| 339 | if (lnm_registered_queues == NULL) { |
| 340 | printf("lognestmonster (lnmQueueByName): queue registry is nonexistant. exiting...\n"); |
| 341 | exit(1); |
| 342 | } |
| 343 | if (lnm_registered_queues->length == 0) { |
| 344 | printf("lognestmonster (lnmQueueByName): queue registry is empty. exiting...\n"); |
| 345 | exit(1); |
| 346 | } |
| 347 | for (uint32_t iter = 0; iter<lnm_registered_queues->length; iter++) { |
| 348 | lnm_queue * iterqueue = (lnm_queue *)lnm_registered_queues->pushed[iter]; |
| 349 | if (strcmp(iterqueue->name, name)==0) { |
| 350 | return (lnmQueue)iterqueue; |
| 351 | } |
| 352 | } |
| 353 | printf("lognestmonster (lnmQueueByName): queue not found in registry. exiting...\n"); |
| 354 | exit(1); |
| 355 | } |
| 356 |
|
| 357 | void lnmQueuePush(lnmQueue queue, lnmItem item) { |
| 358 | if (((lnm_log_statement *)item)->boolpushed == 1) { |
| 359 | printf("lognestmonster (lnmQueuePush): attempt to push an already-pushed log item. exiting...\n"); |
| 360 | exit(1); |
| 361 | } |
| 362 | lnm_pushable_push(((lnm_queue *)queue)->pushed, item); |
| 363 | ((lnm_log_statement *)item)->boolpushed = 1; |
| 364 | lnm_registry_update(); |
| 365 | } |
| 366 |
|
| 367 |
|
| 368 | lnmItem lnmStatement(enum lnmVerbosityLevel verbosity, char * tag, char * message) { |
| 369 | lnm_log_statement * new_statement = malloc(sizeof(lnm_log_statement)); |
| 370 | new_statement->type = 0; |
| 371 | new_statement->verbosity = verbosity; |
| 372 | new_statement->timestamp = lnm_getus(); |
| 373 | int tlen = strlen(tag); |
| 374 | if (tlen > 256 || tlen < 0) { |
| 375 | printf("lognestmonster (lnmStatement): tag length %i is longer than the cap 256 characters. exiting...\n", tlen); |
| 376 | exit(1); |
| 377 | } |
| 378 | int mlen = strlen(message); |
| 379 | if (mlen > 65536 || mlen < 0) { |
| 380 | printf("lognestmonster (lnmStatement): message length %i is longer than the cap 65536 characters. exiting...\n", mlen); |
| 381 | exit(1); |
| 382 | } |
| 383 | new_statement->tag_size = tlen; |
| 384 | new_statement->message_size = mlen; |
| 385 | new_statement->log = malloc(tlen+mlen+1); |
| 386 | strcpy(new_statement->log, tag); |
| 387 | strcat(new_statement->log, message); |
| 388 | lnm_registry_update(); |
| 389 | lnm_pushable_push(lnm_registered_items, (lnmItem)new_statement); |
| 390 | return (lnmItem)new_statement; |
| 391 | } |
| 392 |
|
| 393 |
|
| 394 | lnmItem lnmEvent(void) { |
| 395 | lnm_log_event * new_event = malloc(sizeof(lnm_log_event)); |
| 396 | new_event->type = 1; |
| 397 | new_event->pushed = lnm_new_pushable(); |
| 398 | lnm_registry_update(); |
| 399 | lnm_pushable_push(lnm_registered_items, (lnmItem)new_event); |
| 400 | return (lnmItem)new_event; |
| 401 | } |
| 402 |
|
| 403 | void lnmEventPush(lnmItem event, lnmItem item) { |
| 404 | if (event == item) { |
| 405 | printf("lognestmonster (lnmEventPush): attempt to push event to self. exiting...\n"); |
| 406 | exit(1); |
| 407 | } |
| 408 | lnm_log_statement * item_cast = (lnm_log_statement *)item; |
| 409 | if (item_cast->boolpushed == 1) { |
| 410 | printf("lognestmonster (lnmEventPush): attempt to push an already-pushed log item. exiting...\n"); |
| 411 | exit(1); |
| 412 | } |
| 413 | lnm_log_event * event_t = (lnm_log_event *)event; |
| 414 | if (event_t->type != 1) { |
| 415 | printf("lognestmonster (lnmEventPush): cannot cast non-event to event type. exiting...\n"); |
| 416 | exit(1); |
| 417 | } |
| 418 | lnm_pushable_push(event_t->pushed, item); |
| 419 | item_cast->boolpushed = 1; |
| 420 | lnm_registry_update(); |
| 421 | } |
| 422 |
|
| 423 | void lnmEventPushS(lnmItem event, uint8_t verbosity, char * tag, char * message) { |
| 424 | lnmItem statement = lnmStatement(verbosity, tag, message); |
| 425 | lnmEventPush(event, statement); |
| 426 | } |
| 427 |
|
| 428 | lnmItem lnmEventI(lnmItem item) { |
| 429 | lnmItem event = lnmEvent(); |
| 430 | lnmEventPush(event, item); |
| 431 | return event; |
| 432 | } |
| 433 |
|
| 434 | lnmItem lnmEventS(uint8_t verbosity, char * tag, char * message) { |
| 435 | lnmItem statement = lnmStatement(verbosity, tag, message); |
| 436 | return lnmEventI(statement); |
| 437 | } |
| 438 |
|
| 439 |
|
| 440 | void lnm_debug_tabs(int count) { |
| 441 | for (int i = 0; i < count; i++) { |
| 442 | printf(" "); |
| 443 | } |
| 444 | } |
| 445 |
|
| 446 | void lnm_debug_parse_item(lnmItem item, int tabcount) { |
| 447 | if (lnm_isstatement(item)) { |
| 448 | lnm_log_statement * statement = (lnm_log_statement *) item; |
| 449 | lnm_debug_tabs(tabcount); |
| 450 |
|
| 451 | char * verbosity; |
| 452 | switch (statement->verbosity) { |
| 453 | case 0: |
| 454 | verbosity = "INFO"; |
| 455 | break; |
| 456 | case 1: |
| 457 | verbosity = "DEBUG"; |
| 458 | break; |
| 459 | case 2: |
| 460 | verbosity = "VERBOSE"; |
| 461 | break; |
| 462 | case 3: |
| 463 | verbosity = "VERYVERBOSE"; |
| 464 | break; |
| 465 | case 4: |
| 466 | verbosity = "WARNING"; |
| 467 | break; |
| 468 | case 5: |
| 469 | verbosity = "ERROR"; |
| 470 | break; |
| 471 | } |
| 472 |
|
| 473 | char tag[statement->tag_size+1]; |
| 474 | strncpy(tag, statement->log, statement->tag_size); |
| 475 | tag[statement->tag_size] = '\0'; |
| 476 |
|
| 477 | char message[statement->message_size+1]; |
| 478 | strncpy(message, statement->log+statement->tag_size, statement->message_size); |
| 479 | message[statement->message_size] = '\0'; |
| 480 |
|
| 481 | printf("%" PRIu64 " (%s) %s :: %s\n", statement->timestamp, verbosity, tag, message); |
| 482 | } else if (!lnm_isstatement(item)) { |
| 483 | lnm_log_event * event = (lnm_log_event *) item; |
| 484 | lnm_debug_tabs(tabcount); |
| 485 | printf("Event (%" PRIu32 ") [%" PRIu32 "] [\n", event->pushed->length, event->pushed->capacity); |
| 486 | for (uint32_t i = 0; i < event->pushed->length; i++) { |
| 487 | lnmItem item = event->pushed->pushed[i]; |
| 488 | lnm_debug_parse_item(item, tabcount + 1); |
| 489 | } |
| 490 | lnm_debug_tabs(tabcount); |
| 491 | printf("]\n"); |
| 492 | } else { |
| 493 | printf("lognestmonster (lnm_debug_parse_item): unknown item type. exiting...\n"); |
| 494 | exit(1); |
| 495 | } |
| 496 | } |
| 497 |
|
| 498 | void lnm_debug_parse_registry(void) { |
| 499 | printf("Top level registry (%" PRIu32 ") [%" PRIu32 "] [\n", lnm_registered_items->length, lnm_registered_items->capacity); |
| 500 | for (uint32_t iter = 0; iter < lnm_registered_items->length; iter++) { |
| 501 | lnm_debug_parse_item(lnm_registered_items->pushed[iter], 1); |
| 502 | } |
| 503 | printf("]\n"); |
| 504 | } |
| 505 |
|
| 506 | void lnm_debug_parse_queue(lnmQueue queue) { |
| 507 | lnm_queue * queue_cast = (lnm_queue *)queue; |
| 508 | printf("Queue \"%s\" at %s (%" PRIu32 ") [%" PRIu32 "] [\n", queue_cast->name, queue_cast->out_path, queue_cast->pushed->length, queue_cast->pushed->capacity); |
| 509 | for (uint32_t iter = 0; iter < queue_cast->pushed->length; iter++) { |
| 510 | lnm_debug_parse_item((lnmItem)queue_cast->pushed->pushed[iter], 1); |
| 511 | } |
| 512 | printf("]\n"); |
| 513 | } |
| 514 | #endif // DEFINE_LOGNESTMONSTER |
| 515 | |
| 516 | #ifdef __cplusplus // Linker protection |
| 517 | } |
| 518 | #endif |
| 519 |
|