66 lines
2.3 KiB
C
66 lines
2.3 KiB
C
#include <stdlib.h> /* EXIT_ strtol */
|
|
#include <stdio.h> /* FILE fopen fclose fread */
|
|
#include <errno.h> /* errno */
|
|
#include <ctype.h> /* isdigit */
|
|
#include <limits.h> /* LONG_ INT_ _MIN _MAX */
|
|
#include <assert.h> /* assert */
|
|
#include "min_array.h"
|
|
|
|
MIN_ARRAY(char, char)
|
|
MIN_ARRAY(num, int)
|
|
|
|
/** Concatenates the contents of `fp` after the file pointer to `string`. The
|
|
file pointer is modified. Zeros are preserved, as well as appending a
|
|
null-terminator. @return Success, otherwise `string` may have read a partial
|
|
read and may not be terminated. @throws[fread, malloc] */
|
|
static int cat_fp_to_str(FILE *const fp, struct char_array *const string) {
|
|
const size_t granularity = 1024;
|
|
size_t nread;
|
|
char *cursor;
|
|
assert(fp && string);
|
|
do {
|
|
if(!(cursor = char_array_buffer(string, granularity))) return 0;
|
|
char_array_emplace(string, nread = fread(cursor, 1, granularity, fp));
|
|
} while(nread == granularity); assert(nread < granularity);
|
|
if(ferror(fp) || !(cursor = char_array_new(string))) return 0;
|
|
*cursor = '\0';
|
|
return 1;
|
|
}
|
|
|
|
int main(void) {
|
|
int success = EXIT_FAILURE;
|
|
struct char_array str = MIN_ARRAY_IDLE;
|
|
struct num_array nums = MIN_ARRAY_IDLE;
|
|
int *num;
|
|
long big_num;
|
|
char *a, *anum = 0;
|
|
size_t i;
|
|
errno = 0; /* In case we are running it as part of another editor. */
|
|
if(!cat_fp_to_str(stdin, &str)) goto catch;
|
|
/*printf("<<<%s>>>\n", str.data);*/
|
|
/* The first sentinel '\0' it stops, even though it could have more data,
|
|
and we could conceivably use the length to continue; it's simple. */
|
|
for(a = str.data; a = strpbrk(a, "-0123456789"); ) {
|
|
if(*a == '-') { anum = a++; continue; }
|
|
if(!(num = num_array_new(&nums))) goto catch;
|
|
if(!anum || anum != a - 1) anum = a; /* Wasn't negative. */
|
|
big_num = strtol(anum, &a, 0);
|
|
if((!big_num || big_num == LONG_MIN || big_num == LONG_MAX) && errno)
|
|
goto catch; /* Long conversion failed. */
|
|
if(big_num < INT_MIN || big_num > INT_MAX)
|
|
{ errno = ERANGE; goto catch; }
|
|
*num = (int)big_num; /* Safe now. */
|
|
}
|
|
for(i = 0; i < nums.size; i++) printf("Extracted %d.\n", nums.data[i]);
|
|
success = EXIT_SUCCESS;
|
|
goto finally;
|
|
catch:
|
|
perror("stdin");
|
|
finally:
|
|
printf("Freeeee!! str %lu, nums %lu\n", str.capacity, nums.capacity);
|
|
char_array_(&str);
|
|
num_array_(&nums);
|
|
printf("yessss.\n");
|
|
return success;
|
|
}
|