/[debian]/mimetic/branches/upstream/current/mimetic/codec/codec_chain.h
ViewVC logotype

Contents of /mimetic/branches/upstream/current/mimetic/codec/codec_chain.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 128 - (show annotations)
Sat Feb 25 16:49:20 2006 UTC (15 years, 5 months ago) by gregoa
File MIME type: text/plain
File size: 10255 byte(s)
[svn-inject] Installing original source of mimetic
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

  ViewVC Help
Powered by ViewVC 1.1.26