Skip to content
Snippets Groups Projects
Commit d3470717 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

make composing and parsing to support ObjectsRefs

parent d7a8b2e6
No related branches found
No related tags found
No related merge requests found
......@@ -32,10 +32,10 @@ class xmlApiInputContext : public std::deque < sax::Token >::iterator {
friend struct xmlApi;
 
std::map < std::string, std::map < int, void * > > idToInstanceContexts;
std::map < std::string, int > idToInstanceMaxContexts;
int idMaxContext;
 
public:
xmlApiInputContext ( std::deque < sax::Token >::iterator iter ) : std::deque < sax::Token >::iterator ( iter ) {
xmlApiInputContext ( std::deque < sax::Token >::iterator iter ) : std::deque < sax::Token >::iterator ( iter ), idMaxContext ( 0 ) {
}
 
~xmlApiInputContext ( ) {
......@@ -51,11 +51,8 @@ public:
return idToInstanceContexts[name];
}
 
int & idToInstanceMax ( const std::string & name ) {
if ( idToInstanceMaxContexts.find ( name ) == idToInstanceMaxContexts.end ( ) )
idToInstanceMaxContexts[name] = 0;
return idToInstanceMaxContexts[name];
int & idMax ( ) {
return idMaxContext;
}
 
static std::map < std::string, std::function < void ( void * ) > > & deleteCallbacks ( ) {
......@@ -64,6 +61,10 @@ public:
return res;
}
 
const std::map < std::string, std::map < int, void * > > & dump ( ) const {
return idToInstanceContexts;
}
};
 
class xmlApiOutputContext : public std::deque < sax::Token > {
......@@ -71,18 +72,18 @@ class xmlApiOutputContext : public std::deque < sax::Token > {
friend struct xmlApi;
 
std::map < std::string, std::map < void *, int > > instanceToIdContexts;
std::map < std::string, int > instanceToIdMaxContexts;
int idMaxContext;
 
public:
xmlApiOutputContext ( ) : idMaxContext ( 0 ) {
}
std::map < void *, int > & instanceToId ( const std::string & name ) {
return instanceToIdContexts[name];
}
 
int & instanceToIdMax ( const std::string & name ) {
if ( instanceToIdMaxContexts.find ( name ) == instanceToIdMaxContexts.end ( ) )
instanceToIdMaxContexts[name] = 0;
return instanceToIdMaxContexts[name];
int & idMax ( ) {
return idMaxContext;
}
 
};
......@@ -127,17 +128,22 @@ public:
 
static Group parse ( std::deque < sax::Token >::iterator & data ) {
xmlApiInputContext & input = ( xmlApiInputContext & ) data;
sax::FromXMLParserHelper::skipAttributes ( input, sax::Token::TokenType::START_ELEMENT );
const std::string & tagName = sax::FromXMLParserHelper::getTokenData ( input, sax::Token::TokenType::START_ELEMENT );
 
if ( /* common::GlobalData::optimizeXml && */ tagName == Group::getXmlTagRefName() ) {
sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, Group::getXmlTagRefName() );
if ( /* common::GlobalData::optimizeXml && */ tagName == "Ref" ) {
sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "Ref" );
sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ATTRIBUTE, "id" );
int id = std::from_string < int > ( sax::FromXMLParserHelper::popTokenData ( input, sax::Token::TokenType::CHARACTER ) );
sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ATTRIBUTE, "id" );
sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, Group::getXmlTagRefName() );
sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "Ref" );
std::map < int, void * >::iterator elem = input.idToInstance ( Group::getXmlTagRefName() ).find ( id );
 
if ( elem == input.idToInstance ( Group::getXmlTagRefName() ).end ( ) ) throw exception::CommonException ( "XML Inconsistent" );
if ( elem == input.idToInstance ( Group::getXmlTagRefName() ).end ( ) ) {
std::cerr << input.dump ( ) << std::endl;
throw exception::CommonException ( "XML Inconsistent ( id not found " + std::to_string ( id ) + " )" );
}
 
return * ( ( Group * ) elem->second );
} else {
......@@ -145,8 +151,20 @@ public:
 
if ( callback == parseFunctions ( ).end ( ) ) throw exception::CommonException ( "Parse callback for " + tagName + " tag not registered." );
 
/* find out if this is a base for reference */
bool ref = sax::FromXMLParserHelper::isToken ( input + 1, sax::Token::TokenType::START_ATTRIBUTE, "ref" );
int id = 0;
if ( ref ) {
std::deque < sax::Token >::iterator tmp = input + 2;
id = std::from_string < int > ( sax::FromXMLParserHelper::popTokenData ( tmp, sax::Token::TokenType::CHARACTER ) );
}
Group * res = new Group ( callback->second->parse ( input ) );
input.idToInstance ( Group::getXmlTagRefName() ).insert ( std::make_pair ( input.idToInstanceMax ( Group::getXmlTagRefName() )++, ( void * ) res ) );
/* if object is a base of reference, register it */
if ( ref )
input.idToInstance ( Group::getXmlTagRefName() ).insert ( std::make_pair ( id, ( void * ) res ) );
return * res;
}
}
......@@ -154,7 +172,7 @@ public:
static bool first ( const std::deque < sax::Token >::const_iterator & input ) {
const std::string & tagName = sax::FromXMLParserHelper::getTokenData ( input, sax::Token::TokenType::START_ELEMENT );
 
if ( tagName == Group::getXmlTagRefName() ) return true;
if ( tagName == "Ref" ) return true;
 
typename std::map < std::string, ParserRegisterBase * >::iterator callback = parseFunctions ( ).find ( tagName );
 
......@@ -169,14 +187,30 @@ public:
typename std::map < void *, int >::iterator elem = context.instanceToId ( Group::getXmlTagRefName() ).find ( const_cast< void * >(static_cast< const void * > ( & data.getData ( ) ) ) );
 
if ( common::GlobalData::optimizeXml && elem != context.instanceToId ( Group::getXmlTagRefName() ).end ( ) ) {
output.emplace_back ( Group::getXmlTagRefName(), sax::Token::TokenType::START_ELEMENT );
output.emplace_back ( "Ref", sax::Token::TokenType::START_ELEMENT );
output.emplace_back ( "id", sax::Token::TokenType::START_ATTRIBUTE );
output.emplace_back ( std::to_string ( elem->second ), sax::Token::TokenType::CHARACTER );
output.emplace_back ( "id", sax::Token::TokenType::END_ATTRIBUTE );
output.emplace_back ( Group::getXmlTagRefName(), sax::Token::TokenType::END_ELEMENT );
output.emplace_back ( "Ref", sax::Token::TokenType::END_ELEMENT );
} else {
/* get current position in token stream */
size_t pos = output.size();
int id = 0;
if ( common::GlobalData::optimizeXml ) {
id = context.idMax ( )++;
}
/* encode referenced object */
data.getData ( ).compose ( output );
context.instanceToId ( Group::getXmlTagRefName() ).insert ( std::make_pair ( const_cast< void * > ( static_cast< const void * > ( & data.getData ( ) ) ), context.instanceToIdMax ( Group::getXmlTagRefName() )++ ) );
/* emplace referenced attribute */
if ( common::GlobalData::optimizeXml ) {
output.emplace ( output.begin ( ) + pos + 1, "ref", sax::Token::TokenType::START_ATTRIBUTE );
output.emplace ( output.begin ( ) + pos + 2, std::to_string ( id ) , sax::Token::TokenType::CHARACTER );
output.emplace ( output.begin ( ) + pos + 3, "ref", sax::Token::TokenType::END_ATTRIBUTE );
context.instanceToId ( Group::getXmlTagRefName() ).insert ( std::make_pair ( const_cast< void * > ( static_cast< const void * > ( & data.getData ( ) ) ), id ) );
}
}
}
 
