]> mj.ucw.cz Git - libucw.git/blob - ucw/ff-string.c
Released as 6.5.13.
[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--2018 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, uint l)
18 {
19   ASSERT(l);
20   byte *src;
21   uint src_len = bdirect_read_prepare(f, &src);
22   if (!src_len)
23     return NULL;
24   do
25     {
26       uint cnt = MIN(l, src_len);
27       for (uint 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, uint l)
51 {
52   ASSERT(l);
53   byte *src, *start = b;
54   uint src_len = bdirect_read_prepare(f, &src);
55   if (!src_len)
56     return 0;
57   do
58     {
59       uint cnt = MIN(l, src_len);
60       for (uint 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 uint
83 bgets_bb(struct fastbuf *f, struct bb_t *bb, uint limit)
84 {
85   ASSERT(limit);
86   byte *src;
87   uint 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   uint len = 0, buf_len = MIN(bb->len, limit);
93   do
94     {
95       uint cnt = MIN(src_len, buf_len);
96       for (uint 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   uint src_len = bdirect_read_prepare(f, &src);
136   if (!src_len)
137     return NULL;
138   byte *buf = mp_start_noalign(mp, 1);
139   size_t buf_len = mp_avail(mp);
140   do
141     {
142       uint cnt = MIN(src_len, buf_len);
143       for (uint i = cnt; i--;)
144         {
145           byte v = *src++;
146           if (v == '\n')
147             {
148               bdirect_read_commit(f, src);
149               goto exit;
150             }
151           *buf++ = v;
152         }
153       if (cnt == src_len)
154         {
155           bdirect_read_commit(f, src);
156           src_len = bdirect_read_prepare(f, &src);
157         }
158       else
159         src_len -= cnt;
160       if (cnt == buf_len)
161         {
162           buf = mp_spread(mp, buf, 1);
163           buf_len = mp_avail(mp) - (buf - (byte *)mp_ptr(mp));
164         }
165       else
166         buf_len -= cnt;
167     }
168   while (src_len);
169 exit:
170   buf = mp_spread(mp, buf, 1);
171   *buf++ = 0;
172   return mp_end(mp, buf);
173 }
174
175 char *
176 bgets0(struct fastbuf *f, char *b, uint l)
177 {
178   ASSERT(l);
179   byte *src;
180   uint src_len = bdirect_read_prepare(f, &src);
181   if (!src_len)
182     return NULL;
183   do
184     {
185       uint cnt = MIN(l, src_len);
186       for (uint i = cnt; i--;)
187         {
188           *b = *src++;
189           if (!*b)
190             {
191               bdirect_read_commit(f, src);
192               return b;
193             }
194           b++;
195         }
196       if (unlikely(cnt == l))
197         bthrow(f, "toolong", "%s: Line too long", f->name);
198       l -= cnt;
199       bdirect_read_commit(f, src);
200       src_len = bdirect_read_prepare(f, &src);
201     }
202   while (src_len);
203   *b = 0;
204   return b;
205 }