aboutsummaryrefslogtreecommitdiff
path: root/winbuild
diff options
context:
space:
mode:
authordpeter99 <dpeter99@gmail.com>2018-03-26 20:19:17 +0200
committerdpeter99 <dpeter99@gmail.com>2018-03-26 20:19:17 +0200
commitcc194ed3c8a7aa22df4940ef2cc8bbada172a1d0 (patch)
tree65080caeaa94624157d488ad7cfdf4d3ae1821b9 /winbuild
parentb543e202ab776f41d0e3301e43bf3d3bc40f0c84 (diff)
parent52d5f303682fe75925efb9c5f842bd843b75c115 (diff)
downloadlibsurvive-cc194ed3c8a7aa22df4940ef2cc8bbada172a1d0.tar.gz
libsurvive-cc194ed3c8a7aa22df4940ef2cc8bbada172a1d0.tar.bz2
Merge branch 'master' of https://github.com/dpeter99/libsurvive
Diffstat (limited to 'winbuild')
-rw-r--r--winbuild/getdelim.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/winbuild/getdelim.c b/winbuild/getdelim.c
new file mode 100644
index 0000000..ca808ab
--- /dev/null
+++ b/winbuild/getdelim.c
@@ -0,0 +1,149 @@
+/* Implementations of the getdelim() and getline() functions from POSIX 2008,
+ just in case your libc doesn't have them.
+
+ getdelim() reads from a stream until a specified delimiter is encountered.
+ getline() reads from a stream until a newline is encountered.
+
+ See: http://pubs.opengroup.org/onlinepubs/9699919799/functions/getdelim.html
+
+ NOTE: It is always the caller's responsibility to free the line buffer, even
+ when an error occurs.
+
+ Copyright (c) 2011 James E. Ingram
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#if __STDC_VERSION__ >= 199901L
+/* restrict is a keyword */
+#else
+# define restrict
+#endif
+
+
+#ifndef _POSIX_SOURCE
+typedef long ssize_t;
+#define SSIZE_MAX LONG_MAX
+#endif
+
+
+ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delimiter,
+ FILE *restrict stream);
+ssize_t getline(char **restrict lineptr, size_t *restrict n,
+ FILE *restrict stream);
+
+
+
+#define _GETDELIM_GROWBY 128 /* amount to grow line buffer by */
+#define _GETDELIM_MINLEN 4 /* minimum line buffer size */
+
+
+ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delimiter,
+ FILE *restrict stream)
+{
+ char *buf, *pos;
+ int c;
+ ssize_t bytes;
+
+ if (lineptr == NULL || n == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (stream == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /* resize (or allocate) the line buffer if necessary */
+ buf = *lineptr;
+ if (buf == NULL || *n < _GETDELIM_MINLEN) {
+ buf = realloc(*lineptr, _GETDELIM_GROWBY);
+ if (buf == NULL) {
+ /* ENOMEM */
+ return -1;
+ }
+ *n = _GETDELIM_GROWBY;
+ *lineptr = buf;
+ }
+
+ /* read characters until delimiter is found, end of file is reached, or an
+ error occurs. */
+ bytes = 0;
+ pos = buf;
+ while ((c = getc(stream)) != EOF) {
+ if (bytes + 1 >= SSIZE_MAX) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ bytes++;
+ if (bytes >= *n - 1) {
+ buf = realloc(*lineptr, *n + _GETDELIM_GROWBY);
+ if (buf == NULL) {
+ /* ENOMEM */
+ return -1;
+ }
+ *n += _GETDELIM_GROWBY;
+ pos = buf + bytes - 1;
+ *lineptr = buf;
+ }
+
+ *pos++ = (char) c;
+ if (c == delimiter) {
+ break;
+ }
+ }
+
+ if (ferror(stream) || (feof(stream) && (bytes == 0))) {
+ /* EOF, or an error from getc(). */
+ return -1;
+ }
+
+ *pos = '\0';
+ return bytes;
+}
+
+
+ssize_t getline(char **restrict lineptr, size_t *restrict n,
+ FILE *restrict stream)
+{
+ return getdelim(lineptr, n, '\n', stream);
+}
+
+
+#ifdef _TEST_GETDELIM
+
+/* TODO: this isn't a very extensive test. */
+int main(void)
+{
+ char *line = NULL;
+ size_t n = 0;
+ while (getline(&line, &n, stdin) > 0) {
+ printf("%s", line);
+ }
+ return 0;
+}
+
+#endif