......
......@@ -12,16 +12,35 @@
 
namespace sax {
 
bool FromXMLParserHelper::isToken(const std::deque<Token>::const_iterator& input, Token::TokenType type, const std::string& data) {
void FromXMLParserHelper::skipAttributes ( std::deque < Token >::const_iterator & input, Token::TokenType type ) {
if ( type == sax::Token::TokenType::START_ELEMENT || type == sax::Token::TokenType::END_ELEMENT || type == sax::Token::TokenType::CHARACTER ) {
while ( input->getType ( ) == sax::Token::TokenType::START_ATTRIBUTE ) {
input += 3; /* skip START, PAYLOAD, END */
}
}
}
void FromXMLParserHelper::skipAttributes ( std::deque < Token >::iterator & input, Token::TokenType type ) {
if ( type == sax::Token::TokenType::START_ELEMENT || type == sax::Token::TokenType::END_ELEMENT || type == sax::Token::TokenType::CHARACTER ) {
while ( input->getType ( ) == sax::Token::TokenType::START_ATTRIBUTE ) {
input += 3; /* skip START, PAYLOAD, END */
}
}
}
bool FromXMLParserHelper::isToken(std::deque<Token>::const_iterator input, Token::TokenType type, const std::string& data) {
skipAttributes ( input, type );
return input->getType() == type && input->getData() == data;
}
 
bool FromXMLParserHelper::isTokenType(const std::deque<Token>::const_iterator& input, Token::TokenType type) {
bool FromXMLParserHelper::isTokenType(std::deque<Token>::const_iterator input, Token::TokenType type) {
skipAttributes ( input, type );
return input->getType() == type;
}
 
void FromXMLParserHelper::popToken(std::deque<Token>::iterator& input, Token::TokenType type, const std::string& data) {
if (isToken(input, type, data)) {
skipAttributes ( input, type );
++input;
} else {
throw ParserException(Token(data, type), *input);
......@@ -30,6 +49,7 @@ void FromXMLParserHelper::popToken(std::deque<Token>::iterator& input, Token::To
 
std::string FromXMLParserHelper::popTokenData(std::deque<Token>::iterator& input, Token::TokenType type) {
if(isTokenType(input, type)) {
skipAttributes ( input, type );
std::string result = std::move(*input).moveData();
++input;
return result;
......@@ -38,8 +58,9 @@ std::string FromXMLParserHelper::popTokenData(std::deque<Token>::iterator& input
}
}
 
std::string FromXMLParserHelper::getTokenData(const std::deque<Token>::const_iterator& input, Token::TokenType type) {
std::string FromXMLParserHelper::getTokenData(std::deque<Token>::const_iterator input, Token::TokenType type) {
if(isTokenType(input, type)) {
skipAttributes ( input, type );
return input->getData();
} else {
throw ParserException(Token("?", type), *input);
......
......@@ -21,15 +21,18 @@ namespace sax {
*/
class FromXMLParserHelper {
public:
static bool isToken(const std::deque<Token>::const_iterator& input, Token::TokenType type, const std::string& data);
static bool isTokenType(const std::deque<Token>::const_iterator& input, Token::TokenType type);
static bool isToken(std::deque<Token>::const_iterator input, Token::TokenType type, const std::string& data);
static bool isTokenType(std::deque<Token>::const_iterator input, Token::TokenType type);
static void popToken(std::deque<Token>::iterator& input, Token::TokenType type, const std::string& data);
static std::string popTokenData(std::deque<Token>::iterator& input, Token::TokenType type);
static std::string getTokenData(const std::deque<Token>::const_iterator& input, Token::TokenType type);
static std::string getTokenData(std::deque<Token>::const_iterator input, Token::TokenType type);
 
static std::deque < std::deque < sax::Token > > parseInput(bool needSingle, /*const*/ TCLAP::MultiArg < std::string >& input);
static std::deque < sax::Token > parseInput(/*const*/ TCLAP::ValueArg < std::string >& input);
 
static void skipAttributes ( std::deque < Token >::const_iterator & input, Token::TokenType type );
static void skipAttributes ( std::deque < Token >::iterator & input, Token::TokenType type );
private:
static std::deque< sax::Token > parseSingle(const std::string& input);
};
......
......@@ -39,6 +39,9 @@ void ContainerTest::testXMLParser ( ) {
 
{
std::string tmp2 = alib::XmlDataFactory::toString ( object );
std::cout << tmp2 << std::endl;
alib::Object object2 = alib::XmlDataFactory::fromString < alib::Object > ( tmp2 );
 
CPPUNIT_ASSERT ( object == object2 );
......@@ -46,7 +49,11 @@ void ContainerTest::testXMLParser ( ) {
std::set < primitive::String > concrete = alib::XmlDataFactory::fromString < std::set < primitive::String > > ( tmp2 );
std::string tmp3 = alib::XmlDataFactory::toString ( concrete );
 
CPPUNIT_ASSERT ( tmp2 == tmp3 );
std::cout << tmp3 << std::endl;
alib::Object object3 = alib::XmlDataFactory::fromString < alib::Object > ( tmp3 );
CPPUNIT_ASSERT ( object == object3 );
}
}
 
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment