]> mj.ucw.cz Git - libucw.git/blob - ucw/ff-string.c
Build: Added link path to libraries installed to non-standard path.
[libucw.git] / ucw / 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 <ucw/lib.h>
12 #include <ucw/fastbuf.h>
13 #include <ucw/mempool.h>
14 #include <ucw/bbuf.h>
15
16 char *                                  /* Non-standard */
17 bgets(struct fastbuf *f, char *b, uns l)
18 {
19   ASSERT(l);
20   byte *src;
21   uns src_len = bdirect_read_prepare(f, &src);
22   if (!src_len)
23     return NULL;
24   do
25     {
26       uns cnt = MIN(l, src_len);
27       for (uns i = cnt; i--;)
28         {
29           byte v = *src++;
30           if (v == '\n')
31             {
32               bdirect_read_commit(f, src);
33               goto exit;
34             }
35           *b++ = v;
36         }
37       if (unlikely(cnt == l))
38         bthrow(f, "toolong", "%s: Line too long", f->name);
39       l -= cnt;
40       bdirect_read_commit(f, src);
41       src_len = bdirect_read_prepare(f, &src);
42     }
43   while (src_len);
44 exit:
45   *b = 0;
46   return b;
47 }
48
49 int
50 bgets_nodie(struct fastbuf *f, char *b, uns l)
51 {
52   ASSERT(l);
53   byte *src, *start = b;
54   uns src_len = bdirect_read_prepare(f, &src);
55   if (!src_len)
56     return 0;
57   do
58     {
59       uns cnt = MIN(l, src_len);
60       for (uns i = cnt; i--;)
61         {
62           byte v = *src++;
63           if (v == '\n')
64             {
65               bdirect_read_commit(f, src);
66               goto exit;
67             }
68           *b++ = v;
69         }
70       bdirect_read_commit(f, src);
71       if (cnt == l)
72         return -1;
73       l -= cnt;
74       src_len = bdirect_read_prepare(f, &src);
75     }
76   while (src_len);
77 exit:
78   *b++ = 0;
79   return b - (char *)start;
80 }
81
82 uns
83 bgets_bb(struct fastbuf *f, struct bb_t *bb, uns limit)
84 {
85   ASSERT(limit);
86   byte *src;
87   uns src_len = bdirect_read_prepare(f, &src);
88   if (!src_len)
89     return 0;
90   bb_grow(bb, 1);
91   byte *buf = bb->ptr;
92   uns len = 0, buf_len = MIN(bb->len, limit);
93   do
94     {
95       uns cnt = MIN(src_len, buf_len);
96       for (uns i = cnt; i--;)
97         {
98           byte v = *src++;
99           if (v == '\n')
100             {
101               bdirect_read_commit(f, src);
102               goto exit;
103             }
104           *buf++ = v;
105         }
106       len += cnt;
107       if (cnt == src_len)
108         {
109           bdirect_read_commit(f, src);
110           src_len = bdirect_read_prepare(f, &src);
111         }
112       else
113         src_len -= cnt;
114       if (cnt == buf_len)
115         {
116           if (unlikely(len == limit))
117             bthrow(f, "toolong", "%s: Line too long", f->name);
118           bb_do_grow(bb, len + 1);
119           buf = bb->ptr + len;
120           buf_len = MIN(bb->len, limit) - len;
121         }
122       else
123         buf_len -= cnt;
124     }
125   while (src_len);
126 exit:
127   *buf++ = 0;
128   return buf - bb->ptr;
129 }
130
131 char *
132 bgets_mp(struct fastbuf *f, struct mempool *mp)
133 {
134   byte *src;
135   uns src_len = bdirect_read_prepare(f, &src);
136   if (!src_len)
137     return NULL;
138 #define BLOCK_SIZE (4096 - sizeof(void *))
139   struct block {
140     struct block *prev;
141     byte data[BLOCK_SIZE];
142   } *blocks = NULL;
143   uns sum = 0, buf_len = BLOCK_SIZE, cnt;
144   struct block first_block, *new_block = &first_block;
145   byte *buf = new_block->data;
146   do
147     {
148       cnt = MIN(src_len, buf_len);
149       for (uns i = cnt; i--;)
150         {
151           byte v = *src++;
152           if (v == '\n')
153             {
154               bdirect_read_commit(f, src);
155               goto exit;
156             }
157           *buf++ = v;
158         }
159       if (cnt == src_len)
160         {
161           bdirect_read_commit(f, src);
162           src_len = bdirect_read_prepare(f, &src);
163         }
164       else
165         src_len -= cnt;
166       if (cnt == buf_len)
167         {
168           new_block->prev = blocks;
169           blocks = new_block;
170           sum += buf_len = BLOCK_SIZE;
171           new_block = alloca(sizeof(struct block));
172           buf = new_block->data;
173         }
174       else
175         buf_len -= cnt;
176     }
177   while (src_len);
178 exit: ;
179   uns len = buf - new_block->data;
180   byte *result = mp_alloc(mp, sum + len + 1) + sum;
181   result[len] = 0;
182   memcpy(result, new_block->data, len);
183   while (blocks)
184     {
185       result -= BLOCK_SIZE;
186       memcpy(result, blocks->data, BLOCK_SIZE);
187       blocks = blocks->prev;
188     }
189   return result;
190 #undef BLOCK_SIZE
191 }
192
193 char *
194 bgets0(struct fastbuf *f, char *b, uns l)
195 {
196   ASSERT(l);
197   byte *src;
198   uns src_len = bdirect_read_prepare(f, &src);
199   if (!src_len)
200     return NULL;
201   do
202     {
203       uns cnt = MIN(l, src_len);
204       for (uns i = cnt; i--;)
205         {
206           *b = *src++;
207           if (!*b)
208             {
209               bdirect_read_commit(f, src);
210               return b;
211             }
212           b++;
213         }
214       if (unlikely(cnt == l))
215         bthrow(f, "toolong", "%s: Line too long", f->name);
216       l -= cnt;
217       bdirect_read_commit(f, src);
218       src_len = bdirect_read_prepare(f, &src);
219     }
220   while (src_len);
221   *b = 0;
222   return b;
223 }