~ubuntu-branches/ubuntu/natty/mimetic/natty

« back to all changes in this revision

Viewing changes to mimetic/codec/codec_chain.h

  • Committer: Bazaar Package Importer
  • Author(s): gregor herrmann
  • Date: 2006-06-16 13:16:07 UTC
  • Revision ID: james.westby@ubuntu.com-20060616131607-245mqjypkjuahq6b
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
    copyright            : (C) 2002-2005 by Stefano Barbato
 
3
    email                : stefano@codesink.org
 
4
 
 
5
    $Id: codec_chain.h,v 1.12 2005/02/23 10:26:15 tat Exp $
 
6
 ***************************************************************************/
 
7
 
 
8
/***************************************************************************
 
9
 *                                                                         *
 
10
 *   This program is free software; you can redistribute it and/or modify  *
 
11
 *   it under the terms of the GNU General Public License as published by  *
 
12
 *   the Free Software Foundation; either version 2 of the License, or     *
 
13
 *   (at your option) any later version.                                   *
 
14
 *                                                                         *
 
15
 ***************************************************************************/
 
16
#ifndef _MIMETIC_CODEC_CODEC_CHAIN_
 
17
#define _MIMETIC_CODEC_CODEC_CHAIN_
 
18
#include <iterator>
 
19
#include <string>
 
20
#include <mimetic/codec/codec_base.h>
 
21
 
 
22
 
 
23
namespace mimetic
 
