Implement TRY
This commit is contained in:
parent
576d5353a8
commit
465f879437
4 changed files with 199 additions and 4 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
average
|
||||
convert_to_ints
|
||||
*.swp
|
||||
|
|
7
Makefile
7
Makefile
|
@ -1,9 +1,12 @@
|
|||
all: average
|
||||
all: average convert_to_ints
|
||||
|
||||
average: average.c cmaybe.h
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $<
|
||||
|
||||
convert_to_ints: convert_to_ints.c cmaybe.h
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f average
|
||||
rm -f average convert_to_ints
|
||||
|
||||
.PHONY: all clean
|
||||
|
|
85
cmaybe.h
85
cmaybe.h
|
@ -15,8 +15,89 @@
|
|||
return __return_value;\
|
||||
}
|
||||
|
||||
#define IS_VALUE(x) if((x).is_value)
|
||||
#define IS_NOT_VALUE(x) if(!(x).is_value)
|
||||
#define IS_VALUE(x) if ((x).is_value)
|
||||
#define IS_NOT_VALUE(x) if (!(x).is_value)
|
||||
#define VALUE(x) (x).value
|
||||
|
||||
struct __free_list {
|
||||
struct __free_list *next;
|
||||
void *ptr;
|
||||
};
|
||||
#define ENABLE_TRY() \
|
||||
struct __free_list *__allocations = NULL, *__free_list_node;\
|
||||
void *__allocation, *__old_allocation;\
|
||||
jmp_buf __try_fail_jmp_buf;\
|
||||
if (setjmp(__try_fail_jmp_buf)) {\
|
||||
TRY_FREE_ALL();\
|
||||
RETURN_NOTHING();\
|
||||
}
|
||||
#define TRY_TYPE(name) MAYBE(name) __try_tmp_##name
|
||||
#define TRY(name, maybe_value) (\
|
||||
__try_tmp_##name = maybe_value,\
|
||||
(__try_tmp_##name.is_value ? 0 :\
|
||||
longjmp(__try_fail_jmp_buf, 1)\
|
||||
),\
|
||||
__try_tmp_##name.value\
|
||||
)
|
||||
|
||||
#define TRY_MEMALLOC(allocator, ...) (\
|
||||
__free_list_node = malloc(sizeof(struct __free_list)),\
|
||||
(__free_list_node == NULL ? longjmp(__try_fail_jmp_buf, 1) : 0),\
|
||||
__allocation = allocator(__VA_ARGS__),\
|
||||
(__allocation == NULL ? (\
|
||||
free(__free_list_node),\
|
||||
longjmp(__try_fail_jmp_buf, 1)\
|
||||
) : (\
|
||||
__free_list_node->next = __allocations,\
|
||||
__free_list_node->ptr = __allocation,\
|
||||
__allocations = __free_list_node\
|
||||
)),\
|
||||
__allocation\
|
||||
)
|
||||
#define TRY_MALLOC(size) TRY_MEMALLOC(malloc, size)
|
||||
|
||||
static void __remove_free_list(struct __free_list **head, void *ptr) {
|
||||
struct __free_list **current = head;
|
||||
while (*current != NULL) {
|
||||
if (current[0]->ptr == ptr) {
|
||||
*current = current[0]->next;
|
||||
break;
|
||||
}
|
||||
current = ¤t[0]->next;
|
||||
}
|
||||
}
|
||||
#define TRY_FREE(allocation) (\
|
||||
free(allocation),\
|
||||
__remove_free_list(&__allocations, allocation)\
|
||||
)
|
||||
#define TRY_FREE_ALL() \
|
||||
while (__allocations != NULL) {\
|
||||
struct __free_list *current = __allocations;\
|
||||
free(current->ptr);\
|
||||
__allocations = current->next;\
|
||||
free(current);\
|
||||
}
|
||||
|
||||
static void __replace_free_list(struct __free_list **head, void *from, void *to) {
|
||||
struct __free_list **current = head;
|
||||
while (*current != NULL) {
|
||||
if (current[0]->ptr == from) {
|
||||
current[0]->ptr = to;
|
||||
break;
|
||||
}
|
||||
current = ¤t[0]->next;
|
||||
}
|
||||
}
|
||||
#define TRY_MEMREALLOC(reallocator, old, ...) (\
|
||||
__old_allocation = old,\
|
||||
__allocation = reallocator(old, __VA_ARGS__),\
|
||||
(__allocation == NULL ? (\
|
||||
longjmp(__try_fail_jmp_buf, 1)\
|
||||
) : \
|
||||
__replace_free_list(&__allocations, __old_allocation, __allocation)\
|
||||
),\
|
||||
__allocation\
|
||||
)
|
||||
#define TRY_REALLOC(old, size) TRY_MEMREALLOC(realloc, old, size)
|
||||
|
||||
#endif
|
||||
|
|
110
convert_to_ints.c
Normal file
110
convert_to_ints.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
#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_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) convert_to_numbers(char *line) {
|
||||
ENABLE_RETURN(intmax_t_array);
|
||||
ENABLE_TRY();
|
||||
TRY_TYPE(intmax_t);
|
||||
|
||||
struct intmax_t_array numbers;
|
||||
numbers.length = 0;
|
||||
numbers.alloc_size = 64 * sizeof(intmax_t);
|
||||
numbers.data = TRY_MALLOC(numbers.alloc_size * sizeof(intmax_t));
|
||||
|
||||
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;
|
||||
numbers.length++;
|
||||
if(numbers.alloc_size / sizeof(intmax_t) < numbers.length) {
|
||||
if(SIZE_MAX / 2 < numbers.alloc_size) {
|
||||
TRY_FREE(numbers.data);
|
||||
RETURN_NOTHING();
|
||||
}
|
||||
numbers.alloc_size *= 2;
|
||||
numbers.data = TRY_REALLOC(numbers.data, numbers.alloc_size);
|
||||
}
|
||||
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;
|
||||
}
|
Loading…
Reference in a new issue