17 if (!message || !width || !height) {
18 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid parameters for size message parsing");
22 if (strncmp(message,
"SIZE:", 5) != 0) {
23 return SET_ERRNO(ERROR_INVALID_PARAM,
"Message does not start with 'SIZE:'");
26 const char *ptr = message + 5;
31 unsigned long w = strtoul(ptr, &endptr, 10);
32 if (errno != 0 || endptr == ptr || w > UINT_MAX || w == 0) {
33 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid width value in size message");
38 return SET_ERRNO(ERROR_INVALID_PARAM,
"Missing comma separator in size message");
44 unsigned long h = strtoul(ptr, &endptr, 10);
45 if (errno != 0 || endptr == ptr || h > UINT_MAX || h == 0) {
46 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid height value in size message");
50 if (*endptr !=
'\n' && *endptr !=
'\0') {
51 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid format: size message should end with newline or null terminator");
55 if (w > 65535 || h > 65535) {
56 return SET_ERRNO(ERROR_INVALID_PARAM,
"Size values too large (max 65535)");
59 *width = (
unsigned int)w;
60 *height = (
unsigned int)h;
65 if (!message || !num_samples) {
66 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid parameters for audio message parsing");
70 if (strncmp(message,
"AUDIO:", 6) != 0) {
71 return SET_ERRNO(ERROR_INVALID_PARAM,
"Message does not start with 'AUDIO:'");
74 const char *ptr = message + 6;
79 unsigned long samples = strtoul(ptr, &endptr, 10);
80 if (errno != 0 || endptr == ptr || samples > UINT_MAX || samples == 0) {
81 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid sample count value in audio message");
85 if (*endptr !=
'\n' && *endptr !=
'\0') {
86 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid format: audio message should end with newline or null terminator");
89 *num_samples = (
unsigned int)samples;
98asciichat_error_t
parse_long(
const char *str,
long *out_value,
long min_value,
long max_value) {
100 return SET_ERRNO(ERROR_INVALID_PARAM,
"String pointer is NULL");
104 return SET_ERRNO(ERROR_INVALID_PARAM,
"Output pointer is NULL");
108 return SET_ERRNO(ERROR_INVALID_PARAM,
"Empty string cannot be parsed as integer");
114 long value = strtol(str, &endptr, 10);
117 if (errno == ERANGE) {
118 return SET_ERRNO(ERROR_INVALID_PARAM,
"Integer value out of range: %s", str);
122 if (endptr == str || *endptr !=
'\0') {
123 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid integer format: %s", str);
127 if (value < min_value) {
128 return SET_ERRNO(ERROR_INVALID_PARAM,
"Integer value %ld is below minimum %ld", value, min_value);
131 if (value > max_value) {
132 return SET_ERRNO(ERROR_INVALID_PARAM,
"Integer value %ld exceeds maximum %ld", value, max_value);
139asciichat_error_t
parse_ulong(
const char *str,
unsigned long *out_value,
unsigned long min_value,
140 unsigned long max_value) {
142 return SET_ERRNO(ERROR_INVALID_PARAM,
"String pointer is NULL");
146 return SET_ERRNO(ERROR_INVALID_PARAM,
"Output pointer is NULL");
150 return SET_ERRNO(ERROR_INVALID_PARAM,
"Empty string cannot be parsed as integer");
156 unsigned long value = strtoul(str, &endptr, 10);
159 if (errno == ERANGE) {
160 return SET_ERRNO(ERROR_INVALID_PARAM,
"Integer value out of range: %s", str);
164 if (endptr == str || *endptr !=
'\0') {
165 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid integer format: %s", str);
169 if (value < min_value) {
170 return SET_ERRNO(ERROR_INVALID_PARAM,
"Integer value %lu is below minimum %lu", value, min_value);
173 if (value > max_value) {
174 return SET_ERRNO(ERROR_INVALID_PARAM,
"Integer value %lu exceeds maximum %lu", value, max_value);
181asciichat_error_t
parse_ulonglong(
const char *str,
unsigned long long *out_value,
unsigned long long min_value,
182 unsigned long long max_value) {
184 return SET_ERRNO(ERROR_INVALID_PARAM,
"String pointer is NULL");
188 return SET_ERRNO(ERROR_INVALID_PARAM,
"Output pointer is NULL");
192 return SET_ERRNO(ERROR_INVALID_PARAM,
"Empty string cannot be parsed as integer");
198 unsigned long long value = strtoull(str, &endptr, 10);
201 if (errno == ERANGE) {
202 return SET_ERRNO(ERROR_INVALID_PARAM,
"Integer value out of range: %s", str);
206 if (endptr == str || *endptr !=
'\0') {
207 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid integer format: %s", str);
211 if (value < min_value) {
212 return SET_ERRNO(ERROR_INVALID_PARAM,
"Integer value too small (below minimum)");
215 if (value > max_value) {
216 return SET_ERRNO(ERROR_INVALID_PARAM,
"Integer value too large (exceeds maximum)");
251asciichat_error_t
parse_port(
const char *str, uint16_t *out_port) {
253 return SET_ERRNO(ERROR_INVALID_PARAM,
"String pointer is NULL");
257 return SET_ERRNO(ERROR_INVALID_PARAM,
"Output pointer is NULL");
261 return SET_ERRNO(ERROR_INVALID_PARAM,
"Empty string cannot be parsed as port");
264 pcre2_code *regex = port_regex_get();
267 unsigned long port_ulong;
268 asciichat_error_t err =
parse_ulong(str, &port_ulong, 1, 65535);
269 if (err != ASCIICHAT_OK) {
270 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid port number: %s (must be 1-65535)", str);
272 *out_port = (uint16_t)port_ulong;
277 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(regex, NULL);
279 log_error(
"Failed to allocate match data for port validation");
280 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid port number: %s (must be 1-65535)", str);
283 int match_result = pcre2_jit_match(regex, (PCRE2_SPTR8)str, strlen(str), 0, 0, match_data, NULL);
284 pcre2_match_data_free(match_data);
286 if (match_result < 0) {
288 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid port number: %s (must be 1-65535)", str);
293 unsigned long port_value = strtoul(str, &endptr, 10);
295 if (port_value < 1 || port_value > 65535) {
296 return SET_ERRNO(ERROR_INVALID_PARAM,
"Port out of range: %lu", port_value);
299 *out_port = (uint16_t)port_value;
303asciichat_error_t
parse_int32(
const char *str, int32_t *out_value, int32_t min_value, int32_t max_value) {
305 return SET_ERRNO(ERROR_INVALID_PARAM,
"String pointer is NULL");
309 return SET_ERRNO(ERROR_INVALID_PARAM,
"Output pointer is NULL");
313 asciichat_error_t err =
parse_long(str, &value, (
long)min_value, (
long)max_value);
314 if (err != ASCIICHAT_OK) {
318 *out_value = (int32_t)value;
322asciichat_error_t
parse_uint32(
const char *str, uint32_t *out_value, uint32_t min_value, uint32_t max_value) {
324 return SET_ERRNO(ERROR_INVALID_PARAM,
"String pointer is NULL");
328 return SET_ERRNO(ERROR_INVALID_PARAM,
"Output pointer is NULL");
332 asciichat_error_t err =
parse_ulong(str, &value, (
unsigned long)min_value, (
unsigned long)max_value);
333 if (err != ASCIICHAT_OK) {
337 *out_value = (uint32_t)value;