24
{
 
25
 
 
26
struct null_node;
 
27
 
 
28
template<typename C, typename N = null_node>
 
29
struct codec_chain;
 
30
 
 
31
 
 
32
/*
 
33
 * push_back_node
 
34
 */
 
35
template<typename Node, typename LastNode>
 
36
struct push_back_node
 
37
{
 
38
    typedef    
 
39
     codec_chain<
 
40
         typename Node::content_type,
 
41
        typename
 
42
         push_back_node<
 
43
            typename Node::next_node_type, 
 
44
            LastNode
 
45
            >::node_type
 
46
        > node_type;
 
47
};
 
48
 
 
49
template<typename LastNode>
 
50
struct push_back_node<null_node, LastNode>
 
51
{
 
52
    typedef LastNode node_type;
 
53
};
 
54
 
 
55
 
 
56
/*
 
57
 * returns item[idx] of the Node passed to the ctor
 
58
 */
 
59
template<typename Node, unsigned int idx>
 
60
struct item
 
61
{
 
62
    typedef typename Node::next_node_type next_node_type;
 
63
    typedef typename item<next_node_type, idx-1>::node_type node_type;
 
64
    item(const Node& node)
 
65
    : m_node(node)
 
66
    {}
 
67
    const node_type& node() const
 
68
    {
 
69
        return item<next_node_type, idx-1>(m_node.m_next).node();
 
70
    }
 
71
    const typename node_type::content_type& content() const
 
72
    {
 
73
        return node().m_c;
 
74
    }
 
75
 
 
76
private:
 
77
    const Node& m_node;
 
78
};
 
79
 
 
80
template<typename Node>
 
81
struct item<Node, 0>
 
82
{
 
83
    typedef Node node_type;
 
84
    item(const Node& node)
 
85
    :m_node(node)
 
86
    {}
 
87
    const node_type& node() const
 
88
    {
 
89
        return m_node;
 
90
    }
 
91
    const typename node_type::content_type& content() const
 
92
    {
 
93
        return m_node.m_c;
 
94
    }
 
95
private:
 
96
    const Node& m_node;
 
97
};
 
98
 
 
99
 
 
100
/*
 
101
 * build push_back_node<Node,TailNode::node_type and
 
102
 * initialize it with values stored in Node
 
103
 */
 
104
template<typename Node, typename TailNode, unsigned int idx = Node::count-1>
 
105
struct build_push_back_node
 
106
{
 
107
    typedef typename item<Node,idx>::node_type nth_node_type;
 
108
    typedef typename nth_node_type::content_type nth_content_type;
 
109
    typedef codec_chain<nth_content_type,TailNode>     
 
110
        next_tail_node_type;
 
111
    typedef typename 
 
112
        build_push_back_node<Node,next_tail_node_type,idx-1>::result_node_type
 
113
        result_node_type;
 
114
    /* 
 
115
    result_node_type is equal to push_back_node<Node,TailNode>::node_type
 
116
    */
 
117
    build_push_back_node(const Node& initn, const TailNode& tailn)
 
118
    : m_initn(initn), m_tailn(tailn)
 
119
    {
 
120
    }
 
121
    operator const result_node_type() const
 
122
    {
 
123
        return get();
 
124
    }
 
125
    const result_node_type get() const
 
126
    {
 
127
        const nth_content_type& nth_c=item<Node,idx>(m_initn).content();
 
128
        next_tail_node_type next_tail(nth_c, m_tailn);
 
129
        return build_push_back_node<Node,next_tail_node_type,idx-1>(m_initn,next_tail).get();
 
130
    }
 
131
private:
 
132
    const Node& m_initn;
 
133
    const TailNode& m_tailn;
 
134
};
 
135
 
 
136
 
 
137
template<typename Node, typename TailNode>
 
138
struct build_push_back_node<Node,TailNode,0>
 
139
{
 
140
    typedef typename item<Node,0>::node_type nth_node_type;
 
141
    typedef typename nth_node_type::content_type nth_content_type;
 
142
    typedef codec_chain<nth_content_type, TailNode> next_tail_node_type;
 
143
    typedef next_tail_node_type result_node_type;
 
144
 
 
145
    build_push_back_node(const Node& initn, const TailNode& tailn)
 
146
    : m_initn(initn), m_tailn(tailn)
 
147
    {
 
148
    }
 
149
    operator const result_node_type() const
 
150
    {
 
151
        return get();
 
152
    }
 
153
    const result_node_type get() const
 
154
    {
 
155
        const nth_content_type& nth_c=item<Node,0>(m_initn).content();
 
156
        next_tail_node_type next_tail(nth_c, m_tailn);
 
157
        return next_tail;    
 
158
    }
 
159
private:
 
160
    const Node& m_initn;
 
161
    const TailNode& m_tailn;
 
162
};
 
163
 
 
164
/// Defines a chain of codecs
 
165
/*!
 
166
 Chain of codecs. <b>Don't use it directly use | operator instead</b>.
 
167
 
 
168
 \code
 
169
     // converts test string to upper case, replaces LF chars with
 
170
    // CRLF and encodes it using quoted-printable codec
 
171
    ToUpperCase tuc;
 
172
    Lf2CrLf l2c;
 
173
    QP::Encoder qp; 
 
174
    char buf[MAXLEN]; 
 
175
 
 
176
    string test("....some text here....");
 
177
    code(test.begin(), test.end(), tuc | l2c | qp, buf);
 
178
 \endcode
 
179
 
 
180
 \warning Chainable codecs must derive from chainable_codec<>
 
181
 \sa encode decode
 
182
 */
 
183
 
 
184
 
 
185
template<typename C, typename N>
 
186
struct codec_chain
 
187
{
 
188
    typedef codec_chain<C, N> self_type;
 
189
    typedef C content_type;
 
190
    typedef N next_node_type;
 
191
    enum { count = 1 + next_node_type::count };
 
192
    codec_chain()
 
193
    {
 
194
        setName();
 
195
    }
 
196
    codec_chain(const content_type& c)
 
197
    : m_c(c)
 
198
    {
 
199
        setName();
 
200
    }
 
201
    codec_chain(const content_type& c, const next_node_type& node)
 
202
    : m_c(c), m_next(node)
 
203
    {
 
204
        setName();
 
205
    }
 
206
    codec_chain(const codec_chain& node)
 
207
    : m_c(node.m_c), m_next(node.m_next)
 
208
    {
 
209
        setName();
 
210
    }
 
211
    codec_chain(const null_node&) 
 
212
    {
 
213
        setName();
 
214
    }
 
215
    const char* name() const
 
216
    {
 
217
        return m_name.c_str();
 
218
    }
 
219
    void process(char c)
 
220
    {
 
221
        m_c.process(c, m_next);
 
222
    }
 
223
    void flush()
 
224
    {
 
225
        m_c.flush(m_next);
 
226
        m_next.flush();
 
227
    }
 
228
    template<typename Cn>
 
229
    const Cn& get_c(int idx) const
 
230
    {
 
231
        return get_c(--idx);
 
232
    }
 
233
    const content_type& get_c(int idx) const
 
234
    {
 
235
        if(idx == 0)
 
236
            return m_c;
 
237
        else
 
238
            return get_c(--idx);
 
239
    }
 
240
    template<typename C1>
 
241
    const C1& operator[](int idx) const
 
242
    {
 
243
        if(idx == 0)
 
244
            return m_c;
 
245
        else
 
246
            return m_next[--idx];
 
247
    }
 
248
    self_type& operator*()
 
249
    {    return *this;    }
 
250
    self_type& operator=(char c)
 
251
    {
 
252
        m_c.process(c, m_next);
 
253
        return *this;
 
254
    }
 
255
    self_type& operator++()
 
256
    {    return *this;    }
 
257
    self_type& operator++(int)
 
258
    {    return *this;    }
 
259
    template<typename TailC>
 
260
    typename 
 
261
    push_back_node<self_type, codec_chain<TailC> >::node_type 
 
262
    operator|(const TailC& l)
 
263
    {
 
264
        typedef codec_chain<TailC> tail_node;
 
265
        tail_node tail = l;
 
266
        build_push_back_node<self_type, tail_node> bpbn(*this,tail);
 
267
        return bpbn.get();
 
268
    }
 
269
 //protected:
 
270
    content_type m_c;
 
271
    next_node_type m_next;
 
272
    std::string m_name;
 
273
private:
 
274
    void setName()
 
275
    {
 
276
        m_name = std::string() + m_c.name() + "|" + m_next.name();
 
277
    }
 
278
};
 
279
 
 
280
 
 
281
struct null_node
 
282
{
 
283
    enum { idx = 1 };
 
284
    enum { count = 0 };
 
285
    struct null_content
 
286
    {};
 
287
    typedef null_node self_type;
 
288
    typedef null_content content_type;
 
289
    null_node()
 
290
    {
 
291
    }
 
292
    template<typename C1, typename N1>
 
293
    null_node(const codec_chain<C1, N1>& node)
 
294
    {
 
295
    }
 
296
    const char* name() const
 
297
    {    return "null_node";    }
 
298
    self_type& operator*()
 
299
    {    return *this;    }
 
300
    self_type& operator=(char c)
 
301
    {    return *this;    }
 
302
    self_type& operator++()
 
303
    {    return *this;    }
 
304
    self_type& operator++(int)
 
305
    {    return *this;    }
 
306
    void flush()
 
307
    {
 
308
    }
 
309
    null_content m_c;
 
310
};
 
311
 
 
312
 
 
313
/*
 
314
 * helper classes useful to build codec chains
 
315
 * i.e.  node_traits<Base64,QP>::node_type
 
316
 * i.e.  node_traits<Base64,QP,Lf2CrLf>::node_type
 
317
 */
 
318
template<typename A, typename B=null_node, typename C=null_node, typename D=null_node, typename E=null_node, typename F=null_node, typename G=null_node>
 
319
struct node_traits
 
320
{
 
321
};
 
322
 
 
323
// class specializations...
 
324
 
 
325
template<typename A, typename B, typename C, typename D, typename E,typename F>
 
326
struct node_traits<A,B,C,D,E,F>
 
327
{
 
328
    typedef codec_chain<A,
 
329
        codec_chain<B,
 
330
        codec_chain<C,
 
331
        codec_chain<D,
 
332
        codec_chain<E,
 
333
        codec_chain<F> > > > > > node_type;
 
334
};
 
335
 
 
336
template<typename A, typename B, typename C, typename D, typename E>
 
337
struct node_traits<A,B,C,D,E>
 
338
{
 
339
    typedef codec_chain<A,
 
340
        codec_chain<B,
 
341
        codec_chain<C,
 
342
        codec_chain<D,
 
343
        codec_chain<E> > > > > node_type;
 
344
};
 
345
 
 
346
template<typename A, typename B, typename C, typename D>
 
347
struct node_traits<A,B,C,D>
 
348
{
 
349
    typedef codec_chain<A,
 
350
        codec_chain<B,
 
351
        codec_chain<C,
 
352
        codec_chain<D> > > > node_type;
 
353
};
 
354
 
 
355
template<typename A, typename B, typename C>
 
356
struct node_traits<A,B,C>
 
357
{
 
358
    typedef codec_chain<A,
 
359
        codec_chain<B,
 
360
        codec_chain<C> > > node_type;
 
361
};
 
362
 
 
363
 
 
364
template<typename A, typename B>
 
365
struct node_traits<A,B>
 
366
{
 
367
    typedef codec_chain<A,
 
368
        codec_chain<B> > node_type;
 
369
};
 
370
 
 
371
template<typename A>
 
372
struct node_traits<A>
 
373
{
 
374
    typedef codec_chain<A> node_type;
 
375
};
 
376
 
 
377
 
 
378
/*
 
379
 * must be the base of all chainable codecs
 
380
 */
 
381
template<typename A>
 
382
struct chainable_codec
 
383
{
 
384
    template<typename B>
 
385
    typename node_traits<A,B>::node_type
 
386
    operator|(const B& b)
 
387
    {
 
388
        typedef codec_chain<B> node_b;
 
389
        const A& a = static_cast<A&>(*this);
 
390
        return typename node_traits<A,B>::node_type(a, node_b(b));
 
391
    }
 
392
};
 
393
 
 
394
 
 
395
/*
 
396
 * operator|-creates temporary nodes to initialize chain contents
 
397
 */
 
398
 
 
399
 
 
400
#if 0
 
401
template<class A, class B>
 
402
typename node_traits<A,B>::node_type 
 
403
operator|(const A& a, const B& b)
 
404
{
 
405
 
 
406
    typedef codec_chain<B> node_b;
 
407
    return typename node_traits<A,B>::node_type(a, node_b(b));
 
408
}
 
409
 
 
410
template<typename C, typename Node, typename Last>
 
411
typename 
 
412
push_back_node<codec_chain<C, Node>, codec_chain<Last> >::node_type 
 
413
operator|(const codec_chain<C, Node>& node, const Last& l)
 
414
{
 
415
    typedef codec_chain<C,Node> InitNode;
 
416
    typedef codec_chain<Last> TailNode;
 
417
    TailNode tailnode = l;
 
418
    build_push_back_node<InitNode,TailNode> bpbn(node,tailnode);
 
419
 
 
420
    return bpbn.get();
 
421
}
 
422
 
 
423
#endif
 
424
} // namespace mimetic
 
425
 
 
426
#endif
 
427