]> mj.ucw.cz Git - libucw.git/blob - lib/ff-string.c
45fefb37f740dece0b0805b5334411f3a8dbf341
[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   byte *e = b + l - 1;
19   int k;
20
21   k = bgetc(f);
22   if (k < 0)
23     return NULL;
24   while (b < e)
25     {
26       if (k == '\n' || k < 0)
27         {
28           *b = 0;
29           return b;
30         }
31       *b++ = k;
32       k = bgetc(f);
33     }
34   die("%s: Line too long", f->name);
35 }
36
37 int
38 bgets_nodie(struct fastbuf *f, byte *b, uns l)
39 {
40   byte *start = b;
41   byte *e = b + l - 1;
42   int k;
43
44   k = bgetc(f);
45   if (k < 0)
46     return 0;
47   while (b < e)
48     {
49       if (k == '\n' || k < 0)
50         {
51           *b++ = 0;
52           return b - start;
53         }
54       *b++ = k;
55       k = bgetc(f);
56     }
57   return -1;
58 }
59
60 uns
61 bgets_bb(struct fastbuf *f, bb_t *bb)
62 {
63   byte *buf = bb->ptr, *src;
64   uns len = 0, buf_len = bb->len, src_len = bdirect_read_prepare(f, &src);
65   while (src_len)
66     {
67       uns cnt = MIN(src_len, buf_len);
68       for (uns i = cnt; i--;)
69         {
70           if (*src == '\n')
71             {
72               *buf = 0;
73               return buf - bb->ptr;
74             }
75           *buf++ = *src++;
76         }
77       len += cnt;
78       if (cnt == src_len)
79         src_len = bdirect_read_prepare(f, &src);
80       else
81         src_len -= cnt;
82       if (cnt == buf_len)
83         {
84           bb_do_grow(bb, len + 1);
85           buf = bb->ptr + len;
86           buf_len = bb->len - len;
87         }
88       else
89         buf_len -= cnt;
90     }
91   *buf = 0;
92   return len;
93 }
94
95 byte *
96 bgets_mp(struct mempool *mp, struct fastbuf *f)
97 {
98 #define BLOCK_SIZE 4096
99   struct block {
100     struct block *prev;
101     byte data[BLOCK_SIZE];
102   } *blocks = NULL;
103   uns sum = 0;
104   for (;;)
105     {
106       struct block *new_block = alloca(sizeof(struct block));
107       byte *b = new_block->data, *e = b + BLOCK_SIZE;
108       while (b < e)
109         {
110           int k = bgetc(f);
111           if (k == '\n' || k < 0)
112             {
113               uns len = b - new_block->data;
114               byte *result = mp_alloc(mp, sum + len + 1) + sum;
115               result[len] = 0;
116               memcpy(result, new_block->data, len);
117               while (blocks)
118                 {
119                   result -= BLOCK_SIZE;
120                   memcpy(result, blocks->data, BLOCK_SIZE);
121                   blocks = blocks->prev;
122                 }
123               return result;
124             }
125           *b++ = k;
126         }
127       new_block->prev = blocks;
128       blocks = new_block;
129       sum += BLOCK_SIZE;
130     }
131 #undef BLOCK_SIZE
132 }
133
134 int
135 bgets_stk_step(struct fastbuf *f, byte *old_buf, byte *buf, uns len)
136 {
137   if (old_buf)
138     {
139       len = len >> 1;
140       memcpy(buf, old_buf, len);
141       buf += len;
142     }
143   while (len--)
144     {
145       int k = bgetc(f);
146       if (k == '\n' || k < 0)
147         return *buf = 0;
148       *buf++ = k;
149     }
150   return 1;
151 }
152
153 byte *
154 bgets0(struct fastbuf *f, byte *b, uns l)
155 {
156   byte *e = b + l - 1;
157   int k;
158
159   k = bgetc(f);
160   if (k < 0)
161     return NULL;
162   while (b < e)
163     {
164       if (k <= 0)
165         {
166           *b = 0;
167           return b;
168         }
169       *b++ = k;
170       k = bgetc(f);
171     }
172   die("%s: Line too long", f->name);
173 }