diff --git a/alib2common/src/container/ContainerFeatures.h b/alib2common/src/container/ContainerFeatures.h index 7d25fa118fd21a8f4bff8df4c6c45da304112026..8e5e00f76cbb3f76d2dc2bfbc03cf85902259d0e 100644 --- a/alib2common/src/container/ContainerFeatures.h +++ b/alib2common/src/container/ContainerFeatures.h @@ -34,6 +34,8 @@ template < class ElementType = alib::Object > class ObjectsSet; template < class ElementType = alib::Object > class ObjectsTree; +template < class KeyType = alib::Object, class ValueType = alib::Object > +class ObjectsTrie; template < class ElementType = alib::Object > class ObjectsVector; diff --git a/alib2common/src/container/ObjectsTrie.cpp b/alib2common/src/container/ObjectsTrie.cpp new file mode 100644 index 0000000000000000000000000000000000000000..866e7dec42d95aee4f9dd8a2e789e576d9095ddc --- /dev/null +++ b/alib2common/src/container/ObjectsTrie.cpp @@ -0,0 +1,17 @@ +/* + * ObjectsTrie.cpp + * + * Created on: Apr 1, 2013 + * Author: Jan Travnicek + */ + +#include "ObjectsTrie.h" + +#include "Container.h" + +namespace alib { + +auto objectsTrieParserRegister = xmlApi < container::Container >::ParserRegister < container::ObjectsTrie < > > ( ); +auto objectsTrieParserRegister2 = xmlApi < alib::Object >::ParserRegister < container::ObjectsTrie < > > ( ); + +} /* namespace alib */ diff --git a/alib2common/src/container/ObjectsTrie.h b/alib2common/src/container/ObjectsTrie.h new file mode 100644 index 0000000000000000000000000000000000000000..7d4a33f34e2cd3171a5eace59ae9d6b142fee357 --- /dev/null +++ b/alib2common/src/container/ObjectsTrie.h @@ -0,0 +1,193 @@ +/* + * ObjectsTrie.h + * + * Created on: Apr 1, 2013 + * Author: Jan Travnicek + */ + +#ifndef OBJECTS_TRIE_H_ +#define OBJECTS_TRIE_H_ + +#include <trie> +#include <string> +#include <sstream> + +#include "ContainerBase.h" +#include "ContainerFeatures.h" + +#include <core/xmlApi.hpp> +#include "../object/UniqueObject.h" + +namespace container { + +/** + * Basic container from which are derived all other containers. + * Contains reason why the container occured. + */ +template < class KeyType, class ValueType > +class ObjectsTrie : public std::trie < KeyType, ValueType >, public ContainerBase { +public: + explicit ObjectsTrie ( std::trie < KeyType, ValueType > ); + + virtual ContainerBase * clone ( ) const; + + virtual ContainerBase * plunder ( ) &&; + + virtual int compare ( const ObjectBase & other ) const { + if ( std::type_index ( typeid ( * this ) ) == std::type_index ( typeid ( other ) ) ) return this->compare ( ( decltype ( * this ) )other ); + + return std::type_index ( typeid ( * this ) ) - std::type_index ( typeid ( other ) ); + } + + virtual int compare ( const ObjectsTrie & other ) const; + + virtual void operator >>( std::ostream & os ) const; + + virtual explicit operator std::string ( ) const; + + static const std::string & getXmlTagName ( ) { + static std::string xmlTagName = "Trie"; + + return xmlTagName; + } + + static ObjectsTrie parse ( std::deque < sax::Token >::iterator & input ); + static std::map < KeyType, std::trie < KeyType, ValueType > > parseChildren ( std::deque < sax::Token >::iterator & input ); + static std::trie < KeyType, ValueType > parseRaw ( std::deque < sax::Token >::iterator & input ); + + void compose ( std::deque < sax::Token > & out ) const; + static void composeChildren ( std::deque < sax::Token > & out, const std::map < KeyType, std::trie < KeyType, ValueType > > & children ); + static void compose ( std::deque < sax::Token > & out, const std::trie < KeyType, ValueType > & input ); + + virtual alib::ObjectBase * inc ( ) &&; +}; + +template < class KeyType, class ValueType > +ObjectsTrie < KeyType, ValueType >::ObjectsTrie ( std::trie < KeyType, ValueType > raw ) : std::trie < KeyType, ValueType > ( std::move ( raw ) ) { +} + +template < class KeyType, class ValueType > +ContainerBase * ObjectsTrie < KeyType, ValueType >::clone ( ) const { + return new ObjectsTrie ( * this ); +} + +template < class KeyType, class ValueType > +ContainerBase * ObjectsTrie < KeyType, ValueType >::plunder ( ) && { + return new ObjectsTrie ( std::move ( * this ) ); +} + +template < class KeyType, class ValueType > +int ObjectsTrie < KeyType, ValueType >::compare ( const ObjectsTrie & other ) const { + std::compare < std::trie < KeyType, ValueType > > comp; + + return comp ( static_cast < const std::trie < KeyType, ValueType > & > ( * this ), static_cast < const std::trie < KeyType, ValueType > & > ( other ) ); +} + +template < class KeyType, class ValueType > +void ObjectsTrie < KeyType, ValueType >::operator >>( std::ostream & os ) const { + os << "(ObjectsTrie " << static_cast < const std::trie < KeyType, ValueType > & > ( * this ) << ")"; +} + +template < class KeyType, class ValueType > +ObjectsTrie < KeyType, ValueType >::operator std::string ( ) const { + std::stringstream ss; + ss << * this; + return std::move ( ss ).str ( ); +} + +template < class KeyType, class ValueType > +ObjectsTrie <KeyType, ValueType > ObjectsTrie < KeyType, ValueType >::parse ( std::deque < sax::Token >::iterator & input ) { + return ObjectsTrie < KeyType, ValueType > ( parseRaw ( input ) ); +} + +template < class KeyType, class ValueType > +void ObjectsTrie < KeyType, ValueType >::compose ( std::deque < sax::Token > & out ) const { + compose ( out, * this ); +} + +template < class KeyType, class ValueType > +std::map < KeyType, std::trie < KeyType, ValueType > > ObjectsTrie < KeyType, ValueType >::parseChildren ( std::deque < sax::Token >::iterator & input ) { + std::map < KeyType, std::trie < KeyType, ValueType > > children; + + while ( sax::FromXMLParserHelper::isToken ( input, sax::Token::TokenType::START_ELEMENT, "Child" ) ) { + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "Child" ); + + KeyType key = alib::xmlApi < KeyType >::parse ( input ); + ValueType value = alib::xmlApi < ValueType >::parse ( input ); + std::map < KeyType, std::trie < KeyType, ValueType > > innerChildren = parseChildren ( input ); + + children.insert ( std::make_pair ( std::move ( key ), std::trie < KeyType, ValueType > ( std::move ( value ), std::move ( innerChildren ) ) ) ); + + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "Child" ); + } + + return children; +} + +template < class KeyType, class ValueType > +std::trie < KeyType, ValueType > ObjectsTrie < KeyType, ValueType >::parseRaw ( std::deque < sax::Token >::iterator & input ) { + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, ObjectsTrie < >::getXmlTagName ( ) ); + ValueType value = alib::xmlApi < ValueType >::parse ( input ); + std::map < KeyType, std::trie < KeyType, ValueType > > children = parseChildren ( input ); + + std::trie < KeyType, ValueType > trie ( std::move ( value ), std::move ( children ) ); + + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, ObjectsTrie < >::getXmlTagName ( ) ); + return trie; +} + +template < class KeyType, class ValueType > +void ObjectsTrie < KeyType, ValueType >::composeChildren ( std::deque < sax::Token > & out, const std::map < KeyType, std::trie < KeyType, ValueType > > & children ) { + for ( const std::pair < const KeyType, std::trie < KeyType, ValueType > > & child : children ) { + out.emplace_back ( "Child", sax::Token::TokenType::START_ELEMENT ); + + alib::xmlApi < KeyType >::compose ( out, child.first ); + alib::xmlApi < ValueType >::compose ( out, child.second.getData ( ) ); + composeChildren ( out, child.second.getChildren ( ) ); + + out.emplace_back ( "Child", sax::Token::TokenType::END_ELEMENT ); + } +} + +template < class KeyType, class ValueType > +void ObjectsTrie < KeyType, ValueType >::compose ( std::deque < sax::Token > & out, const std::trie < KeyType, ValueType > & input ) { + out.emplace_back ( ObjectsTrie < >::getXmlTagName ( ), sax::Token::TokenType::START_ELEMENT ); + alib::xmlApi < ValueType >::compose ( out, input.getData ( ) ); + composeChildren ( out, input.getChildren ( ) ); + out.emplace_back ( ObjectsTrie < >::getXmlTagName ( ), sax::Token::TokenType::END_ELEMENT ); +} + +template < class KeyType, class ValueType > +alib::ObjectBase* ObjectsTrie < KeyType, ValueType >::inc() && { + return new alib::UniqueObject(alib::Object(std::move(*this)), primitive::Integer(0)); +} + +} /* namespace container */ + +namespace alib { + +template < typename T, typename R > +struct xmlApi < std::trie < T, R > > { + static std::trie < T, R > parse ( std::deque < sax::Token >::iterator & input ); + static bool first ( const std::deque < sax::Token >::const_iterator & input ); + static void compose ( std::deque < sax::Token > & output, const std::trie < T, R > & data ); +}; + +template < typename T, typename R > +std::trie < T, R > xmlApi < std::trie < T, R > >::parse ( std::deque < sax::Token >::iterator & input ) { + return container::ObjectsTrie < T, R >::parseRaw ( input ); +} + +template < typename T, typename R > +bool xmlApi < std::trie < T, R > >::first ( const std::deque < sax::Token >::const_iterator & input ) { + return sax::FromXMLParserHelper::isToken ( input, sax::Token::TokenType::START_ELEMENT, container::ObjectsTrie < >::getXmlTagName ( ) ); +} + +template < typename T, typename R > +void xmlApi < std::trie < T, R > >::compose ( std::deque < sax::Token > & output, const std::trie < T, R > & input ) { + return container::ObjectsTrie < T, R >::compose ( output, input ); +} + +} /* namespace alib */ + +#endif /* OBJECTS_TRIE_H_ */ diff --git a/alib2common/test-src/container/ContainerTest.cpp b/alib2common/test-src/container/ContainerTest.cpp index 18080680a42886ce418ea97467168cc1b196cc46..deccbb04ec11c3dae9d8dff08f39d8518b7515bd 100644 --- a/alib2common/test-src/container/ContainerTest.cpp +++ b/alib2common/test-src/container/ContainerTest.cpp @@ -8,7 +8,9 @@ #include "container/ObjectsSet.h" #include "container/ObjectsVariant.h" #include "container/ObjectsTree.h" +#include "container/ObjectsTrie.h" #include "primitive/Integer.h" +#include "primitive/Character.h" #include "primitive/String.h" #include "factory/XmlDataFactory.hpp" @@ -105,6 +107,39 @@ void ContainerTest::testTreeParsing ( ) { } } +void ContainerTest::testTrieParsing ( ) { + { + std::trie < char, int > t ( 1 ); + + std::string string = alib::XmlDataFactory::toString ( t ); + std::cout << string << std::endl; + + std::trie < char, int > t2 = alib::XmlDataFactory::fromString < std::trie < char, int > > ( string ); + + CPPUNIT_ASSERT ( t == t2 ); + } + { + std::trie < char, int > t ( 0, std::map < char, std::trie < char, int > > { std::make_pair ( 'a', std::trie < char, int > ( 1 ) ), std::make_pair ( 'b', std::trie < char, int > ( 2 ) ) } ); + + std::string string = alib::XmlDataFactory::toString ( t ); + std::cout << string << std::endl; + + std::trie < char, int > t2 = alib::XmlDataFactory::fromString < std::trie < char, int > > ( string ); + + CPPUNIT_ASSERT ( t == t2 ); + } + { + std::trie < char, int > t ( 0, std::map < char, std::trie < char, int > > { std::make_pair ( 'a', std::trie < char, int > ( 1, std::map < char, std::trie < char, int > > { std::make_pair ( 'a', std::trie < char, int > ( 3 ) ), std::make_pair ( 'b', std::trie < char, int > ( 4 ) ) } ) ), std::make_pair ( 'b', std::trie < char, int > ( 2, std::map < char, std::trie < char, int > > { std::make_pair ( 'a', std::trie < char, int > ( 5 ) ), std::make_pair ( 'b', std::trie < char, int > ( 6 ) ) } ) ) } ); + + std::string string = alib::XmlDataFactory::toString ( t ); + std::cout << string << std::endl; + + std::trie < char, int > t2 = alib::XmlDataFactory::fromString < std::trie < char, int > > ( string ); + + CPPUNIT_ASSERT ( t == t2 ); + } +} + void ContainerTest::testProperties ( ) { CPPUNIT_ASSERT ( std::is_nothrow_move_constructible < container::ObjectsSet < alib::Object > >::value ); } diff --git a/alib2common/test-src/container/ContainerTest.h b/alib2common/test-src/container/ContainerTest.h index b9fb3b9121a2a92722947e059c7d6e7d7772904c..1e2a756cca8b3870c1348b27aa6e76a6314e4b59 100644 --- a/alib2common/test-src/container/ContainerTest.h +++ b/alib2common/test-src/container/ContainerTest.h @@ -8,6 +8,7 @@ class ContainerTest : public CppUnit::TestFixture { CPPUNIT_TEST ( testXMLParser ); CPPUNIT_TEST ( testVariantParsing ); CPPUNIT_TEST ( testTreeParsing ); + CPPUNIT_TEST ( testTrieParsing ); CPPUNIT_TEST ( testProperties ); CPPUNIT_TEST_SUITE_END ( ); @@ -18,6 +19,7 @@ public: void testXMLParser ( ); void testVariantParsing ( ); void testTreeParsing ( ); + void testTrieParsing ( ); void testProperties ( ); };