source: trunk/third/gnome-vfs/libgnomevfs/getdelim.c @ 15497

Revision 15497, 4.0 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15496, which included commits to RCS files with non-trunk default branches.
Line 
1/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3
4   The GNU C Library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Library General Public License as
6   published by the Free Software Foundation; either version 2 of the
7   License, or (at your option) any later version.
8
9   The GNU C Library is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Library General Public License for more details.
13
14   You should have received a copy of the GNU Library General Public
15   License along with the GNU C Library; see the file COPYING.LIB.  If not,
16   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17   Boston, MA 02111-1307, USA.  */
18
19#include <stddef.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <limits.h>
24#include <errno.h>
25
26/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
27   (and null-terminate it). *LINEPTR is a pointer returned from malloc (or
28   NULL), pointing to *N characters of space.  It is realloc'd as
29   necessary.  Returns the number of characters read (not including the
30   null terminator), or -1 on error or EOF.  */
31
32ssize_t
33getdelim (lineptr, n, terminator, stream)
34     char **lineptr;
35     size_t *n;
36     int terminator;
37     FILE *stream;
38{
39  char *line, *p;
40  size_t size, copy;
41
42  if (!__validfp (stream) || lineptr == NULL || n == NULL)
43    {
44      __set_errno (EINVAL);
45      return -1;
46    }
47
48  if (ferror (stream))
49    return -1;
50
51  /* Make sure we have a line buffer to start with.  */
52  if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars.  */
53    {
54#ifndef MAX_CANON
55#define MAX_CANON       256
56#endif
57      line = realloc (*lineptr, MAX_CANON);
58      if (line == NULL)
59        return -1;
60      *lineptr = line;
61      *n = MAX_CANON;
62    }
63
64  line = *lineptr;
65  size = *n;
66
67  copy = size;
68  p = line;
69
70  if (stream->__buffer == NULL && stream->__userbuf)
71    {
72      /* Unbuffered stream.  Not much optimization to do.  */
73
74      while (1)
75        {
76          size_t len;
77
78          while (--copy > 0)
79            {
80              register int c = getc (stream);
81              if (c == EOF)
82                goto lose;
83              else if ((*p++ = c) == terminator)
84                goto win;
85            }
86
87          /* Need to enlarge the line buffer.  */
88          len = p - line;
89          size *= 2;
90          line = realloc (line, size);
91          if (line == NULL)
92            goto lose;
93          *lineptr = line;
94          *n = size;
95          p = line + len;
96          copy = size - len;
97        }
98    }
99  else
100    {
101      /* Leave space for the terminating null.  */
102      --copy;
103
104      if (!stream->__seen || stream->__buffer == NULL || stream->__pushed_back)
105        {
106          /* Do one with getc to allocate a buffer.  */
107          int c = getc (stream);
108          if (c == EOF)
109            goto lose;
110          *p++ = c;
111          if (c == terminator)
112            goto win;
113          --copy;
114        }
115
116      while (1)
117        {
118          size_t i;
119          char *found;
120
121          i = stream->__get_limit - stream->__bufp;
122          if (i == 0)
123            {
124              /* Refill the buffer.  */
125              int c = __fillbf (stream);
126              if (c == EOF)
127                goto lose;
128              *p++ = c;
129              if (c == terminator)
130                goto win;
131              --copy;
132              i = stream->__get_limit - stream->__bufp;
133            }
134
135          if (i > copy)
136            i = copy;
137
138          found = (char *) __memccpy ((void *) p, stream->__bufp,
139                                      terminator, i);
140          if (found != NULL)
141            {
142              stream->__bufp += found - p;
143              p = found;
144              goto win;
145            }
146
147          stream->__bufp += i;
148          p += i;
149          copy -= i;
150          if (copy == 0)
151            {
152              /* Need to enlarge the line buffer.  */
153              size_t len = p - line;
154              size *= 2;
155              line = realloc (line, size);
156              if (line == NULL)
157                goto lose;
158              *lineptr = line;
159              *n = size;
160              p = line + len;
161              copy = size - len;
162              /* Leave space for the terminating null.  */
163              --copy;
164            }
165        }
166    }
167
168 lose:
169  if (p == *lineptr)
170    return -1;
171  /* Return a partial line since we got an error in the middle.  */
172 win:
173  *p = '\0';
174  return p - *lineptr;
175}
176
177weak_alias (__getdelim, getdelim)
Note: See TracBrowser for help on using the repository browser.