]> mj.ucw.cz Git - libucw.git/blob - charset/fb-charconv.c
9a36590aeb64f2b1746da03bd8fcd0e63a9220b0
[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 "lib/lib.h"
11 #include "lib/fastbuf.h"
12 #include "charset/charconv.h"
13 #include "charset/fb-charconv.h"
14
15 #include <stdlib.h>
16
17 #define BUFSIZE 1024
18
19 struct fb_charconv {
20   struct fastbuf fb;
21   struct fastbuf *orig;
22   struct conv_context ctxt;
23   byte buf[BUFSIZE];
24 };
25 #define FB_CC(f) ((struct fb_charconv *)(f)->is_fastbuf)
26
27 static void
28 fb_cc_spout(struct fastbuf *f)
29 {
30   struct conv_context *ct = &FB_CC(f)->ctxt;
31   int flags;
32
33   ct->source = f->buffer;
34   ct->source_end = f->bptr;
35   do
36     {
37       flags = conv_run(ct);
38       if (ct->dest > ct->dest_start)
39         bdirect_write_commit(FB_CC(f)->orig, ct->dest);
40       uns l = bdirect_write_prepare(FB_CC(f)->orig, &ct->dest_start);
41       ct->dest = ct->dest_start;
42       ct->dest_end = ct->dest + l;
43     }
44   while (!(flags & CONV_SOURCE_END));
45
46   f->bptr = f->buffer;
47 }
48
49 static int
50 fb_cc_refill(struct fastbuf *f)
51 {
52   struct conv_context *ct = &FB_CC(f)->ctxt;
53   int flags;
54
55   f->bptr = f->bstop = f->buffer;
56   do
57     {
58       byte *src;
59       uns len = bdirect_read_prepare(FB_CC(f)->orig, &src);
60       if (!len)
61         break;
62       ct->source = src;
63       ct->source_end = ct->source + len;
64       ct->dest = ct->dest_start = f->bstop;
65       ct->dest_end = f->bufend;
66       flags = conv_run(ct);
67       bdirect_read_commit(FB_CC(f)->orig, (byte*)ct->source);
68       f->bstop = ct->dest;
69     }
70   while (!(flags & CONV_DEST_END));
71   return (f->bstop > f->bptr);
72 }
73
74 static void
75 fb_cc_close(struct fastbuf *f)
76 {
77   bflush(FB_CC(f)->orig);
78   xfree(f);
79 }
80
81 struct fastbuf *
82 fb_wrap_charconv_out(struct fastbuf *f, int cs_from, int cs_to)
83 {
84   if (cs_from == cs_to)
85     return f;
86
87   struct fastbuf *g = xmalloc_zero(sizeof(struct fb_charconv));
88   FB_CC(g)->orig = f;
89   conv_init(&FB_CC(g)->ctxt);
90   conv_set_charset(&FB_CC(g)->ctxt, cs_from, cs_to);
91   g->name = "<charconv-out>";
92   g->spout = fb_cc_spout;
93   g->close = fb_cc_close;
94   g->buffer = g->bstop = g->bptr = FB_CC(g)->buf;
95   g->bufend = g->buffer + BUFSIZE;
96   return g;
97 }
98
99 struct fastbuf *
100 fb_wrap_charconv_in(struct fastbuf *f, int cs_from, int cs_to)
101 {
102   if (cs_from == cs_to)
103     return f;
104
105   struct fastbuf *g = xmalloc_zero(sizeof(struct fb_charconv));
106   FB_CC(g)->orig = f;
107   conv_init(&FB_CC(g)->ctxt);
108   conv_set_charset(&FB_CC(g)->ctxt, cs_from, cs_to);
109   g->name = "<charconv-in>";
110   g->refill = fb_cc_refill;
111   g->close = fb_cc_close;
112   g->buffer = g->bstop = g->bptr = FB_CC(g)->buf;
113   g->bufend = g->buffer + BUFSIZE;
114   return g;
115 }