cmaybe/convert_to_ints.c

156 lines
3.3 KiB
C

#define _POSIX_C_SOURCE 200809L
#include <inttypes.h>
#include <setjmp.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "cmaybe.h"
MAYBE_TYPE(voidptr, void *);
MAYBE(voidptr) strchr_maybe(const void *s, int c) {
ENABLE_RETURN(voidptr);
void *location = strchr(s, c);
if (location == NULL) {
RETURN_NOTHING();
} else {
RETURN_VALUE(location);
}
}
MAYBE(voidptr) malloc_maybe(size_t size) {
ENABLE_RETURN(voidptr);
void *allocation = malloc(size);
if(allocation == NULL && size != 0) {
RETURN_NOTHING();
} else {
RETURN_VALUE(allocation);
}
}
MAYBE(voidptr) realloc_maybe(void *old, size_t size) {
ENABLE_RETURN(voidptr);
void *allocation = realloc(old, size);
if(allocation == NULL && size != 0) {
RETURN_NOTHING();
} else {
RETURN_VALUE(allocation);
}
}
MAYBE_TYPE(intmax_t, intmax_t);
MAYBE(intmax_t) str2int(const char *string) {
ENABLE_RETURN(intmax_t);
char *endptr;
intmax_t num = strtoimax(string, &endptr, 10);
if (*endptr == '\0' && string[0] != '\0') {
RETURN_VALUE(num);
} else {
RETURN_NOTHING();
}
}
struct intmax_t_array {
intmax_t *data;
size_t length;
size_t alloc_size;
};
MAYBE_TYPE(intmax_t_array, struct intmax_t_array);
MAYBE(intmax_t_array) create_array(void) {
ENABLE_RETURN(intmax_t_array);
ENABLE_TRY();
TRY_TYPE(voidptr);
struct intmax_t_array array;
array.length = 0;
array.alloc_size = sizeof(intmax_t);
array.data = TRY(voidptr, malloc_maybe(array.alloc_size));
RETURN_VALUE(array);
}
MAYBE(intmax_t_array) resize_array(struct intmax_t_array array, size_t length) {
ENABLE_RETURN(intmax_t_array);
ENABLE_TRY();
TRY_TYPE(voidptr);
struct intmax_t_array resized_array = {array.data, length, array.alloc_size};
if(resized_array.alloc_size / sizeof(intmax_t) < resized_array.length) {
if(SIZE_MAX / 2 < resized_array.alloc_size) {
RETURN_NOTHING();
}
resized_array.alloc_size *= 2;
resized_array.data = TRY(voidptr, realloc_maybe(resized_array.data, resized_array.alloc_size));
}
RETURN_VALUE(resized_array);
}
MAYBE(intmax_t_array) convert_to_numbers(char *line) {
ENABLE_RETURN(intmax_t_array);
ENABLE_TRY();
TRY_TYPE(intmax_t);
TRY_TYPE(intmax_t_array);
struct intmax_t_array numbers = TRY(intmax_t_array, create_array());
FREE_ON_TRY_FAIL(numbers.data);
char *strtok_saveptr = NULL;
for (;;) {
char *num_str;
if (strtok_saveptr == NULL) {
num_str = strtok_r(line, " ", &strtok_saveptr);
} else {
num_str = strtok_r(NULL, " ", &strtok_saveptr);
}
if (num_str == NULL) {
break;
}
intmax_t num = TRY(intmax_t, str2int(num_str));
size_t index = numbers.length;
void *old_ptr = numbers.data;
numbers = TRY(intmax_t_array, resize_array(numbers, numbers.length + 1));
TRY_HOF_REPLACE(old_ptr, numbers.data);
numbers.data[index] = num;
}
RETURN_VALUE(numbers);
}
int main(void) {
size_t line_size = 0;
char *line = NULL;
ssize_t line_len;
while ((line_len = getline(&line, &line_size, stdin)) > 0) {
MAYBE(voidptr) newline = strchr_maybe(line, '\n');
IS_VALUE(newline) {
*(char*)VALUE(newline) = '\0';
}
MAYBE(intmax_t_array) numbers = convert_to_numbers(line);
IS_VALUE(numbers) {
for (size_t i = 0; i < VALUE(numbers).length; i++) {
printf("%jd ", VALUE(numbers).data[i]);
}
printf("\n");
} else {
printf("Error in conversion\n");
}
}
return 0;
}