ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
wasm.c
Go to the documentation of this file.
1
6
7/* Storage capacities in elements; text buffers include the terminating NUL. */
8#define LOG_WASM_CLEAN_MESSAGE_BUFFER_SIZE 4096
9#define LOG_WASM_MSG_BUFFER_SIZE 4096
10
11#include <emscripten.h>
12#include <string.h>
13#include <ascii-chat/log/log.h>
15#include <stdint.h>
16#include <stddef.h>
17
18// EM_JS bridge: route to appropriate console method based on log level
19// level: 0=DEV, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=FATAL
20// Message contains the COMPLETE formatted log line with timestamp, level, thread, file:line, etc.
21// clang-format off
22EM_JS(void, js_console_log, (int level, const char *message), {
23 const msg = UTF8ToString(message);
24 const levelNames = [ 'DEV', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL' ];
25 const levelName = (level >= 0 && level <= 5) ? levelNames[level] : '?????';
26
27 // Debug: show message length to verify content is being passed
28 const msgLen = msg.length;
29 const hasTimestamp =
30 msg.startsWith('[') && msg.includes(':') && msg.includes('.') && msg[msg.indexOf(']') + 1] === ' ';
31 const debugInfo = `[WASM_MSG_LEN = ${msgLen}, HAS_TS = ${hasTimestamp}]`;
32
33 // Route to appropriate console method
34 switch (level) {
35 case 0: // LOG_DEV
36 case 1: // LOG_DEBUG
37 case 2: // LOG_INFO
38 console.log(debugInfo, msg);
39 break;
40 case 3: // LOG_WARN
41 console.warn(debugInfo, msg);
42 break;
43 case 4: // LOG_ERROR
44 case 5: // LOG_FATAL
45 console.error(debugInfo, msg);
46 break;
47 default:
48 console.log(debugInfo, msg);
49 }
50});
51// clang-format on
52
53// Platform hook called by logging system
54// This is called after each log message is formatted, before printing to stderr/stdout
55// The message parameter contains the COMPLETE formatted log line with ANSI codes:
56// [HH:MM:SS.microseconds] [LEVEL] [thread/name] file:line@function(): message
57// We strip the ANSI codes before sending to browser console for clean output
58void platform_log_hook(log_level_t level, const char *message) {
59 if (message) {
60 // Strip ANSI codes for clean browser console output
61 static char clean_message[LOG_WASM_CLEAN_MESSAGE_BUFFER_SIZE];
62 strip_ansi_codes(message, clean_message, sizeof(clean_message));
63 js_console_log((int)level, clean_message);
64 }
65}
66
67// Parse log level from formatted message: "[LEVEL] message..."
68// Returns the log_level_t enum value, or -1 if not found
69int wasm_parse_log_level(const uint8_t *buf, size_t count) {
70 if (!buf || count < 5) {
71 return -1; // Too short to contain [LEVEL]
72 }
73
74 // Check if message starts with [
75 if (buf[0] != '[') {
76 return -1;
77 }
78
79 // Look for closing ]
80 int bracket_end = -1;
81 for (size_t i = 1; i < count && i < 10; i++) {
82 if (buf[i] == ']') {
83 bracket_end = (int)i;
84 break;
85 }
86 }
87
88 if (bracket_end < 3) {
89 return -1; // Too short, minimum is [XX]
90 }
91
92 // Extract level string
93 int level_len = bracket_end - 1;
94 const char *level_start = (const char *)&buf[1];
95
96 // Match against known level strings (from logging.c)
97 if (level_len == 3 && strncmp(level_start, "DEV", 3) == 0) {
98 return LOG_DEV;
99 }
100 if (level_len == 5 && strncmp(level_start, "DEBUG", 5) == 0) {
101 return LOG_DEBUG;
102 }
103 if (level_len == 4 && strncmp(level_start, "INFO", 4) == 0) {
104 return LOG_INFO;
105 }
106 if (level_len == 4 && strncmp(level_start, "WARN", 4) == 0) {
107 return LOG_WARN;
108 }
109 if (level_len == 5 && strncmp(level_start, "ERROR", 5) == 0) {
110 return LOG_ERROR;
111 }
112 if (level_len == 5 && strncmp(level_start, "FATAL", 5) == 0) {
113 return LOG_FATAL;
114 }
115
116 return -1; // Level not recognized
117}
118
119// Public API for logging to console
120void wasm_log_to_console(int fd, const uint8_t *buf, size_t count) {
121 // For WASM, route stdout/stderr to browser console
122 if ((fd == 1 || fd == 2) && buf && count > 0) {
123 // Parse log level from formatted message
124 int level = wasm_parse_log_level(buf, count);
125 if (level >= 0) {
126 // Create null-terminated string for console output
127 // Copy buffer to local array and null-terminate
128 static char msg_buffer[LOG_WASM_MSG_BUFFER_SIZE];
129 size_t copy_len = (count < sizeof(msg_buffer) - 1) ? count : (sizeof(msg_buffer) - 1);
130 memcpy(msg_buffer, buf, copy_len);
131 msg_buffer[copy_len] = '\0';
132
133 // Remove trailing newline if present (console adds it automatically)
134 if (copy_len > 0 && msg_buffer[copy_len - 1] == '\n') {
135 msg_buffer[copy_len - 1] = '\0';
136 }
137
138 // Route to console
139 js_console_log(level, msg_buffer);
140 }
141 }
142}
unsigned char uint8_t
Definition common.h:60
log_level_t
Logging levels enumeration.
Definition types.h:29
void strip_ansi_codes(const char *input, char *output, size_t output_size)
Strip ANSI escape codes from a string.
Definition string.c:374
📝 Logging API with multiple log levels and terminal output control
🔤 String Manipulation and Shell Escaping Utilities
#define LOG_DEV
Definition types.h:38
#define LOG_DEBUG
Definition types.h:39
#define LOG_FATAL
Definition types.h:43
#define LOG_ERROR
Definition types.h:42
#define LOG_WARN
Definition types.h:41
#define LOG_INFO
Definition types.h:40
#define LOG_WASM_MSG_BUFFER_SIZE
Definition wasm.c:9
EM_JS(void, js_console_log,(int level, const char *message), { const msg=UTF8ToString(message);const levelNames=[ 'DEV', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'];const levelName=(level >=0 &&level<=5) ? levelNames[level] :'???^;const msgLen=msg.length;const hasTimestamp=msg.startsWith('[') &&msg.includes(':') &&msg.includes('.') &&msg[msg.indexOf(']')+1]===' ';const debugInfo=`[WASM_MSG_LEN=${msgLen}, HAS_TS=${hasTimestamp}]`;switch(level) { case 0:case 1:case 2:console.log(debugInfo, msg);break;case 3:console.warn(debugInfo, msg);break;case 4:case 5:console.error(debugInfo, msg);break;default:console.log(debugInfo, msg);} })
int wasm_parse_log_level(const uint8_t *buf, size_t count)
Parse log level from formatted message.
Definition wasm.c:69
void platform_log_hook(log_level_t level, const char *message)
Definition wasm.c:58
#define LOG_WASM_CLEAN_MESSAGE_BUFFER_SIZE
Definition wasm.c:8
void wasm_log_to_console(int fd, const uint8_t *buf, size_t count)
Route output to browser console based on log level.
Definition wasm.c:120