Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
getdelim.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2016-2017 Peter Budai.
4 Copyright (C) 2020 Pascal Obry.
5 Copyright (C) 2022 Martin Baƙinka.
6
7 darktable is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 darktable is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with darktable. If not, see <http://www.gnu.org/licenses/>.
19
20 getdelim.c --- Implementation of replacement getdelim function.
21
22 Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2011 Free Software
23 Foundation, Inc.
24
25 This program is free software; you can redistribute it and/or
26 modify it under the terms of the GNU General Public License as
27 published by the Free Software Foundation; either version 2, or (at
28 your option) any later version.
29
30 This program is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with this program; if not, write to the Free Software
37 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
38*/
39
40#include "common/darktable.h"
41
42/* Ported from glibc by Simon Josefsson. */
43
44#include <config.h>
45
46/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
47 optimizes away the IS_NULL_PTR(lineptr) || IS_NULL_PTR(n) || IS_NULL_PTR(fp) tests below. */
48#define _GL_ARG_NONNULL(params)
49
50#include <stdio.h>
51
52#include <limits.h>
53#include <stdint.h>
54#include <stdlib.h>
55#include <errno.h>
56
57#ifndef SSIZE_MAX
58#define SSIZE_MAX ((ssize_t)(SIZE_MAX / 2))
59#endif
60
61#if USE_UNLOCKED_IO
62#include "unlocked-io.h"
63#define getc_maybe_unlocked(fp) getc(fp)
64#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED
65#undef flockfile
66#undef funlockfile
67#define flockfile(x) ((void)0)
68#define funlockfile(x) ((void)0)
69#define getc_maybe_unlocked(fp) getc(fp)
70#else
71#define getc_maybe_unlocked(fp) getc_unlocked(fp)
72#endif
73
74/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
75 NUL-terminate it). *LINEPTR is a pointer returned from malloc (or
76 NULL), pointing to *N characters of space. It is realloc'ed as
77 necessary. Returns the number of characters read (not including
78 the null terminator), or -1 on error or EOF. */
79
80ssize_t getdelim(char **lineptr, size_t *n, int delimiter, FILE *fp)
81{
82 ssize_t result;
83 size_t cur_len = 0;
84
85 if(IS_NULL_PTR(lineptr) || IS_NULL_PTR(n) || IS_NULL_PTR(fp))
86 {
87 errno = EINVAL;
88 return -1;
89 }
90
91 flockfile(fp);
92
93 if(IS_NULL_PTR(*lineptr) || *n == 0)
94 {
95 char *new_lineptr;
96 *n = 120;
97 new_lineptr = (char *)realloc(*lineptr, *n);
98 if(IS_NULL_PTR(new_lineptr))
99 {
100 result = -1;
101 goto unlock_return;
102 }
103 *lineptr = new_lineptr;
104 }
105
106 for(;;)
107 {
108 int i;
109
111 if(i == EOF)
112 {
113 result = -1;
114 break;
115 }
116
117 /* Make enough space for len+1 (for final NUL) bytes. */
118 if(cur_len + 1 >= *n)
119 {
120 size_t needed_max = SSIZE_MAX < SIZE_MAX ? (size_t)SSIZE_MAX + 1 : SIZE_MAX;
121 size_t needed = 2 * *n + 1; /* Be generous. */
122 char *new_lineptr;
123
124 if(needed_max < needed) needed = needed_max;
125 if(cur_len + 1 >= needed)
126 {
127 result = -1;
128 errno = EOVERFLOW;
129 goto unlock_return;
130 }
131
132 new_lineptr = (char *)realloc(*lineptr, needed);
133 if(IS_NULL_PTR(new_lineptr))
134 {
135 result = -1;
136 goto unlock_return;
137 }
138
139 *lineptr = new_lineptr;
140 *n = needed;
141 }
142
143 (*lineptr)[cur_len] = i;
144 cur_len++;
145
146 if(i == delimiter) break;
147 }
148 (*lineptr)[cur_len] = '\0';
149 result = cur_len ? cur_len : result;
150
151unlock_return:
152 funlockfile(fp); /* doesn't set errno */
153
154 return result;
155}
156
157ssize_t getline(char **lineptr, size_t *n, FILE *stream)
158{
159 return getdelim(lineptr, n, '\n', stream);
160}
161
162// clang-format off
163// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
164// vim: shiftwidth=2 expandtab tabstop=2 cindent
165// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
166// clang-format on
167
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
ssize_t getdelim(char **lineptr, size_t *n, int delimiter, FILE *fp)
Definition getdelim.c:80
#define SSIZE_MAX
Definition getdelim.c:58
#define flockfile(x)
Definition getdelim.c:67
#define getc_maybe_unlocked(fp)
Definition getdelim.c:69
#define funlockfile(x)
Definition getdelim.c:68
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
Definition getdelim.c:157