]> mj.ucw.cz Git - libucw.git/blob - lib/ff-string.c
removed obsolete segmentation
[libucw.git] / lib / ff-string.c
1 /*
2  *      UCW Library -- Fast Buffered I/O: Strings
3  *
4  *      (c) 1997--2006 Martin Mares <mj@ucw.cz>
5  *      (c) 2006 Pavel Charvat <pchar@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "lib/lib.h"
12 #include "lib/fastbuf.h"
13 #include "lib/mempool.h"
14
15 byte *                                  /* Non-standard */
16 bgets(struct fastbuf *f, byte *b, uns l)
17 {
18   ASSERT(l);
19   byte *src;
20   uns src_len = bdirect_read_prepare(f, &src);
21   if (!src_len)
22     return NULL;
23   do
24     {
25       uns cnt = MIN(l, src_len);
26       for (uns i = cnt; i--;)
27         {
28           byte v = *src++;
29           if (v == '\n')
30             {
31               bdirect_read_commit(f, src);
32               goto exit;
33             }
34           *b++ = v;
35         }
36       if (unlikely(cnt == l))
37         die("%s: Line too long", f->name);
38       l -= cnt;
39       bdirect_read_commit(f, src);
40       src_len = bdirect_read_prepare(f, &src);
41     }
42   while (src_len);
43 exit:
44   *b = 0;
45   return b;
46 }
47
48 int
49 bgets_nodie(struct fastbuf *f, byte *b, uns l)
50 {
51   ASSERT(l);
52   byte *src, *start = b;
53   uns src_len = bdirect_read_prepare(f, &src);
54   if (!src_len)
55     return 0;
56   do
57     {
58       uns cnt = MIN(l, src_len);
59       for (uns i = cnt; i--;)
60         {
61           byte v = *src++;
62           if (v == '\n')
63             {
64               bdirect_read_commit(f, src);
65               goto exit;
66             }
67           *b++ = v;
68         }
69       bdirect_read_commit(f, src);
70       if (cnt == l)
71         return -1;
72       l -= cnt;
73       src_len = bdirect_read_prepare(f, &src);
74     }
75   while (src_len);
76 exit:
77   *b++ = 0;
78   return b - start;
79 }
80
81 uns
82 bgets_bb(struct fastbuf *f, bb_t *bb, uns limit)
83 {
84   ASSERT(limit);
85   byte *src;
86   uns src_len = bdirect_read_prepare(f, &src);
87   if (!src_len)
88     return 0;
89   bb_grow(bb, 1);
90   byte *buf = bb->ptr;
91   uns len = 0, buf_len = MIN(bb->len, limit);
92   do
93     {
94       uns cnt = MIN(src_len, buf_len);
95       for (uns i = cnt; i--;)
96         {
97           byte v = *src++;
98           if (v == '\n')
99             {
100               bdirect_read_commit(f, src);
101               goto exit;
102             }
103           *buf++ = v;
104         }
105       len += cnt;
106       if (cnt == src_len)
107         {
108           bdirect_read_commit(f, src);
109           src_len = bdirect_read_prepare(f, &src);
110         }
111       else
112         src_len -= cnt;
113       if (cnt == buf_len)
114         {
115           if (unlikely(len == limit))
116             die("%s: Line too long", f->name);
117           bb_do_grow(bb, len + 1);
118           buf = bb->ptr + len;
119           buf_len = MIN(bb->len, limit) - len;
120         }
121       else
122         buf_len -= cnt;
123     }
124   while (src_len);
125 exit:
126   *buf++ = 0;
127   return buf - bb->ptr;
128 }
129
130 byte *
131 bgets_mp(struct fastbuf *f, struct mempool *mp)
132 {
133   byte *src;
134   uns src_len = bdirect_read_prepare(f, &src);
135   if (!src_len)
136     return NULL;
137 #define BLOCK_SIZE (4096 - sizeof(void *))
138   struct block {
139     struct block *prev;
140     byte data[BLOCK_SIZE];
141   } *blocks = NULL;
142   uns sum = 0, buf_len = BLOCK_SIZE, cnt;
143   struct block first_block, *new_block = &first_block;
144   byte *buf = new_block->data;
145   do
146     {
147       cnt = MIN(src_len, buf_len);
148       for (uns i = cnt; i--;)
149         {
150           byte v = *src++;
151           if (v == '\n')
152             {
153               bdirect_read_commit(f, src);
154               goto exit;
155             }
156           *buf++ = v;
157         }
158       if (cnt == src_len)
159         {
160           bdirect_read_commit(f, src);
161           src_len = bdirect_read_prepare(f, &src);
162         }
163       else
164         src_len -= cnt;
165       if (cnt == buf_len)
166         {
167           new_block->prev = blocks;
168           blocks = new_block;
169           sum += buf_len = BLOCK_SIZE;
170           new_block = alloca(sizeof(struct block));
171           buf = new_block->data;
172         }
173       else
174         buf_len -= cnt;
175     }
176   while (src_len);
177 exit: ;
178   uns len = buf - new_block->data;
179   byte *result = mp_alloc(mp, sum + len + 1) + sum;
180   result[len] = 0;
181   memcpy(result, new_block->data, len);
182   while (blocks)
183     {
184       result -= BLOCK_SIZE;
185       memcpy(result, blocks->data, BLOCK_SIZE);
186       blocks = blocks->prev;
187     }
188   return result;
189 #undef BLOCK_SIZE
190 }
191
192 void
193 bgets_stk_init(struct bgets_stk_struct *s)
194 {
195   s->src_len = bdirect_read_prepare(s->f, &s->src);
196   if (!s->src_len)
197     {
198       s->cur_buf = NULL;
199       s->cur_len = 0;
200     }
201   else
202     {
203       s->old_buf = NULL;
204       s->cur_len = 256;
205     }
206 }
207
208 void
209 bgets_stk_step(struct bgets_stk_struct *s)
210 {
211   byte *buf = s->cur_buf;
212   uns buf_len = s->cur_len;
213   if (s->old_buf)
214     {
215       memcpy( s->cur_buf, s->old_buf, s->old_len);
216       buf += s->old_len;
217       buf_len -= s->old_len;
218     }
219   do
220     {
221       uns cnt = MIN(s->src_len, buf_len);
222       for (uns i = cnt; i--;)
223         {
224           byte v = *s->src++;
225           if (v == '\n')
226             {
227               bdirect_read_commit(s->f, s->src);
228               goto exit;
229             }
230           *buf++ = v;
231         }
232       if (cnt == s->src_len)
233         {
234           bdirect_read_commit(s->f, s->src);
235           s->src_len = bdirect_read_prepare(s->f, &s->src);
236         }
237       else
238         s->src_len -= cnt;
239       if (cnt == buf_len)
240         {
241           s->old_len = s->cur_len;
242           s->old_buf = s->cur_buf;
243           s->cur_len *= 2;
244           return;
245         }
246       else
247         buf_len -= cnt;
248     }
249   while (s->src_len);
250 exit:
251   *buf = 0;
252   s->cur_len = 0;
253 }
254
255 byte *
256 bgets0(struct fastbuf *f, byte *b, uns l)
257 {
258   ASSERT(l);
259   byte *src;
260   uns src_len = bdirect_read_prepare(f, &src);
261   if (!src_len)
262     return NULL;
263   do
264     {
265       uns cnt = MIN(l, src_len);
266       for (uns i = cnt; i--;)
267         {
268           *b = *src++;
269           if (!*b)
270             {
271               bdirect_read_commit(f, src);
272               return b;
273             }
274           b++;
275         }
276       if (unlikely(cnt == l))
277         die("%s: Line too long", f->name);
278       l -= cnt;
279       bdirect_read_commit(f, src);
280       src_len = bdirect_read_prepare(f, &src);
281     }
282   while (src_len);
283   *b = 0;
284   return b;
285 }