Lely core libraries 2.3.4
stdio.c
Go to the documentation of this file.
1
23#include "libc.h"
24
25#if !LELY_NO_STDIO
26
27#include <lely/libc/stdio.h>
28
29#include <assert.h>
30#include <errno.h>
31#include <stdarg.h>
32#include <stdlib.h>
33
34#if !(_POSIX_C_SOURCE >= 200809L)
35
36#ifndef LELY_LIBC_GETDELIM_SIZE
38#define LELY_LIBC_GETDELIM_SIZE 64
39#endif
40
41ssize_t
42getdelim(char **lineptr, size_t *n, int delim, FILE *stream)
43{
44 if (!lineptr || !n) {
45#ifdef EINVAL
46 errno = EINVAL;
47#endif
48 return -1;
49 }
50 if (!*n)
51 *lineptr = NULL;
52 else if (!*lineptr)
53 *n = 0;
54 size_t size = LELY_LIBC_GETDELIM_SIZE;
55
56 char *cp = *lineptr;
57 for (;;) {
58 // Make sure we have enough space for the next character and the
59 // terminating null byte.
60 if (*n - (cp - *lineptr) < 2) {
61 int errsv = errno;
62 // First try to double the buffer, to minimize the
63 // number of reallocations.
64 while (size < (size_t)(cp - *lineptr + 2))
65 size *= 2;
66 char *tmp = realloc(*lineptr, size);
67 if (!tmp) {
68 errno = errsv;
69 // If doubling the buffer fails, try to allocate
70 // just enough memory for the next character
71 // (including the terminating null byte).
72 size = cp - *lineptr + 2;
73 tmp = realloc(*lineptr, size);
74 if (!tmp)
75 return -1;
76 }
77 cp = tmp + (cp - *lineptr);
78 *lineptr = tmp;
79 *n = size;
80 }
81 int c = fgetc(stream);
82 // On end-of-file, if any characters have been written to the
83 // buffer and no error has occurred, do not return -1. This
84 // allows the caller to retrieve the last (undelimited) record.
85 if (c == EOF && (ferror(stream) || !(cp - *lineptr)))
86 return -1;
87 if (c == EOF || (*cp++ = c) == delim)
88 break;
89 }
90 *cp = '\0';
91
92 return cp - *lineptr;
93}
94
95ssize_t
96getline(char **lineptr, size_t *n, FILE *stream)
97{
98 return getdelim(lineptr, n, '\n', stream);
99}
100
101#endif // !(_POSIX_C_SOURCE >= 200809L)
102
103#if !defined(_GNU_SOURCE)
104
105int
106asprintf(char **strp, const char *fmt, ...)
107{
108 va_list ap;
109 va_start(ap, fmt);
110 int result = vasprintf(strp, fmt, ap);
111 va_end(ap);
112 return result;
113}
114
115int
116vasprintf(char **strp, const char *fmt, va_list ap)
117{
118 assert(strp);
119
120 va_list aq;
121 va_copy(aq, ap);
122 // NOLINTNEXTLINE(clang-analyzer-valist.Uninitialized)
123 int n = vsnprintf(NULL, 0, fmt, aq);
124 va_end(aq);
125 if (n < 0)
126 return n;
127
128 char *s = malloc(n + 1);
129 if (!s)
130 return -1;
131
132 n = vsnprintf(s, n + 1, fmt, ap);
133 if (n < 0) {
134 int errsv = errno;
135 free(s);
136 errno = errsv;
137 return n;
138 }
139
140 *strp = s;
141 return n;
142}
143
144#endif // !_GNU_SOURCE
145
146#endif // !LELY_NO_STDIO
This is the internal header file of the C11 and POSIX compatibility library.
int asprintf(char **strp, const char *fmt,...)
Equivalent to sprintf(), except that it allocates a string large enough to hold the output,...
Definition: stdio.c:106
int vasprintf(char **strp, const char *fmt, va_list ap)
Equivalent to vsprintf(), except that it allocates a string large enough to hold the output,...
Definition: stdio.c:116
This header file is part of the C11 and POSIX compatibility library; it includes <stdio....
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....