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