aboutsummaryrefslogtreecommitdiff
path: root/src/drain.h
blob: 5ee1dfe29196ba3cd60bcd40e274673910fa6a03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#pragma once
#include <stdio.h>
#include <stdlib.h>

static char *
drain(FILE *fp, size_t *osize)
{
	if (fseek(fp, 0, SEEK_END) < 0) {
		perror("drain:SEEK_END");
		return NULL;
	}
	size_t size = ftell(fp);
	if (fseek(fp, 0, SEEK_SET) < 0) {
		perror("drain:SEEK_SET");
		return NULL;
	}
	char *const s = malloc(size + 1);
	if (s == NULL) {
		perror("drain:malloc");
		return NULL;
	}
	if (fread(s, 1, size, fp) != size) {
		perror("drain:fread");
		free(s);
		return NULL;
	}
	s[size] = '\0';
	if (osize != NULL)
		*osize = size;
	return s;
}

static char *
drain_stdin(size_t *osize)
{
	size_t size = 256;
	char *data = malloc(size);
	if (data == NULL) {
		perror("drain_stdin:malloc");
		return NULL;
	}
	size_t i = 0;
	for (;; i++) {
		if (i >= size) {
			size *= 2;
			char *const hold = data;
			data = realloc(data, size);
			if (data == NULL) {
				perror("drain_stdin:realloc");
				free(hold);
				return NULL;
			}
		}
		int c = getchar();
		if (c == EOF)
			break;
		data[i] = c;
	}
	data[i] = '\0';
	if (osize != NULL)
		*osize = i;
	return data;
}