~ubuntu-branches/ubuntu/maverick/bc/maverick

« back to all changes in this revision

Viewing changes to dc/string.c

  • Committer: Bazaar Package Importer
  • Author(s): Dirk Eddelbuettel
  • Date: 2002-04-13 11:33:49 UTC
  • Revision ID: james.westby@ubuntu.com-20020413113349-hl2r1t730b91ov68
Tags: upstream-1.06
ImportĀ upstreamĀ versionĀ 1.06

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * implement string functions for dc
 
3
 *
 
4
 * Copyright (C) 1994, 1997, 1998 Free Software Foundation, Inc.
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2, or (at your option)
 
9
 * any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, you can either send email to this
 
18
 * program's author (see below) or write to:
 
19
 *
 
20
 *    The Free Software Foundation, Inc.
 
21
 *    59 Temple Place, Suite 330
 
22
 *    Boston, MA 02111 USA
 
23
 */
 
24
 
 
25
/* This should be the only module that knows the internals of type dc_string */
 
26
 
 
27
#include "config.h"
 
28
 
 
29
#include <stdio.h>
 
30
#ifdef HAVE_STDDEF_H
 
31
# include <stddef.h>    /* ptrdiff_t */
 
32
#else
 
33
# define ptrdiff_t      size_t
 
34
#endif
 
35
#ifdef HAVE_STDLIB_H
 
36
# include <stdlib.h>
 
37
#endif
 
38
#ifdef HAVE_STRING_H
 
39
# include <string.h>    /* memcpy */
 
40
#else
 
41
# ifdef HAVE_MEMORY_H
 
42
#  include <memory.h>   /* memcpy, maybe */
 
43
# else
 
44
#  ifdef HAVE_STRINGS_H
 
45
#   include <strings.h> /* memcpy, maybe */
 
46
#  endif
 
47
# endif
 
48
#endif
 
49
#include "dc.h"
 
50
#include "dc-proto.h"
 
51
 
 
52
/* here is the completion of the dc_string type: */
 
53
struct dc_string {
 
54
        char *s_ptr;  /* pointer to base of string */
 
55
        size_t s_len; /* length of counted string */
 
56
        int  s_refs;  /* reference count to cut down on memory use by duplicates */
 
57
};
 
58
 
 
59
 
 
60
/* return a duplicate of the string in the passed value */
 
61
/* The mismatched data types forces the caller to deal with
 
62
 * bad dc_type'd dc_data values, and makes it more convenient
 
63
 * for the caller to not have to do the grunge work of setting
 
64
 * up a dc_type result.
 
65
 */
 
66
dc_data
 
67
dc_dup_str DC_DECLARG((value))
 
68
        dc_str value DC_DECLEND
 
69
{
 
70
        dc_data result;
 
71
 
 
72
        ++value->s_refs;
 
73
        result.v.string = value;
 
74
        result.dc_type = DC_STRING;
 
75
        return result;
 
76
}
 
77
 
 
78
/* free an instance of a dc_str value */
 
79
void
 
80
dc_free_str DC_DECLARG((value))
 
81
        dc_str *value DC_DECLEND
 
82
{
 
83
        struct dc_string *string = *value;
 
84
 
 
85
        if (--string->s_refs < 1){
 
86
                free(string->s_ptr);
 
87
                free(string);
 
88
        }
 
89
}
 
90
 
 
91
/* Output a dc_str value.
 
92
 * Add a trailing newline if "newline" is set.
 
93
 * Free the value after use if discard_flag is set.
 
94
 */
 
95
void
 
96
dc_out_str DC_DECLARG((value, newline, discard_flag))
 
97
        dc_str value DC_DECLSEP
 
98
        dc_newline newline DC_DECLSEP
 
99
        dc_discard discard_flag DC_DECLEND
 
100
{
 
101
        fwrite(value->s_ptr, value->s_len, sizeof *value->s_ptr, stdout);
 
102
        if (newline == DC_WITHNL)
 
103
                putchar('\n');
 
104
        if (discard_flag == DC_TOSS)
 
105
                dc_free_str(&value);
 
106
}
 
