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
37 #define LELY_LIBC_GETDELIM_SIZE 64
39 #endif
40 
41 ssize_t
42 getdelim(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 
95 ssize_t
96 getline(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 
105 int
106 asprintf(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 
115 int
116 vasprintf(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
libc.h
asprintf
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
vasprintf
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
stdio.h
stdlib.h