00001
00002
00003
00004
00005
00006
00007 #ifndef _MIMETIC_CODEC_CODEC_CHAIN_
00008 #define _MIMETIC_CODEC_CODEC_CHAIN_
00009 #include <iterator>
00010 #include <string>
00011 #include <mimetic/codec/codec_base.h>
00012
00013
00014 namespace mimetic
00015 {
00016
00017 struct null_node;
00018
00019 template<typename C, typename N = null_node>
00020 struct codec_chain;
00021
00022
00023
00024
00025
00026 template<typename Node, typename LastNode>
00027 struct push_back_node
00028 {
00029 typedef
00030 codec_chain<
00031 typename Node::content_type,
00032 typename
00033 push_back_node<
00034 typename Node::next_node_type,
00035 LastNode
00036 >::node_type
00037 > node_type;
00038 };
00039
00040 template<typename LastNode>
00041 struct push_back_node<null_node, LastNode>
00042 {
00043 typedef LastNode node_type;
00044 };
00045
00046
00047
00048
00049
00050 template<typename Node, unsigned int idx>
00051 struct item
00052 {
00053 typedef typename Node::next_node_type next_node_type;
00054 typedef typename item<next_node_type, idx-1>::node_type node_type;
00055 item(const Node& node)
00056 : m_node(node)
00057 {}
00058 const node_type& node() const
00059 {
00060 return item<next_node_type, idx-1>(m_node.m_next).node();
00061 }
00062 const typename node_type::content_type& content() const
00063 {
00064 return node().m_c;
00065 }
00066
00067 private:
00068 const Node& m_node;
00069 };
00070
00071 template<typename Node>
00072 struct item<Node, 0>
00073 {
00074 typedef Node node_type;
00075 item(const Node& node)
00076 :m_node(node)
00077 {}
00078 const node_type& node() const
00079 {
00080 return m_node;
00081 }
00082 const typename node_type::content_type& content() const
00083 {
00084 return m_node.m_c;
00085 }
00086 private:
00087 const Node& m_node;
00088 };
00089
00090
00091
00092
00093
00094
00095 template<typename Node, typename TailNode, unsigned int idx = Node::count-1>
00096 struct build_push_back_node
00097 {
00098 typedef typename item<Node,idx>::node_type nth_node_type;
00099 typedef typename nth_node_type::content_type nth_content_type;
00100 typedef codec_chain<nth_content_type,TailNode>
00101 next_tail_node_type;
00102 typedef typename
00103 build_push_back_node<Node,next_tail_node_type,idx-1>::result_node_type
00104 result_node_type;
00105
00106
00107
00108 build_push_back_node(const Node& initn, const TailNode& tailn)
00109 : m_initn(initn), m_tailn(tailn)
00110 {
00111 }
00112 operator const result_node_type() const
00113 {
00114 return get();
00115 }
00116 const result_node_type get() const
00117 {
00118 const nth_content_type& nth_c=item<Node,idx>(m_initn).content();
00119 next_tail_node_type next_tail(nth_c, m_tailn);
00120 return build_push_back_node<Node,next_tail_node_type,idx-1>(m_initn,next_tail).get();
00121 }
00122 private:
00123 const Node& m_initn;
00124 const TailNode& m_tailn;
00125 };
00126
00127
00128 template<typename Node, typename TailNode>
00129 struct build_push_back_node<Node,TailNode,0>
00130 {
00131 typedef typename item<Node,0>::node_type nth_node_type;
00132 typedef typename nth_node_type::content_type nth_content_type;
00133 typedef codec_chain<nth_content_type, TailNode> next_tail_node_type;
00134 typedef next_tail_node_type result_node_type;
00135
00136 build_push_back_node(const Node& initn, const TailNode& tailn)
00137 : m_initn(initn), m_tailn(tailn)
00138 {
00139 }
00140 operator const result_node_type() const
00141 {
00142 return get();
00143 }
00144 const result_node_type get() const
00145 {
00146 const nth_content_type& nth_c=item<Node,0>(m_initn).content();
00147 next_tail_node_type next_tail(nth_c, m_tailn);
00148 return next_tail;
00149 }
00150 private:
00151 const Node& m_initn;
00152 const TailNode& m_tailn;
00153 };
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 template<typename C, typename N>
00177 struct codec_chain
00178 {
00179 typedef codec_chain<C, N> self_type;
00180 typedef C content_type;
00181 typedef N next_node_type;
00182 enum { count = 1 + next_node_type::count };
00183 codec_chain()
00184 {
00185 setName();
00186 }
00187 codec_chain(const content_type& c)
00188 : m_c(c)
00189 {
00190 setName();
00191 }
00192 codec_chain(const content_type& c, const next_node_type& node)
00193 : m_c(c), m_next(node)
00194 {
00195 setName();
00196 }
00197 codec_chain(const codec_chain& node)
00198 : m_c(node.m_c), m_next(node.m_next)
00199 {
00200 setName();
00201 }
00202 codec_chain(const null_node&)
00203 {
00204 setName();
00205 }
00206 const char* name() const
00207 {
00208 return m_name.c_str();
00209 }
00210 void process(char c)
00211 {
00212 m_c.process(c, m_next);
00213 }
00214 void flush()
00215 {
00216 m_c.flush(m_next);
00217 m_next.flush();
00218 }
00219 template<typename Cn>
00220 const Cn& get_c(int idx) const
00221 {
00222 return get_c(--idx);
00223 }
00224 const content_type& get_c(int idx) const
00225 {
00226 if(idx == 0)
00227 return m_c;
00228 else
00229 return get_c(--idx);
00230 }
00231 template<typename C1>
00232 const C1& operator[](int idx) const
00233 {
00234 if(idx == 0)
00235 return m_c;
00236 else
00237 return m_next[--idx];
00238 }
00239 self_type& operator*()
00240 { return *this; }
00241 self_type& operator=(char c)
00242 {
00243 m_c.process(c, m_next);
00244 return *this;
00245 }
00246 self_type& operator++()
00247 { return *this; }
00248 self_type& operator++(int)
00249 { return *this; }
00250 template<typename TailC>
00251 typename
00252 push_back_node<self_type, codec_chain<TailC> >::node_type
00253 operator|(const TailC& l)
00254 {
00255 typedef codec_chain<TailC> tail_node;
00256 tail_node tail = l;
00257 build_push_back_node<self_type, tail_node> bpbn(*this,tail);
00258 return bpbn.get();
00259 }
00260
00261 content_type m_c;
00262 next_node_type m_next;
00263 std::string m_name;
00264 private:
00265 void setName()
00266 {
00267 m_name = std::string() + m_c.name() + "|" + m_next.name();
00268 }
00269 };
00270
00271
00272 struct null_node
00273 {
00274 enum { idx = 1 };
00275 enum { count = 0 };
00276 struct null_content
00277 {};
00278 typedef null_node self_type;
00279 typedef null_content content_type;
00280 null_node()
00281 {
00282 }
00283 template<typename C1, typename N1>
00284 null_node(const codec_chain<C1, N1>& node)
00285 {
00286 }
00287 const char* name() const
00288 { return "null_node"; }
00289 self_type& operator*()
00290 { return *this; }
00291 self_type& operator=(char c)
00292 { return *this; }
00293 self_type& operator++()
00294 { return *this; }
00295 self_type& operator++(int)
00296 { return *this; }
00297 void flush()
00298 {
00299 }
00300 null_content m_c;
00301 };
00302
00303
00304
00305
00306
00307
00308
00309 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>
00310 struct node_traits
00311 {
00312 };
00313
00314
00315
00316 template<typename A, typename B, typename C, typename D, typename E,typename F>
00317 struct node_traits<A,B,C,D,E,F>
00318 {
00319 typedef codec_chain<A,
00320 codec_chain<B,
00321 codec_chain<C,
00322 codec_chain<D,
00323 codec_chain<E,
00324 codec_chain<F> > > > > > node_type;
00325 };
00326
00327 template<typename A, typename B, typename C, typename D, typename E>
00328 struct node_traits<A,B,C,D,E>
00329 {
00330 typedef codec_chain<A,
00331 codec_chain<B,
00332 codec_chain<C,
00333 codec_chain<D,
00334 codec_chain<E> > > > > node_type;
00335 };
00336
00337 template<typename A, typename B, typename C, typename D>
00338 struct node_traits<A,B,C,D>
00339 {
00340 typedef codec_chain<A,
00341 codec_chain<B,
00342 codec_chain<C,
00343 codec_chain<D> > > > node_type;
00344 };
00345
00346 template<typename A, typename B, typename C>
00347 struct node_traits<A,B,C>
00348 {
00349 typedef codec_chain<A,
00350 codec_chain<B,
00351 codec_chain<C> > > node_type;
00352 };
00353
00354
00355 template<typename A, typename B>
00356 struct node_traits<A,B>
00357 {
00358 typedef codec_chain<A,
00359 codec_chain<B> > node_type;
00360 };
00361
00362 template<typename A>
00363 struct node_traits<A>
00364 {
00365 typedef codec_chain<A> node_type;
00366 };
00367
00368
00369
00370
00371
00372 template<typename A>
00373 struct chainable_codec
00374 {
00375 template<typename B>
00376 typename node_traits<A,B>::node_type
00377 operator|(const B& b)
00378 {
00379 typedef codec_chain<B> node_b;
00380 const A& a = static_cast<A&>(*this);
00381 return typename node_traits<A,B>::node_type(a, node_b(b));
00382 }
00383 };
00384
00385
00386
00387
00388
00389
00390
00391 #if 0
00392 template<class A, class B>
00393 typename node_traits<A,B>::node_type
00394 operator|(const A& a, const B& b)
00395 {
00396
00397 typedef codec_chain<B> node_b;
00398 return typename node_traits<A,B>::node_type(a, node_b(b));
00399 }
00400
00401 template<typename C, typename Node, typename Last>
00402 typename
00403 push_back_node<codec_chain<C, Node>, codec_chain<Last> >::node_type
00404 operator|(const codec_chain<C, Node>& node, const Last& l)
00405 {
00406 typedef codec_chain<C,Node> InitNode;
00407 typedef codec_chain<Last> TailNode;
00408 TailNode tailnode = l;
00409 build_push_back_node<InitNode,TailNode> bpbn(node,tailnode);
00410
00411 return bpbn.get();
00412 }
00413
00414 #endif
00415 }
00416
00417 #endif
00418