Lely core libraries  2.2.5
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 
38 ssize_t
39 getdelim(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 
92 ssize_t
93 getline(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)
101 
102 int
103 asprintf(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 
112 int
113 vasprintf(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
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....