1
/***************************************************************************
2
copyright : (C) 2002-2005 by Stefano Barbato
3
email : stefano@codesink.org
5
$Id: codec_chain.h,v 1.12 2005/02/23 10:26:15 tat Exp $
6
***************************************************************************/
8
/***************************************************************************
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. *
15
***************************************************************************/
16
#ifndef _MIMETIC_CODEC_CODEC_CHAIN_
17
#define _MIMETIC_CODEC_CODEC_CHAIN_
20
#include <mimetic/codec/codec_base.h>
28
template<typename C, typename N = null_node>
35
template<typename Node, typename LastNode>
40
typename Node::content_type,
43
typename Node::next_node_type,
49
template<typename LastNode>
50
struct push_back_node<null_node, LastNode>
52
typedef LastNode node_type;
57
* returns item[idx] of the Node passed to the ctor
59
template<typename Node, unsigned int idx>
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)
67
const node_type& node() const
69
return item<next_node_type, idx-1>(m_node.m_next).node();
71
const typename node_type::content_type& content() const
80
template<typename Node>
83
typedef Node node_type;
84
item(const Node& node)
87
const node_type& node() const
91
const typename node_type::content_type& content() const
101
* build push_back_node<Node,TailNode::node_type and
102
* initialize it with values stored in Node
104
template<typename Node, typename TailNode, unsigned int idx = Node::count-1>
105
struct build_push_back_node
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>
112
build_push_back_node<Node,next_tail_node_type,idx-1>::result_node_type
115
result_node_type is equal to push_back_node<Node,TailNode>::node_type
117
build_push_back_node(const Node& initn, const TailNode& tailn)
118
: m_initn(initn), m_tailn(tailn)
121
operator const result_node_type() const
125
const result_node_type get() const
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();
133
const TailNode& m_tailn;
137
template<typename Node, typename TailNode>
138
struct build_push_back_node<Node,TailNode,0>
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;
145
build_push_back_node(const Node& initn, const TailNode& tailn)
146
: m_initn(initn), m_tailn(tailn)
149
operator const result_node_type() const
153
const result_node_type get() const
155
const nth_content_type& nth_c=item<Node,0>(m_initn).content();
156
next_tail_node_type next_tail(nth_c, m_tailn);
161
const TailNode& m_tailn;
164
/// Defines a chain of codecs
166
Chain of codecs. <b>Don't use it directly use | operator instead</b>.
169
// converts test string to upper case, replaces LF chars with
170
// CRLF and encodes it using quoted-printable codec
176
string test("....some text here....");
177
code(test.begin(), test.end(), tuc | l2c | qp, buf);
180
\warning Chainable codecs must derive from chainable_codec<>
185
template<typename C, typename N>
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 };
196
codec_chain(const content_type& c)
201
codec_chain(const content_type& c, const next_node_type& node)
202
: m_c(c), m_next(node)
206
codec_chain(const codec_chain& node)
207
: m_c(node.m_c), m_next(node.m_next)
211
codec_chain(const null_node&)
215
const char* name() const
217
return m_name.c_str();
221
m_c.process(c, m_next);
228
template<typename Cn>
229
const Cn& get_c(int idx) const
233
const content_type& get_c(int idx) const
240
template<typename C1>
241
const C1& operator[](int idx) const
246
return m_next[--idx];
248
self_type& operator*()
250
self_type& operator=(char c)
252
m_c.process(c, m_next);
255
self_type& operator++()
257
self_type& operator++(int)
259
template<typename TailC>
261
push_back_node<self_type, codec_chain<TailC> >::node_type
262
operator|(const TailC& l)
264
typedef codec_chain<TailC> tail_node;
266
build_push_back_node<self_type, tail_node> bpbn(*this,tail);
271
next_node_type m_next;
276
m_name = std::string() + m_c.name() + "|" + m_next.name();
287
typedef null_node self_type;
288
typedef null_content content_type;
292
template<typename C1, typename N1>
293
null_node(const codec_chain<C1, N1>& node)
296
const char* name() const
297
{ return "null_node"; }
298
self_type& operator*()
300
self_type& operator=(char c)
302
self_type& operator++()
304
self_type& operator++(int)
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
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>
323
// class specializations...
325
template<typename A, typename B, typename C, typename D, typename E,typename F>
326
struct node_traits<A,B,C,D,E,F>
328
typedef codec_chain<A,
333
codec_chain<F> > > > > > node_type;
336
template<typename A, typename B, typename C, typename D, typename E>
337
struct node_traits<A,B,C,D,E>
339
typedef codec_chain<A,
343
codec_chain<E> > > > > node_type;
346
template<typename A, typename B, typename C, typename D>
347
struct node_traits<A,B,C,D>
349
typedef codec_chain<A,
352
codec_chain<D> > > > node_type;
355
template<typename A, typename B, typename C>
356
struct node_traits<A,B,C>
358
typedef codec_chain<A,
360
codec_chain<C> > > node_type;
364
template<typename A, typename B>
365
struct node_traits<A,B>
367
typedef codec_chain<A,
368
codec_chain<B> > node_type;
372
struct node_traits<A>
374
typedef codec_chain<A> node_type;
379
* must be the base of all chainable codecs
382
struct chainable_codec
385
typename node_traits<A,B>::node_type
386
operator|(const B& b)
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));
396
* operator|-creates temporary nodes to initialize chain contents
401
template<class A, class B>
402
typename node_traits<A,B>::node_type
403
operator|(const A& a, const B& b)
406
typedef codec_chain<B> node_b;
407
return typename node_traits<A,B>::node_type(a, node_b(b));
410
template<typename C, typename Node, typename Last>
412
push_back_node<codec_chain<C, Node>, codec_chain<Last> >::node_type
413
operator|(const codec_chain<C, Node>& node, const Last& l)
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);
424
} // namespace mimetic