Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef IWORKCONTAINERCONTEXT_H_INCLUDED
00011 #define IWORKCONTAINERCONTEXT_H_INCLUDED
00012
00013 #include <cassert>
00014 #include <deque>
00015
00016 #include <boost/optional.hpp>
00017
00018 #include "IWORKTypes_fwd.h"
00019 #include "IWORKRefContext.h"
00020 #include "IWORKXMLContextBase.h"
00021
00022 namespace libetonyek
00023 {
00024
00025 template<typename Type, class NestedParser, template<typename T, class C> class Collector, unsigned Id, unsigned RefId = 0>
00026 class IWORKContainerContext : public IWORKXMLElementContextBase
00027 {
00028 typedef boost::unordered_map<ID_t, Type> Dict_t;
00029
00030 public:
00031 IWORKContainerContext(IWORKXMLParserState &state, std::deque<Type> &elements)
00032 : IWORKXMLElementContextBase(state)
00033 , m_dict(0)
00034 , m_elements(elements)
00035 , m_collector(elements)
00036 {
00037 }
00038
00039 IWORKContainerContext(IWORKXMLParserState &state, Dict_t &dict, std::deque<Type> &elements)
00040 : IWORKXMLElementContextBase(state)
00041 , m_dict(&dict)
00042 , m_elements(elements)
00043 , m_collector(elements)
00044 {
00045 }
00046
00047 protected:
00048 virtual IWORKXMLContextPtr_t element(const int name)
00049 {
00050 if (m_ref && m_dict)
00051 handleRef();
00052 else if (m_collector.pending())
00053 m_collector.push();
00054
00055 if (name == Id)
00056 return m_collector.template makeContext<NestedParser>(getState());
00057 else if ((RefId != 0) && (name == RefId))
00058 return makeContext<IWORKRefContext>(getState(), m_ref);
00059 return IWORKXMLContextPtr_t();
00060 }
00061
00062 virtual void endOfElement()
00063 {
00064 if (m_ref && m_dict)
00065 handleRef();
00066 else if (m_collector.pending())
00067 m_collector.push();
00068 }
00069
00070 private:
00071 void handleRef()
00072 {
00073 assert(m_dict);
00074
00075 const typename Dict_t::const_iterator it = m_dict->find(get(m_ref));
00076 if (it == m_dict->end())
00077 m_elements.push_back(Type());
00078 else
00079 m_elements.push_back(it->second);
00080 }
00081
00082 private:
00083 Dict_t *const m_dict;
00084 boost::optional<ID_t> m_ref;
00085 std::deque<Type> &m_elements;
00086 Collector<Type, std::deque<Type> > m_collector;
00087 };
00088
00089 }
00090
00091 #endif // IWORKCONTAINERCONTEXT_H_INCLUDED
00092
00093