mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-01 00:46:20 -05:00
* MDAL 0.5.90 : support for custom Logger and 1D meshes * [FEATURE] [MESH] Support rendering of 1D meshes, see https://github.com/qgis/QGIS-Enhancement-Proposals/issues/164 1D mesh consist of edges (edge is straight line segment with 2 vertices) and the data that is defined on either vertices or edges. Such data can be loaded by MDAL and rendered as mesh layer in QGIS.
214 lines
4.5 KiB
C++
214 lines
4.5 KiB
C++
/*
|
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
|
Copyright (C) 2019 Peter Petrik (zilolv at gmail dot com)
|
|
*/
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <assert.h>
|
|
#include "mdal_xml.hpp"
|
|
#include "mdal.h"
|
|
#include "mdal_utils.hpp"
|
|
#include "mdal_logger.hpp"
|
|
|
|
class XMLString
|
|
{
|
|
private:
|
|
xmlChar *mXmlChar;
|
|
|
|
public:
|
|
XMLString( const std::string &str )
|
|
{
|
|
mXmlChar = xmlCharStrdup( str.c_str() );
|
|
}
|
|
XMLString( xmlChar *str )
|
|
{
|
|
mXmlChar = str;
|
|
}
|
|
|
|
~XMLString()
|
|
{
|
|
if ( mXmlChar )
|
|
xmlFree( mXmlChar );
|
|
}
|
|
|
|
xmlChar *get() {return mXmlChar;}
|
|
};
|
|
|
|
XMLFile::XMLFile() = default;
|
|
|
|
XMLFile::~XMLFile()
|
|
{
|
|
if ( mXmlDoc )
|
|
{
|
|
xmlFreeDoc( mXmlDoc );
|
|
mXmlDoc = nullptr;
|
|
}
|
|
}
|
|
|
|
void XMLFile::error( const std::string &str ) const
|
|
{
|
|
throw MDAL::Error( MDAL_Status::Err_UnknownFormat, str + "(" + mFileName + ")" );
|
|
}
|
|
|
|
void XMLFile::openFile( const std::string &fileName )
|
|
{
|
|
mFileName = fileName;
|
|
mXmlDoc = xmlParseFile( fileName.c_str() );
|
|
if ( mXmlDoc == nullptr )
|
|
{
|
|
error( "XML Document not parsed successfully " + fileName );
|
|
}
|
|
}
|
|
|
|
void XMLFile::checkEqual( const xmlChar *xmlString, const std::string &str, const std::string &err ) const
|
|
{
|
|
assert( xmlString );
|
|
|
|
if ( xmlStrcmp( xmlString, XMLString( str.c_str() ).get() ) != 0 )
|
|
{
|
|
std::string str2 = toString( xmlString );
|
|
error( err );
|
|
}
|
|
}
|
|
|
|
bool XMLFile::checkEqual( const xmlChar *xmlString, const std::string &str ) const
|
|
{
|
|
assert( xmlString );
|
|
return ( xmlStrcmp( xmlString, XMLString( str.c_str() ).get() ) == 0 );
|
|
}
|
|
|
|
xmlNodePtr XMLFile::getCheckRoot( const std::string &name ) const
|
|
{
|
|
xmlNodePtr rootNode = root();
|
|
checkEqual( rootNode->name, name, "Root element is not" + name );
|
|
return rootNode;
|
|
}
|
|
|
|
xmlNodePtr XMLFile::getCheckChild( xmlNodePtr parent, const std::string &name, bool force ) const
|
|
{
|
|
assert( parent );
|
|
xmlNodePtr ret;
|
|
ret = parent->xmlChildrenNode;
|
|
while ( ret != nullptr )
|
|
{
|
|
if ( checkEqual( ret->name, name ) )
|
|
{
|
|
return ret;
|
|
}
|
|
ret = ret->next;
|
|
}
|
|
|
|
if ( force && !ret )
|
|
error( "Element " + toString( parent->name ) + " does not have a child " + name );
|
|
|
|
return ret;
|
|
}
|
|
|
|
xmlNodePtr XMLFile::getCheckSibling( xmlNodePtr parent, const std::string &name, bool force ) const
|
|
{
|
|
assert( parent );
|
|
|
|
xmlNodePtr ret = xmlNextElementSibling( parent );
|
|
while ( ret != nullptr )
|
|
{
|
|
if ( checkEqual( ret->name, name ) )
|
|
{
|
|
return ret;
|
|
}
|
|
ret = xmlNextElementSibling( ret );
|
|
}
|
|
|
|
if ( force && !ret )
|
|
error( "Element " + toString( parent->name ) + " does not have a sibling " + name );
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool XMLFile::checkAttribute( xmlNodePtr parent, const std::string &name, const std::string &expectedVal ) const
|
|
{
|
|
assert( parent );
|
|
|
|
xmlChar *uri = xmlGetProp( parent, XMLString( name.c_str() ).get() );
|
|
if ( !uri )
|
|
return false;
|
|
|
|
bool ret = checkEqual( uri, expectedVal );
|
|
xmlFree( uri );
|
|
|
|
return ret;
|
|
}
|
|
|
|
void XMLFile::checkAttribute( xmlNodePtr parent, const std::string &name, const std::string &expectedVal, const std::string &err ) const
|
|
{
|
|
assert( parent );
|
|
xmlChar *uri = xmlGetProp( parent, XMLString( name.c_str() ).get() );
|
|
if ( !uri )
|
|
error( err );
|
|
|
|
XMLString str( uri );
|
|
checkEqual( uri, expectedVal, err );
|
|
}
|
|
|
|
xmlNodePtr XMLFile::root() const
|
|
{
|
|
assert( mXmlDoc );
|
|
|
|
xmlNodePtr cur = xmlDocGetRootElement( mXmlDoc );
|
|
if ( cur == nullptr )
|
|
error( "XML Document is empty" );
|
|
|
|
return cur;
|
|
}
|
|
|
|
std::string XMLFile::toString( const xmlChar *xmlString ) const
|
|
{
|
|
if ( !xmlString )
|
|
error( "Name of XML element is empty" );
|
|
|
|
// Works only for ASCII strings
|
|
std::string ret( reinterpret_cast<const char *>( xmlString ) );
|
|
return ret;
|
|
}
|
|
|
|
double XMLFile::queryDoubleAttribute( xmlNodePtr elem, std::string name ) const
|
|
{
|
|
std::string valStr = attribute( elem, name );
|
|
double val = MDAL::toDouble( valStr );
|
|
return val;
|
|
}
|
|
|
|
size_t XMLFile::querySizeTAttribute( xmlNodePtr elem, std::string name ) const
|
|
{
|
|
std::string valStr = attribute( elem, name );
|
|
size_t val = MDAL::toSizeT( valStr );
|
|
return val;
|
|
}
|
|
|
|
std::string XMLFile::attribute( xmlNodePtr node, std::string name ) const
|
|
{
|
|
std::string ret;
|
|
assert( node );
|
|
|
|
xmlChar *uri = xmlGetProp( node, XMLString( name ).get() );
|
|
XMLString str( uri );
|
|
if ( !uri )
|
|
{
|
|
error( "Unable to get attribute " + name );
|
|
}
|
|
ret = toString( uri );
|
|
return ret;
|
|
}
|
|
|
|
std::string XMLFile::content( xmlNodePtr node ) const
|
|
{
|
|
assert( node );
|
|
|
|
std::string ret;
|
|
|
|
XMLString content( xmlNodeGetContent( node ) );
|
|
ret = toString( content.get() );
|
|
|
|
return ret;
|
|
}
|