github.com/afumu/libc@v0.0.6/musl/src/stdio/getdelim.c (about)

     1  #include "stdio_impl.h"
     2  #include <string.h>
     3  #include <stdlib.h>
     4  #include <inttypes.h>
     5  #include <errno.h>
     6  
     7  ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restrict f)
     8  {
     9  	char *tmp;
    10  	unsigned char *z;
    11  	size_t k;
    12  	size_t i=0;
    13  	int c;
    14  
    15  	FLOCK(f);
    16  
    17  	if (!n || !s) {
    18  		f->mode |= f->mode-1;
    19  		f->flags |= F_ERR;
    20  		FUNLOCK(f);
    21  		errno = EINVAL;
    22  		return -1;
    23  	}
    24  
    25  	if (!*s) *n=0;
    26  
    27  	for (;;) {
    28  		if (f->rpos != f->rend) {
    29  			z = memchr(f->rpos, delim, f->rend - f->rpos);
    30  			k = z ? z - f->rpos + 1 : f->rend - f->rpos;
    31  		} else {
    32  			z = 0;
    33  			k = 0;
    34  		}
    35  		if (i+k >= *n) {
    36  			size_t m = i+k+2;
    37  			if (!z && m < SIZE_MAX/4) m += m/2;
    38  			tmp = realloc(*s, m);
    39  			if (!tmp) {
    40  				m = i+k+2;
    41  				tmp = realloc(*s, m);
    42  				if (!tmp) {
    43  					/* Copy as much as fits and ensure no
    44  					 * pushback remains in the FILE buf. */
    45  					k = *n-i;
    46  					memcpy(*s+i, f->rpos, k);
    47  					f->rpos += k;
    48  					f->mode |= f->mode-1;
    49  					f->flags |= F_ERR;
    50  					FUNLOCK(f);
    51  					errno = ENOMEM;
    52  					return -1;
    53  				}
    54  			}
    55  			*s = tmp;
    56  			*n = m;
    57  		}
    58  		memcpy(*s+i, f->rpos, k);
    59  		f->rpos += k;
    60  		i += k;
    61  		if (z) break;
    62  		if ((c = getc_unlocked(f)) == EOF) {
    63  			if (!i || !feof(f)) {
    64  				FUNLOCK(f);
    65  				return -1;
    66  			}
    67  			break;
    68  		}
    69  		/* If the byte read by getc won't fit without growing the
    70  		 * output buffer, push it back for next iteration. */
    71  		if (i+1 >= *n) *--f->rpos = c;
    72  		else if (((*s)[i++] = c) == delim) break;
    73  	}
    74  	(*s)[i] = 0;
    75  
    76  	FUNLOCK(f);
    77  
    78  	return i;
    79  }
    80  
    81  weak_alias(getdelim, __getdelim);