Index

lognestmonster / 0306c29

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

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
13920 Nov 2019 15:1271af75aUtility upgradesJosh Stockin15311N

Blob @ lognestmonster / src / c / lognestmonster.h

text/plain7662 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}
57
58void lnm_pushable_push(lnm_pushable * pushable, lnmItem item) {
59 if (pushable->length+1 >= 65535) {
60 printf("lognestmonster (lnm_pushable_push): pushable reached cap length 65535. exiting...\n");
61 exit(1);
62 }
63 pushable->pushed = realloc(pushable->pushed, sizeof(lnmItem)*(pushable->length+1)); // reallocate with size: length+1
64 pushable->pushed[pushable->length] = item;
65 pushable->length += 1;
66}
67
68int lnm_pushable_indexof(lnm_pushable * pushable, lnmItem item) {
69 int len = pushable->length;
70 for (int iter = 0; iter<len; iter++) {
71 if (item == pushable->pushed[iter]) return iter;
72 }
73 return -1;
74}
75
76void lnm_pushable_remove(lnm_pushable * pushable, int index) {
77 if (index>=pushable->length || index < 0) {
78 printf("lognestmonster (lnm_pushable_remove): attempt to remove index out of pushable bounds. exiting...\n");
79 exit(1);
80 }
81 lnmItem * new_pushed = malloc(sizeof(lnmItem)*(pushable->length-1)); // map array excluding index
82 for (int iter = 0; iter<index; iter++) {
83 new_pushed[iter] = pushable->pushed[iter];
84 }
85 for (int iter = index+1; iter<pushable->length; iter++) {
86 new_pushed[iter-1] = pushable->pushed[iter];
87 }
88 free(pushable->pushed);
89 pushable->length--;
90 pushable->pushed = new_pushed;
91}
92
93
94// Statement and event structure definitions
95
96typedef struct {
97 uint8_t type:1; // Used internally; 0 = statement, 1 = event
98 lnm_pushable * pushed; // array of memory locations for lnm_event and lnm_log_statement structs
99} lnm_log_event;
100
101typedef struct {
102 // word 1, 4 bytes data 4 bytes padding
103 uint8_t type:1; // Used internally; 0 = statement, 1 = event
104 uint8_t verbosity:3; // lnmVerbosityLevel, 0-5
105 uint8_t tag_size; // character length of the tag
106 uint16_t message_size; // character length of the message
107
108 // word 2, 8 bytes data
109 uint64_t timestamp; // 64-bit millisecond timestamp
110
111 // word 3, 8 bytes data
112 char * log; // tag string + message string
113} lnm_log_statement;
114
115
116// Library utilities
117
118unsigned long lnm_getus(void) {
119 struct timeval current_time;
120 gettimeofday(&current_time, NULL);
121 unsigned long ms = (current_time.tv_sec*1000000+current_time.tv_usec);
122 return ms;
123}
124
125unsigned long lnm_getms(void) {
126 return lnm_getus()/1000;
127}
128
129
130int lnm_isstatement(lnmItem item) {
131 lnm_log_statement * s = (lnm_log_statement *)item;
132 return !s->type;
133}
134
135
136// Item registry utils
137
138//lnm_pushable * registered_items = lnm_new_pushable();
139
140
141// Core library
142
143lnmItem lnmStatement(uint8_t verbosity, char * tag, char * message) {
144 lnm_log_statement * new_statement = malloc(sizeof(lnm_log_statement));
145 new_statement->type = 0;
146 new_statement->verbosity = verbosity;
147 new_statement->timestamp = lnm_getms();
148 int tlen = strlen(tag);
149 if (tlen > 255 || tlen < 0) {
150 printf("lognestmonster (lnmStatement): tag length %i is longer than the cap 255 characters. exiting...\n", tlen);
151 exit(1);
152 }
153 int mlen = strlen(message);
154 if (mlen > 65535 || mlen < 0) {
155 printf("lognestmonster (lnmStatement): message length %i is longer than the cap 65535 characters. exiting...\n", mlen);
156 exit(1);
157 }
158 new_statement->tag_size = tlen;
159 new_statement->message_size = mlen;
160 new_statement->log = malloc(tlen+mlen+1);
161 strcpy(new_statement->log, tag);
162 strcat(new_statement->log, message);
163 return (lnmItem)new_statement;
164}
165
166
167lnmItem lnmEvent(void) {
168 lnm_log_event * new_event = malloc(sizeof(lnm_log_event));
169 new_event->type = 1;
170 new_event->pushed = lnm_new_pushable();
171 return (lnmItem)new_event;
172}
173
174void lnmEventPush(lnmItem event, lnmItem item) {
175 if (event == item) {
176 printf("lognestmonster (lnmEventPush): attempt to push event to self. exiting...\n");
177 exit(1);
178 }
179 lnm_log_event * event_t = (lnm_log_event *)event;
180 if (event_t->type != 1) {
181 printf("lognestmonster (lnmEventPush): cannot cast non-event to event type. exiting...\n");
182 exit(1);
183 }
184 lnm_pushable_push(event_t->pushed, item);
185}
186
187void lnmEventPushS(lnmItem event, uint8_t verbosity, char * tag, char * message) {
188 lnmItem statement = lnmStatement(verbosity, tag, message);
189 lnmEventPush(event, statement);
190}
191
192lnmItem lnmEventI(lnmItem item) {
193 lnmItem event = lnmEvent();
194 lnmEventPush(event, item);
195 return event;
196}
197
198lnmItem lnmEventS(uint8_t verbosity, char * tag, char * message) {
199 lnmItem statement = lnmStatement(verbosity, tag, message);
200 return lnmEventI(statement);
201}
202
203
204void lnm_debug_tabs(int count) {
205 for (int i = 0; i < count; i++) {
206 printf(" ");
207 }
208}
209
210void lnm_debug_parse(lnmItem item, int tabcount) {
211 if (lnm_isstatement(item)) {
212 lnm_log_statement * statement = (lnm_log_statement *) item;
213 lnm_debug_tabs(tabcount);
214 printf("Statement {\n");
215
216 lnm_debug_tabs(tabcount+1);
217 char * verbosity;
218 switch (statement->verbosity) {
219 case 0:
220 verbosity = "INFO";
221 break;
222 case 1:
223 verbosity = "DEBUG";
224 break;
225 case 2:
226 verbosity = "VERBOSE";
227 break;
228 case 3:
229 verbosity = "VERYVERBOSE";
230 break;
231 case 4:
232 verbosity = "WARNING";
233 break;
234 case 5:
235 verbosity = "ERROR";
236 break;
237 }
238 printf("Verbosity %s\n", verbosity);
239
240 lnm_debug_tabs(tabcount+1);
241 printf("Timestamp %ld\n", statement->timestamp);
242
243 lnm_debug_tabs(tabcount+1);
244 char tag[statement->tag_size+1];
245 strncpy(tag, statement->log, statement->tag_size);
246 tag[statement->tag_size] = '\0';
247 printf("Tag (%i) %s\n", statement->tag_size, tag);
248
249 lnm_debug_tabs(tabcount+1);
250 char message[statement->message_size+1];
251 strncpy(message, statement->log+statement->tag_size, statement->message_size);
252 message[statement->message_size] = '\0';
253 printf("Message (%i) %s\n", statement->message_size, message);
254
255 lnm_debug_tabs(tabcount);
256 printf("}\n");
257 } else if (!lnm_isstatement(item)) {
258 lnm_log_event * event = (lnm_log_event *) item;
259 lnm_debug_tabs(tabcount);
260 printf("Event (%i) [\n", event->pushed->length);
261 for (int i = 0; i < event->pushed->length; i++) {
262 lnmItem item = event->pushed->pushed[i];
263 lnm_debug_parse(item, tabcount + 1);
264 }
265 lnm_debug_tabs(tabcount);
266 printf("]\n");
267 } else {
268 printf("lognestmonster (lnm_debug_parse): unknown item type. exiting...\n");
269 exit(1);
270 }
271}
272
273#endif
274