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