source: tags/initial/ALEIO/lenstring.c

Last change on this file was 2, checked in by oldcode, 24 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.7 KB
Line 
1/* lenstring.c --- implementation of lenstring functions
2   Jim Blandy <jimb@gnu.ai.mit.edu> --- September 1994 */
3
4#include <stdlib.h>
5#include <stdio.h>
6#include <string.h>
7
8#include "lenstring.h"
9#include "xmalloc.h"
10
11/* The name of the program we're running, for use in error messages.
12   It isn't terribly modular of us to use this, but hey, every program
13   should have a progname variable.  */
14extern char *progname;
15
16/* Most entries are smaller than this, so this value avoids a few
17   calls to realloc.  */
18#define INITIAL_BUF_LEN 4096
19
20
21/* Write STRING to STREAM.
22   Return value same as for stdio's fwrite.  */
23size_t
24write_lenstring (lenstring *string,
25                 FILE *stream)
26{
27  return fwrite (string->text, sizeof (*string->text), string->len, stream);
28}
29
30
31/* Write STRING to STREAM, left-justified in a field of FIELD spaces.
32   If STRING is longer than FIELD, truncate it.  */
33
34void
35display_clipped_lenstring (lenstring *string, int field, FILE *stream)
36{
37  if (string->len >= field)
38    fwrite (string->text, sizeof (*string->text), field, stream);
39  else
40    {
41      write_lenstring (string, stream);
42
43      {
44        int pad = field - string->len;
45   
46        while (pad-- > 0)
47          putc (' ', stream);
48      }
49    }
50}
51
52
53/* Read text from SOURCE until we find DELIMITER, or hit EOF.
54   Set *STRING to the text we read; the delimiting string or EOF is
55   not included in STRING.
56
57   If the text was terminated by EOF, and is empty (i.e. its length is
58   zero), set STRING->text to zero and return EOF.  In this case, the
59   caller should not free STRING->text.
60
61   Otherwise, the text is stored in memory obtained via malloc, and
62   should be freed by the caller.
63
64   If the string was terminated by DELIMITER, return 0.
65   If the string was non-empty and terminated by EOF, return 1.
66   If an error occurred reading the string, print an error message
67   and exit.  */
68int
69read_delimited_lenstring (lenstring *string,
70                          char *delimiter,
71                          FILE *stream)
72{
73  size_t delimiter_len = strlen (delimiter);
74  char delimiter_last_char;
75
76  size_t buf_len = INITIAL_BUF_LEN;
77  char *buf = (char *) xmalloc (buf_len);
78
79  size_t i = 0;
80  int c;
81
82  if (delimiter_len == 0)
83    {
84      /* If there are other reasonable ways to handle this case,
85         perhaps we should just abort here.  */
86      string->len = 0;
87      string->text = buf;
88      return 0;
89    }
90
91  delimiter_last_char = delimiter[delimiter_len - 1];
92
93  while ((c = getc (stream)) != EOF)
94    {
95      /* Do we need to enlarge the buffer?  */
96      if (i >= buf_len-1)
97        {
98          buf_len *= 2;
99          buf = (char *) xrealloc (buf, buf_len);
100        }
101
102      buf[i++] = c;
103     
104      /* Have we read the delimiter?  We check to see if we just
105         stored delim_last_char; this is a quick, false-positive test.
106         Then we check for the whole string; this is a slow but
107         correct test.  */
108      if (c == delimiter_last_char
109          && i >= delimiter_len
110          && ! memcmp (&buf[i - delimiter_len], delimiter, delimiter_len))
111        break;
112    }
113
114  if (ferror (stream))
115    {
116      perror (progname);
117      exit (2);
118    }
119
120  if (c == EOF)
121    {
122      /* Special case, as documented.  */
123      if (i == 0)
124        {
125          free (buf);
126          string->text = 0;
127          string->len = 0;
128          return EOF;
129        }
130      else
131        {
132          string->text = buf;
133          string->len = i;
134          return 1;
135        }
136    }
137  else
138    {
139      string->text = buf;
140      string->len = i - delimiter_len;
141      return 0;
142    }
143}
144
145
146/* Search STRING for an occurrence of SUBSTRING starting not before
147   START, and return its starting position, or -1 if SUBSTRING is not
148   a substring of STRING.  */
149size_t
150search_lenstring (lenstring *string,
151                  const char *substring,
152                  size_t start)
153{
154  /* Based on the memmem implementation in the GNU C library.
155     This implementation's copyright is:
156     
157     Copyright (C) 1991, 1992 Free Software Foundation, Inc.
158     This file is part of the GNU C Library.
159     
160     The GNU C Library is free software; you can redistribute it and/or
161     modify it under the terms of the GNU Library General Public License as
162     published by the Free Software Foundation; either version 2 of the
163     License, or (at your option) any later version.
164     
165     The GNU C Library is distributed in the hope that it will be useful,
166     but WITHOUT ANY WARRANTY; without even the implied warranty of
167     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
168     Library General Public License for more details.
169     
170     You should have received a copy of the GNU Library General Public
171     License along with the GNU C Library; see the file COPYING.LIB.  If
172     not, write to the Free Software Foundation, Inc., 675 Mass Ave,
173     Cambridge, MA 02139, USA.  */
174
175  const void *haystack = string->text + start;
176  const size_t haystack_len = string->len - start;
177  const void *needle = substring;
178  const size_t needle_len = strlen (substring);
179
180  register const char *begin;
181  register const char *last_possible
182    = (const char *) haystack + haystack_len - needle_len;
183
184  if (needle_len == 0)
185    return start;
186
187  for (begin = (const char *) haystack;
188       begin <= last_possible;
189       ++begin)
190    if (!memcmp ((void *) begin, needle, needle_len))
191      return (begin - (const char *) haystack) + start;
192
193  return -1;
194}
195
196
197/* Strip newlines from IN, leaving the result in OUT.
198   OUT points to the same text as IN.  */
199void
200strip_newlines (lenstring *out, lenstring *in)
201{
202  char *p = in->text;
203  char *p_end = in->text + in->len;
204
205  while (p < p_end && *p == '\n')
206    p++;
207
208  out->text = p;
209  out->len  = p_end - p;
210}
211
212
213/* Append STR2 to the end of STR1.  Assume STR1 has sufficient space
214   allocated.  */
215void
216append_lenstring (lenstring *str1, lenstring *str2)
217{
218  memcpy (str1->text + str1->len, str2->text, str2->len);
219  str1->len += str2->len;
220}
Note: See TracBrowser for help on using the repository browser.