107
 
 
108
/* make a copy of a string (base s, length len)
 
109
 * into a dc_str value; return a dc_data result
 
110
 * with this value
 
111
 */
 
112
dc_data
 
113
dc_makestring DC_DECLARG((s, len))
 
114
        const char *s DC_DECLSEP
 
115
        size_t len DC_DECLEND
 
116
{
 
117
        dc_data result;
 
118
        struct dc_string *string;
 
119
 
 
120
        string = dc_malloc(sizeof *string);
 
121
        string->s_ptr = dc_malloc(len+1);
 
122
        memcpy(string->s_ptr, s, len);
 
123
        string->s_ptr[len] = '\0';      /* nul terminated for those who need it */
 
124
        string->s_len = len;
 
125
        string->s_refs = 1;
 
126
        result.v.string = string;
 
127
        result.dc_type = DC_STRING;
 
128
        return result;
 
129
}
 
130
 
 
131
/* read a dc_str value from FILE *fp;
 
132
 * if ldelim == rdelim, then read until a ldelim char or EOF is reached;
 
133
 * if ldelim != rdelim, then read until a matching rdelim for the
 
134
 * (already eaten) first ldelim is read.
 
135
 * Return a dc_data result with the dc_str value as its contents.
 
136
 */
 
137
dc_data
 
138
dc_readstring DC_DECLARG((fp, ldelim, rdelim))
 
139
        FILE *fp DC_DECLSEP
 
140
        int ldelim DC_DECLSEP
 
141
        int rdelim DC_DECLEND
 
142
{
 
143
        static char *line_buf = NULL;   /* a buffer to build the string in */ 
 
144
        static size_t buflen = 0;               /* the current size of line_buf */
 
145
        int depth=1;
 
146
        int c;
 
147
        char *p;
 
148
        const char *end;
 
149
 
 
150
        if (!line_buf){
 
151
                /* initial buflen should be large enough to handle most cases */
 
152
                buflen = 2016;
 
153
                line_buf = dc_malloc(buflen);
 
154
        }
 
155
        p = line_buf;
 
156
        end = line_buf + buflen;
 
157
        for (;;){
 
158
                c = getc(fp);
 
159
                if (c == EOF)
 
160
                        break;
 
161
                else if (c == rdelim && --depth < 1)
 
162
                        break;
 
163
                else if (c == ldelim)
 
164
                        ++depth;
 
165
                if (p >= end){
 
166
                        ptrdiff_t offset = p - line_buf;
 
167
                        /* buflen increment should be big enough
 
168
                         * to avoid execessive reallocs:
 
169
                         */
 
170
                        buflen += 2048;
 
171
                        line_buf = realloc(line_buf, buflen);
 
172
                        if (!line_buf)
 
173
                                dc_memfail();
 
174
                        p = line_buf + offset;
 
175
                        end = line_buf + buflen;
 
176
                }
 
177
                *p++ = c;
 
178
        }
 
179
        return dc_makestring(line_buf, (size_t)(p-line_buf));
 
180
}
 
181
 
 
182
/* return the base pointer of the dc_str value;
 
183
 * This function is needed because no one else knows what dc_str
 
184
 * looks like.
 
185
 */
 
186
const char *
 
187
dc_str2charp DC_DECLARG((value))
 
188
        dc_str value DC_DECLEND
 
189
{
 
190
        return value->s_ptr;
 
191
}
 
192
 
 
193
/* return the length of the dc_str value;
 
194
 * This function is needed because no one else knows what dc_str
 
195
 * looks like, and strlen(dc_str2charp(value)) won't work
 
196
 * if there's an embedded '\0'.
 
197
 */
 
198
size_t
 
199
dc_strlen DC_DECLARG((value))
 
200
        dc_str value DC_DECLEND
 
201
{
 
202
        return value->s_len;
 
203
}
 
204
 
 
205
 
 
206
/* initialize the strings subsystem */
 
207
void
 
208
dc_string_init DC_DECLVOID()
 
209
{
 
210
        /* nothing to do for this implementation */
 
211
}