]> mj.ucw.cz Git - libucw.git/blob - charset/fb-charconv.c
252e899466db82d1c46d3ef6e50d754e5ed7ba32
[libucw.git] / charset / fb-charconv.c
1 /*
2  *      Sherlock Library -- Charset Conversion Wrapper for Fast Buffered I/O
3  *
4  *      (c) 2003--2005 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/fastbuf.h>
12 #include <charset/charconv.h>
13 #include <charset/fb-charconv.h>
14
15 #define BUFSIZE 1024
16
17 struct fb_charconv {
18   struct fastbuf fb;
19   struct fastbuf *orig;
20   struct conv_context ctxt;
21   byte buf[BUFSIZE];
22 };
23 #define FB_CC(f) ((struct fb_charconv *)(f))
24
25 static void
26 fb_cc_spout(struct fastbuf *f)
27 {
28   struct conv_context *ct = &FB_CC(f)->ctxt;
29   int flags;
30
31   ct->source = f->buffer;
32   ct->source_end = f->bptr;
33   do
34     {
35       flags = conv_run(ct);
36       if (ct->dest > ct->dest_start)
37         bdirect_write_commit(FB_CC(f)->orig, ct->dest);
38       uns l = bdirect_write_prepare(FB_CC(f)->orig, &ct->dest_start);
39       ct->dest = ct->dest_start;
40       ct->dest_end = ct->dest + l;
41     }
42   while (!(flags & CONV_SOURCE_END));
43
44   f->bptr = f->buffer;
45 }
46
47 static int
48 fb_cc_refill(struct fastbuf *f)
49 {
50   struct conv_context *ct = &FB_CC(f)->ctxt;
51   int flags;
52
53   f->bptr = f->bstop = f->buffer;
54   do
55     {
56       byte *src;
57       uns len = bdirect_read_prepare(FB_CC(f)->orig, &src);
58       if (!len)
59         break;
60       ct->source = src;
61       ct->source_end = ct->source + len;
62       ct->dest = ct->dest_start = f->bstop;
63       ct->dest_end = f->bufend;
64       flags = conv_run(ct);
65       bdirect_read_commit(FB_CC(f)->orig, (byte*)ct->source);
66       f->bstop = ct->dest;
67     }
68   while (!(flags & CONV_DEST_END));
69   return (f->bstop > f->bptr);
70 }
71
72 static void
73 fb_cc_close(struct fastbuf *f)
74 {
75   bflush(FB_CC(f)->orig);
76   xfree(f);
77 }
78
79 struct fastbuf *
80 fb_wrap_charconv_out(struct fastbuf *f, int cs_from, int cs_to)
81 {
82   if (cs_from == cs_to)
83     return f;
84
85   struct fastbuf *g = xmalloc_zero(sizeof(struct fb_charconv));
86   FB_CC(g)->orig = f;
87   conv_init(&FB_CC(g)->ctxt);
88   conv_set_charset(&FB_CC(g)->ctxt, cs_from, cs_to);
89   g->name = "<charconv-out>";
90   g->spout = fb_cc_spout;
91   g->close = fb_cc_close;
92   g->buffer = g->bstop = g->bptr = FB_CC(g)->buf;
93   g->bufend = g->buffer + BUFSIZE;
94   return g;
95 }
96
97 struct fastbuf *
98 fb_wrap_charconv_in(struct fastbuf *f, int cs_from, int cs_to)
99 {
100   if (cs_from == cs_to)
101     return f;
102
103   struct fastbuf *g = xmalloc_zero(sizeof(struct fb_charconv));
104   FB_CC(g)->orig = f;
105   conv_init(&FB_CC(g)->ctxt);
106   conv_set_charset(&FB_CC(g)->ctxt, cs_from, cs_to);
107   g->name = "<charconv-in>";
108   g->refill = fb_cc_refill;
109   g->close = fb_cc_close;
110   g->buffer = g->bstop = g->bptr = FB_CC(g)->buf;
111   g->bufend = g->buffer + BUFSIZE;
112   return g;
113 }