ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
console.c
Go to the documentation of this file.
1
7#include <emscripten.h>
8#include <string.h>
9#include <ascii-chat/log/logging.h>
10#include <stdint.h>
11#include <stddef.h>
12
13// EM_JS bridge: route to appropriate console method based on log level
14// level: 0=DEV, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=FATAL
15EM_JS(void, js_console_log, (int level, const char *message), {
16 const msg = UTF8ToString($1);
17
18 switch ($0) {
19 case 0: // LOG_DEV
20 case 1: // LOG_DEBUG
21 console.debug(msg);
22 break;
23 case 2: // LOG_INFO
24 console.log(msg);
25 break;
26 case 3: // LOG_WARN
27 console.warn(msg);
28 break;
29 case 4: // LOG_ERROR
30 case 5: // LOG_FATAL
31 console.error(msg);
32 break;
33 default:
34 console.log(msg);
35 }
36});
37
38// Platform hook called by logging system
39// This is called after each log message is formatted, before printing to stderr/stdout
40void platform_log_hook(log_level_t level, const char *message) {
41 if (message) {
42 js_console_log((int)level, message);
43 }
44}
45
46// Parse log level from formatted message: "[LEVEL] message..."
47// Returns the log_level_t enum value, or -1 if not found
48int wasm_parse_log_level(const uint8_t *buf, size_t count) {
49 if (!buf || count < 5) {
50 return -1; // Too short to contain [LEVEL]
51 }
52
53 // Check if message starts with [
54 if (buf[0] != '[') {
55 return -1;
56 }
57
58 // Look for closing ]
59 int bracket_end = -1;
60 for (size_t i = 1; i < count && i < 10; i++) {
61 if (buf[i] == ']') {
62 bracket_end = (int)i;
63 break;
64 }
65 }
66
67 if (bracket_end < 3) {
68 return -1; // Too short, minimum is [XX]
69 }
70
71 // Extract level string
72 int level_len = bracket_end - 1;
73 const char *level_start = (const char *)&buf[1];
74
75 // Match against known level strings (from logging.c)
76 if (level_len == 3 && strncmp(level_start, "DEV", 3) == 0) {
77 return LOG_DEV;
78 }
79 if (level_len == 5 && strncmp(level_start, "DEBUG", 5) == 0) {
80 return LOG_DEBUG;
81 }
82 if (level_len == 4 && strncmp(level_start, "INFO", 4) == 0) {
83 return LOG_INFO;
84 }
85 if (level_len == 4 && strncmp(level_start, "WARN", 4) == 0) {
86 return LOG_WARN;
87 }
88 if (level_len == 5 && strncmp(level_start, "ERROR", 5) == 0) {
89 return LOG_ERROR;
90 }
91 if (level_len == 5 && strncmp(level_start, "FATAL", 5) == 0) {
92 return LOG_FATAL;
93 }
94
95 return -1; // Level not recognized
96}
97
98// Public API for logging to console
99void wasm_log_to_console(int fd, const uint8_t *buf, size_t count) {
100 // For WASM, route stdout/stderr to browser console
101 if ((fd == 1 || fd == 2) && buf && count > 0) {
102 // Parse log level from formatted message
103 int level = wasm_parse_log_level(buf, count);
104 if (level >= 0) {
105 // Create null-terminated string for console output
106 // Copy buffer to local array and null-terminate
107 static char msg_buffer[4096];
108 size_t copy_len = (count < sizeof(msg_buffer) - 1) ? count : (sizeof(msg_buffer) - 1);
109 memcpy(msg_buffer, buf, copy_len);
110 msg_buffer[copy_len] = '\0';
111
112 // Remove trailing newline if present (console adds it automatically)
113 if (copy_len > 0 && msg_buffer[copy_len - 1] == '\n') {
114 msg_buffer[copy_len - 1] = '\0';
115 }
116
117 // Route to console
118 js_console_log(level, msg_buffer);
119 }
120 }
121}
int wasm_parse_log_level(const uint8_t *buf, size_t count)
Definition console.c:48
void platform_log_hook(log_level_t level, const char *message)
Definition console.c:40
void wasm_log_to_console(int fd, const uint8_t *buf, size_t count)
Definition console.c:99
EM_JS(void, js_console_log,(int level, const char *message), { const msg=UTF8ToString($1);switch($0) { case 0:case 1:console.debug(msg);break;case 2:console.log(msg);break;case 3:console.warn(msg);break;case 4:case 5:console.error(msg);break;default:console.log(msg);} })