Index

lognestmonster / 6511286

A general-purpose single-header C logging library and parser for event-based logs. (Incomplete)

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
13819 Nov 2019 22:236511286Condition and exception handlingJosh Stockin1112N

Blob @ lognestmonster / src / c / lognestmonster.h

text/plain6479 bytesdownload raw
1// lognestmonster Copyright (c) 2019 Joshua 'joshuas3' Stockin
2// lognestmonster.h
3// C header file for implementation of the lognestmonster logging library
4
5// <https://github.com/JoshuaS3/lognestmonster/>.
6
7
8// This file is part of lognestmonster.
9
10// lognestmonster is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14
15// lognestmonster is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19
20// You should have received a copy of the GNU General Public License
21// along with lognestmonster. If not, see <https://www.gnu.org/licenses/>.
22
23#ifndef __LOGNESTMONSTER__
24#define __LOGNESTMONSTER__ 1
25
26// SEMANTICS
27// internal definitions: lnm_lower_camel_case
28// public definitions: lnmUpperCamelCase
29
30// stdc inclusions
31
32#include <stdint.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/time.h>
36
37
38// Base definitions
39
40enum lnmVerbosityLevel {lnmInfo, lnmDebug, lnmVerbose, lnmVeryVerbose, lnmWarning, lnmError};
41typedef uint8_t * lnmItem;
42
43
44// Pushable structure
45
46typedef struct {
47 uint16_t length;
48 lnmItem * pushed;
49} lnm_pushable;
50
51lnm_pushable * lnm_new_pushable() {
52 lnm_pushable * new_pushable = malloc(sizeof(lnm_pushable));
53 new_pushable->length = 0;
54 new_pushable->pushed = malloc(0);
55 return new_pushable;
56}
57void lnm_pushable_push(lnm_pushable * pushable, lnmItem item) {
58 if (pushable->length+1 >= 65535) {
59 printf("lognestmonster: pushable reached cap length 65535");
60 exit(1);
61 }
62 pushable->pushed = realloc(pushable->pushed, sizeof(lnmItem)*(pushable->length+1)); // reallocate with size: length+1
63 pushable->pushed[pushable->length] = item;
64 pushable->length += 1;
65}
66
67
68// Statement and event structure definitions
69
70typedef struct {
71 uint8_t type:1; // Used internally; 0 = statement, 1 = event
72 lnm_pushable * pushed; // array of memory locations for lnm_event and lnm_log_statement structs
73} lnm_log_event;
74
75typedef struct {
76 // word 1, 4 bytes data 4 bytes padding
77 uint8_t type:1; // Used internally; 0 = statement, 1 = event
78 uint8_t verbosity:3; // lnmVerbosityLevel, 0-5
79 uint8_t tag_size; // character length of the tag
80 uint16_t message_size; // character length of the message
81
82 // word 2, 8 bytes data
83 uint64_t timestamp; // 64-bit millisecond timestamp
84
85 // word 3, 8 bytes data
86 char * log; // tag string + message string
87} lnm_log_statement;
88
89
90// Core library
91
92unsigned long lnm_getus(void) {
93 struct timeval current_time;
94 gettimeofday(&current_time, NULL);
95 unsigned long ms = (current_time.tv_sec*1000000+current_time.tv_usec);
96 return ms;
97}
98
99unsigned long lnm_getms(void) {
100 return lnm_getus()/1000;
101}
102
103lnmItem lnmStatement(uint8_t verbosity, char * tag, char * message) {
104 lnm_log_statement * new_statement = malloc(sizeof(lnm_log_statement));
105 new_statement->type = 0;
106 new_statement->verbosity = verbosity;
107 new_statement->timestamp = lnm_getms();
108 int tlen = strlen(tag);
109 if (tlen > 255 || tlen < 0) {
110 printf("lognestmonster: tag length %i is longer than the cap 255 characters. exiting...\n", tlen);
111 exit(1);
112 }
113 int mlen = strlen(message);
114 if (mlen > 65535 || mlen < 0) {
115 printf("lognestmonster: message length %i is longer than the cap 65535 characters. exiting...\n", mlen);
116 exit(1);
117 }
118 new_statement->tag_size = tlen;
119 new_statement->message_size = mlen;
120 new_statement->log = malloc(tlen+mlen+1);
121 strcpy(new_statement->log, tag);
122 strcat(new_statement->log, message);
123 return (lnmItem)new_statement;
124}
125
126lnmItem lnmEvent(void) {
127 lnm_log_event * new_event = malloc(sizeof(lnm_log_event));
128 new_event->type = 1;
129 new_event->pushed = lnm_new_pushable();
130 return (lnmItem)new_event;
131}
132
133void lnmEventPush(lnmItem event, lnmItem item) {
134 if (event == item) {
135 printf("lognestmonster: attempt to push event to self. exiting...\n");
136 exit(1);
137 }
138 lnm_log_event * event_t = (lnm_log_event *)event;
139 if (event_t->type != 1) {
140 printf("lognestmonster: cannot cast non-event to event type. exiting...\n");
141 exit(1);
142 }
143 lnm_pushable_push(event_t->pushed, item);
144}
145
146void lnmEventPushS(lnmItem event, uint8_t verbosity, char * tag, char * message) {
147 lnmItem statement = lnmStatement(verbosity, tag, message);
148 lnmEventPush(event, statement);
149}
150
151lnmItem lnmEventI(lnmItem item) {
152 lnmItem event = lnmEvent();
153 lnmEventPush(event, item);
154 return event;
155}
156
157lnmItem lnmEventS(uint8_t verbosity, char * tag, char * message) {
158 lnmItem statement = lnmStatement(verbosity, tag, message);
159 return lnmEventI(statement);
160}
161
162void lnm_debug_tabs(int count) {
163 for (int i = 0; i < count; i++) {
164 printf(" ");
165 }
166}
167
168void lnm_debug_parse(lnmItem item, int tabcount) {
169 lnm_log_statement * statement = (lnm_log_statement *) item;
170 if (statement->type == 0) {
171 lnm_debug_tabs(tabcount);
172 printf("Statement {\n");
173
174 lnm_debug_tabs(tabcount+1);
175 char * verbosity;
176 switch (statement->verbosity) {
177 case 0:
178 verbosity = "INFO";
179 break;
180 case 1:
181 verbosity = "DEBUG";
182 break;
183 case 2:
184 verbosity = "VERBOSE";
185 break;
186 case 3:
187 verbosity = "VERYVERBOSE";
188 break;
189 case 4:
190 verbosity = "WARNING";
191 break;
192 case 5:
193 verbosity = "ERROR";
194 break;
195 }
196 printf("Verbosity %s\n", verbosity);
197
198 lnm_debug_tabs(tabcount+1);
199 printf("Timestamp %ld\n", statement->timestamp);
200
201 lnm_debug_tabs(tabcount+1);
202 char tag[statement->tag_size+1];
203 strncpy(tag, statement->log, statement->tag_size);
204 tag[statement->tag_size] = '\0';
205 printf("Tag (%i) %s\n", statement->tag_size, tag);
206
207 lnm_debug_tabs(tabcount+1);
208 char message[statement->message_size+1];
209 strncpy(message, statement->log+statement->tag_size, statement->message_size);
210 message[statement->message_size] = '\0';
211 printf("Message (%i) %s\n", statement->message_size, message);
212
213 lnm_debug_tabs(tabcount);
214 printf("}\n");
215 } else if (statement->type == 1) {
216 lnm_debug_tabs(tabcount);
217 lnm_log_event * event = (lnm_log_event *) item;
218 printf("Event (%i) [\n", event->pushed->length);
219 for (int i = 0; i < event->pushed->length; i++) {
220 lnmItem item = event->pushed->pushed[i];
221 lnm_debug_parse(item, tabcount + 1);
222 }
223 lnm_debug_tabs(tabcount);
224 printf("]\n");
225 } else {
226 printf("Bad item type\n");
227 exit(1);
228 }
229}
230
231#endif
232