Subversion Repositories SvarDOS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
219 mateuszvis 1
/* getdelim.c --- Implementation of replacement getdelim function.
2
   Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free
3
   Software Foundation, Inc.
4
 
5
   This program is free software; you can redistribute it and/or
6
   modify it under the terms of the GNU General Public License as
7
   published by the Free Software Foundation; either version 2, or (at
8
   your option) any later version.
9
 
10
   This program is distributed in the hope that it will be useful, but
11
   WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
   General Public License for more details.
14
 
15
   You should have received a copy of the GNU General Public License
16
   along with this program; if not, write to the Free Software
17
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
   02110-1301, USA.  */
19
 
20
/* Ported from glibc by Simon Josefsson. */
21
 
22
#ifdef HAVE_CONFIG_H
23
# include <config.h>
24
#endif
25
 
26
#include "getdelim.h"
27
 
28
#include <limits.h>
29
#include <stdlib.h>
30
#include <errno.h>
31
 
32
#ifndef SIZE_MAX
33
# define SIZE_MAX ((size_t) -1)
34
#endif
35
#ifndef SSIZE_MAX
36
# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
37
#endif
38
#if !HAVE_FLOCKFILE
39
# undef flockfile
40
# define flockfile(x) ((void) 0)
41
#endif
42
#if !HAVE_FUNLOCKFILE
43
# undef funlockfile
44
# define funlockfile(x) ((void) 0)
45
#endif
46
 
47
/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
48
   NUL-terminate it).  *LINEPTR is a pointer returned from malloc (or
49
   NULL), pointing to *N characters of space.  It is realloc'ed as
50
   necessary.  Returns the number of characters read (not including
51
   the null terminator), or -1 on error or EOF.  */
52
ssize_t getdelim(char **lineptr, size_t *n, int delimiter, FILE *fp) {
53
  ssize_t result;
54
  size_t cur_len = 0;
55
 
56
  if ((lineptr == NULL) || (n == NULL) || (fp == NULL)) {
57
    errno = EINVAL;
58
    return(-1);
59
  }
60
 
61
  flockfile (fp);
62
 
63
  if ((*lineptr == NULL) || (*n == 0)) {
64
    *n = 120;
65
    *lineptr = (char *)malloc(*n);
66
    if (*lineptr == NULL) {
67
      result = -1;
68
      goto unlock_return;
69
    }
70
  }
71
 
72
  for (;;) {
73
    int i;
74
 
75
    i = getc(fp);
76
    if (i == EOF) {
77
      result = -1;
78
      break;
79
    }
80
 
81
    /* Make enough space for len+1 (for final NUL) bytes.  */
82
    if (cur_len + 1 >= *n) {
83
      size_t needed_max = SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
84
      size_t needed = 2 * *n + 1;   /* Be generous. */
85
      char *new_lineptr;
86
 
87
      if (needed_max < needed) needed = needed_max;
88
      if (cur_len + 1 >= needed) {
89
        result = -1;
90
        goto unlock_return;
91
      }
92
 
93
      new_lineptr = (char *) realloc (*lineptr, needed);
94
      if (new_lineptr == NULL) {
95
        result = -1;
96
        goto unlock_return;
97
      }
98
 
99
      *lineptr = new_lineptr;
100
      *n = needed;
101
    }
102
 
103
    (*lineptr)[cur_len] = i;
104
    cur_len++;
105
 
106
    if (i == delimiter) break;
107
  }
108
  (*lineptr)[cur_len] = '\0';
109
 
110
  if (cur_len != 0) result = cur_len;
111
  /* result = cur_len ? cur_len : result; */ /* this one have been replaced by the line above for reading simplicity */
112
 
113
 unlock_return:
114
  funlockfile(fp);
115
  return(result);
116
}