diff --git a/.github/workflows/ticcutils.yml b/.github/workflows/ticcutils.yml index 644ff62..f8f871a 100644 --- a/.github/workflows/ticcutils.yml +++ b/.github/workflows/ticcutils.yml @@ -5,7 +5,9 @@ on: schedule: - cron: "0 22 3 * 5" # run test once a month push: - branches: [master] + branches: + - master + - develop paths: - configure.ac - 'src/**' diff --git a/include/ticcutils/CommandLine.h b/include/ticcutils/CommandLine.h index 19929e8..e5bf190 100644 --- a/include/ticcutils/CommandLine.h +++ b/include/ticcutils/CommandLine.h @@ -107,7 +107,7 @@ namespace TiCC { class CL_Options { friend std::ostream& operator<<( std::ostream&, const CL_Options& ); public: - typedef std::vector::const_iterator const_iterator; + using const_iterator = std::vector::const_iterator; CL_Options(); CL_Options( const std::string&, const std::string& ); void allow_args( const std::string& = "", const std::string& = "" ); @@ -126,14 +126,6 @@ namespace TiCC { } void add_short_options( const std::string& s ); void add_long_options( const std::string& s ); - void set_short_options( const std::string& s ){ - // misnomer, kept for backward compatability - add_short_options( s ); - } - void set_long_options( const std::string& s ){ - // misnomer, kept for backward compatability - add_long_options( s ); - } const std::string& prog_name() const { /// return the stored name of the calling program (normally argv[0]) return _prog_name; @@ -334,8 +326,8 @@ namespace TiCC { bool extract_internal( const std::string&, std::string& ); std::vector Opts; std::vector MassOpts; - CL_Options( const CL_Options& ); - CL_Options& operator=( const CL_Options& ); + CL_Options( const CL_Options& ) = delete; + CL_Options& operator=( const CL_Options& ) = delete; std::set valid_chars; std::set valid_chars_par; std::set valid_chars_opt; diff --git a/include/ticcutils/Configuration.h b/include/ticcutils/Configuration.h index 3329b0e..b6ef9f3 100644 --- a/include/ticcutils/Configuration.h +++ b/include/ticcutils/Configuration.h @@ -46,8 +46,8 @@ namespace TiCC { /// There is an implicit \b global section when the section is unnamed. class Configuration { public: - typedef std::map ssMap; - typedef std::map sssMap; + using ssMap = std::map; + using sssMap = std::map; Configuration(); void merge( const Configuration&, bool = false ); bool fill( const std::string& ); diff --git a/include/ticcutils/FileUtils.h b/include/ticcutils/FileUtils.h index 9b15174..0406f71 100644 --- a/include/ticcutils/FileUtils.h +++ b/include/ticcutils/FileUtils.h @@ -70,8 +70,8 @@ namespace TiCC { std::string _temp_name; std::ofstream *_os; bool _keep; - tmp_stream( const tmp_stream& ); - tmp_stream operator=( const tmp_stream& ); + tmp_stream( const tmp_stream& ) = delete; + tmp_stream operator=( const tmp_stream& ) = delete; }; } diff --git a/include/ticcutils/LogBuffer.h b/include/ticcutils/LogBuffer.h index 7fea411..2186183 100644 --- a/include/ticcutils/LogBuffer.h +++ b/include/ticcutils/LogBuffer.h @@ -78,13 +78,11 @@ template > std::string ass_mess; void buffer_out(); // prohibit copying and assignment - basic_log_buffer( const basic_log_buffer& ); - basic_log_buffer& operator=( const basic_log_buffer& ); + basic_log_buffer( const basic_log_buffer& ) = delete; + basic_log_buffer& operator=( const basic_log_buffer& ) = delete; }; -typedef basic_log_buffer > LogBuffer; -typedef basic_log_buffer > wLogBuffer; - +using LogBuffer = basic_log_buffer>; template basic_log_buffer::~basic_log_buffer(){ diff --git a/include/ticcutils/LogStream.h b/include/ticcutils/LogStream.h index f3610a9..83b2608 100644 --- a/include/ticcutils/LogStream.h +++ b/include/ticcutils/LogStream.h @@ -43,34 +43,28 @@ namespace TiCC { public: explicit LogStream(); explicit LogStream( int ); - explicit LogStream( const std::string&, LogFlag = StampBoth ); - explicit LogStream( const char *cs, LogFlag lf = StampBoth ): - LogStream( std::string( cs ), lf ) {}; LogStream( std::ostream&, - const std::string& = "", LogFlag = StampBoth ); - LogStream( const LogStream&, const std::string&, LogFlag ); - LogStream( const LogStream&, const std::string& ); LogStream( const LogStream * ); + LogStream *create( const std::string&, std::ios_base::openmode = std::ios::out ); bool set_single_threaded_mode(); bool single_threaded() const { return single_threaded_mode; }; - void setthreshold( LogLevel t ){ buf.Threshold( t ); }; - LogLevel getthreshold() const { return buf.Threshold(); }; - void setlevel( LogLevel l ){ buf.Level( l ); }; - LogLevel getlevel() const{ return buf.Level(); }; + void set_threshold( LogLevel t ){ buf.Threshold( t ); }; + LogLevel get_threshold() const { return buf.Threshold(); }; + void set_level( LogLevel l ){ buf.Level( l ); }; + LogLevel get_level() const{ return buf.Level(); }; void associate( std::ostream& os ) { buf.AssocStream( os ); }; - // std::ostream& associate() const { return buf.AssocStream(); }; - void setstamp( LogFlag f ){ buf.StampFlag( f ); }; - LogFlag getstamp() const { return buf.StampFlag(); }; - void message( const std::string& s ){ buf.Message( s ); }; - void addmessage( const std::string& ); - void addmessage( const int ); - const std::string& message() const { return buf.Message(); }; + void set_stamp( LogFlag f ){ buf.StampFlag( f ); }; + LogFlag get_stamp() const { return buf.StampFlag(); }; + void set_message( const std::string& s ){ buf.Message( s ); }; + void add_message( const std::string& ); + void add_message( const int ); + const std::string& get_message() const { return buf.Message(); }; static bool Problems(); private: LogBuffer buf; // prohibit assignment - LogStream& operator=( const LogStream& ); + LogStream& operator=( const LogStream& ) = delete; bool IsBlocking(); bool single_threaded_mode; }; @@ -79,7 +73,7 @@ namespace TiCC { bool IsActive( LogStream * ); /// \brief create a LogStream - class Log{ + class Log { public: explicit Log( LogStream * ); explicit Log( LogStream& l ); @@ -88,8 +82,8 @@ namespace TiCC { private: LogStream *my_stream; LogLevel my_level; - Log( const Log& ); - Log& operator=( const Log& ); + Log( const Log& ) = delete; + Log& operator=( const Log& ) = delete; }; /// \brief create a debugging LogStream @@ -102,8 +96,8 @@ namespace TiCC { private: LogStream *my_stream; LogLevel my_level; - Dbg( const Dbg& ); - Dbg& operator=( const Dbg& ); + Dbg( const Dbg& ) = delete; + Dbg& operator=( const Dbg& ) = delete; }; /// \brief a debugging LogStream for heavy output @@ -116,8 +110,8 @@ namespace TiCC { private: LogStream *my_stream; LogLevel my_level; - xDbg( const xDbg& ); - xDbg& operator=( const xDbg& ); + xDbg( const xDbg& ) = delete; + xDbg& operator=( const xDbg& ) = delete; }; /// \brief a debugging LogStream for extreme output @@ -130,8 +124,8 @@ namespace TiCC { private: LogStream *my_stream; LogLevel my_level; - xxDbg( const xxDbg& ); - xxDbg& operator=( const xxDbg& ); + xxDbg( const xxDbg& ) = delete; + xxDbg& operator=( const xxDbg& ) = delete; }; } diff --git a/include/ticcutils/UniHash.h b/include/ticcutils/UniHash.h index e2c3c70..7a40026 100644 --- a/include/ticcutils/UniHash.h +++ b/include/ticcutils/UniHash.h @@ -56,8 +56,8 @@ namespace Hash { private: const icu::UnicodeString _value; unsigned int _ID; - UniInfo( const UniInfo& ) =delete; - UniInfo& operator=( const UniInfo& ) =delete; + UniInfo( const UniInfo& ) = delete; + UniInfo& operator=( const UniInfo& ) = delete; }; /// \brief The UnicodeHash class is used to enumerate Unicode strings. @@ -85,8 +85,8 @@ namespace Hash { unsigned int _num_of_tokens; std::vector _rev_index; Tries::UniTrie _tree; - UnicodeHash( const UnicodeHash& ) =delete; - UnicodeHash& operator=( const UnicodeHash& ) =delete; + UnicodeHash( const UnicodeHash& ) = delete; + UnicodeHash& operator=( const UnicodeHash& ) = delete; }; } diff --git a/include/ticcutils/Unicode.h b/include/ticcutils/Unicode.h index b2ae42e..f88b10c 100644 --- a/include/ticcutils/Unicode.h +++ b/include/ticcutils/Unicode.h @@ -84,7 +84,7 @@ namespace TiCC { bool set_debug( bool b ){ bool r = _debug; _debug = b; return r; }; private: // inhibit copies! - UnicodeRegexMatcher( const UnicodeRegexMatcher& ) =delete; + UnicodeRegexMatcher( const UnicodeRegexMatcher& ) = delete; UnicodeRegexMatcher& operator=( const UnicodeRegexMatcher& ) = delete; RegexPattern *_pattern; RegexMatcher *_matcher; diff --git a/include/ticcutils/XMLtools.h b/include/ticcutils/XMLtools.h index 90f3763..492e267 100644 --- a/include/ticcutils/XMLtools.h +++ b/include/ticcutils/XMLtools.h @@ -27,46 +27,56 @@ #ifndef TICC_XML_TOOLS_H #define TICC_XML_TOOLS_H +#include #include #include #include -#include +#include #include "libxml/xmlstring.h" #include "libxml/globals.h" #include "libxml/parser.h" namespace TiCC { - inline const xmlChar *to_xmlChar( const char *in ){ - return reinterpret_cast(in); + xmlDoc *create_xmlDocument( const std::string& ); + xmlNode *getRoot( xmlDoc *); + bool isNCName( const std::string& ); + std::string create_NCName( const std::string& ); + + inline const xmlChar *to_xmlChar( const std::string& in ){ + return reinterpret_cast(in.c_str()); } - inline const char *to_char( const xmlChar *in ){ + inline const std::string to_string( const xmlChar *in ){ return reinterpret_cast(in); } + inline const std::string to_string( const xmlChar *in, size_t len ){ + return std::string( reinterpret_cast(in), len ); + } + inline xmlNode *XmlNewNode( const std::string& elem ){ - return xmlNewNode( 0, to_xmlChar(elem.c_str()) ); + return xmlNewNode( 0, to_xmlChar(elem) ); } inline xmlNode *XmlNewNode( xmlNs *ns, const std::string& elem ){ - return xmlNewNode( ns, to_xmlChar(elem.c_str()) ); + return xmlNewNode( ns, to_xmlChar(elem) ); } inline xmlNode *XmlNewComment( const std::string& elem ){ - return xmlNewComment( to_xmlChar(elem.c_str()) ); + return xmlNewComment( to_xmlChar(elem) ); } inline xmlNode *XmlNewChild( xmlNode *node, const std::string& elem ){ - xmlNode *chld = xmlNewNode( 0, to_xmlChar(elem.c_str()) ); + xmlNode *chld = xmlNewNode( 0, to_xmlChar(elem) ); return xmlAddChild( node, chld ); } inline xmlNode *XmlNewChild( xmlNode *node, xmlNs *ns, const std::string& elem ){ - xmlNode *chld = xmlNewNode( ns, to_xmlChar(elem.c_str()) ); + xmlNode *chld = xmlNewNode( ns, to_xmlChar(elem) ); return xmlAddChild( node, chld ); } @@ -76,13 +86,13 @@ namespace TiCC { if ( val.empty() ) return xmlNewTextChild( node, 0, - to_xmlChar(elem.c_str()), + to_xmlChar(elem), 0 ); else return xmlNewTextChild( node, 0, - to_xmlChar(elem.c_str()), - to_xmlChar(val.c_str()) ); + to_xmlChar(elem), + to_xmlChar(val) ); } inline xmlNode *XmlNewTextChild( xmlNode *node, @@ -90,25 +100,52 @@ namespace TiCC { const std::string& elem, const std::string& val ){ if ( val.empty() ) - return xmlNewTextChild( node, ns, - to_xmlChar(elem.c_str()) - , 0 ); + return xmlNewTextChild( node, + ns, + to_xmlChar(elem) + ,0 ); else - return xmlNewTextChild( node, ns, - to_xmlChar(elem.c_str()), - to_xmlChar(val.c_str()) ); + return xmlNewTextChild( node, + ns, + to_xmlChar(elem), + to_xmlChar(val) ); } inline void XmlAddContent( xmlNode *node, const std::string& cont ){ - xmlNodeAddContent( node, to_xmlChar(cont.c_str()) ); + xmlNodeAddContent( node, to_xmlChar(cont) ); } inline xmlAttr *XmlSetAttribute( xmlNode *node, const std::string& att, const std::string& val ){ return xmlSetProp( node, - to_xmlChar(att.c_str()), - to_xmlChar(val.c_str()) ); + to_xmlChar(att), + to_xmlChar(val) ); + } + + inline std::string Name( const xmlNode *node ){ + std::string result; + if ( node ){ + result = to_string(node->name); + } + return result; + } + + inline std::string TextValue( const xmlNode *node ){ + /// extract the string content of an xmlNode + /*! + \param node The xmlNode to extract from + \return the string value of node + */ + std::string result; + if ( node ){ + xmlChar *tmp = xmlNodeGetContent( node ); + if ( tmp ){ + result = to_string(tmp ); + xmlFree( tmp ); + } + } + return result; } inline std::string getAttribute( const xmlNode *node, @@ -116,8 +153,9 @@ namespace TiCC { if ( node ){ const xmlAttr *a = node->properties; while ( a ){ - if ( att == to_char(a->name) ) - return to_char(a->children->content); + if ( att == to_string(a->name) ){ + return TextValue(a->children); + } a = a->next; } } @@ -129,8 +167,7 @@ namespace TiCC { if ( node ){ const xmlAttr *a = node->properties; while ( a ){ - result[to_char(a->name) ] - = to_char(a->children->content); + result[to_string(a->name)] = TextValue(a->children); a = a->next; } } @@ -146,48 +183,23 @@ namespace TiCC { std::map getNSvalues( const xmlNode * ); std::map getDefinedNS( const xmlNode * ); - std::string serialize( const xmlNode& node ); + const std::string serialize( const xmlNode& ); + const std::string serialize( const xmlNode* ); + const std::string serialize( const xmlDoc& ); + const std::string serialize( const xmlDoc* ); - inline std::string Name( const xmlNode *node ){ - std::string result; - if ( node ){ - result = to_char(node->name); - } - return result; + inline std::ostream& operator << ( std::ostream& os, const xmlDoc& doc ){ + os << serialize(doc); + return os; } - inline std::string XmlContent( const xmlNode *node ){ - std::string result; - if ( node ){ - xmlChar *tmp = xmlNodeListGetString( node->doc, node->children, 1 ); - if ( tmp ){ - result = std::string( to_char(tmp) ); - xmlFree( tmp ); - } + inline std::ostream& operator << ( std::ostream& os, const xmlDoc* doc ){ + if ( doc ){ + os << serialize(*doc); } - return result; - } - - /// \brief XmlDoc is a C++ wrapper around libxml2::xmlDoc - class XmlDoc { - friend std::ostream& operator << ( std::ostream& , const XmlDoc& ); - public: - explicit XmlDoc( const std::string& ); - ~XmlDoc(){ - xmlFreeDoc( the_doc ); + else { + os << "No xmlDoc"; } - void setRoot( xmlNode* ); - xmlNode *getRoot() const; - xmlNode *MakeRoot( const std::string& ); - const std::string toString() const; - private: - XmlDoc( const XmlDoc& ) =delete; // no copies please - XmlDoc& operator= ( const XmlDoc& ) =delete; // no copies please - xmlDoc *the_doc; - }; - - inline std::ostream& operator << ( std::ostream& os, const XmlDoc& doc ){ - os << doc.toString(); return os; } @@ -197,7 +209,12 @@ namespace TiCC { } inline std::ostream& operator << ( std::ostream& os, const xmlNode *node ){ - os << serialize( *node ); + if ( node ){ + os << serialize( *node ); + } + else { + os << "No xmlNode"; + } return os; } diff --git a/include/ticcutils/enum_flags.h b/include/ticcutils/enum_flags.h index ea2e563..bad413f 100644 --- a/include/ticcutils/enum_flags.h +++ b/include/ticcutils/enum_flags.h @@ -39,7 +39,6 @@ namespace TiCC { inline ENUMTYPE operator ~ (ENUMTYPE a) { return ENUMTYPE(~((std::underlying_type::type)a)); } \ inline ENUMTYPE operator ^ (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((std::underlying_type::type)a) ^ ((std::underlying_type::type)b)); } \ inline ENUMTYPE &operator ^= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((std::underlying_type::type &)a) ^= ((std::underlying_type::type)b)); } \ - inline std::ostream& operator<<( std::ostream& os, const ENUMTYPE& f ){ os << (std::underlying_type::type &)f; return os; } \ - + inline bool operator % ( const ENUMTYPE &a, ENUMTYPE b) { return (a & b) == b; } } #endif diff --git a/src/FdStream.cxx b/src/FdStream.cxx index 2b42d29..2a471d6 100644 --- a/src/FdStream.cxx +++ b/src/FdStream.cxx @@ -206,7 +206,7 @@ bool nb_putline( ostream& os, const string& what, int& timeout ){ unsigned int i=0; int count = 0; bool result = true; - typedef void (*sig_hndl)(int); + using sig_hndl = void (*)(int); sig_hndl sig; // specify that the SIGPIPE signal is to be ignored sig=signal(SIGPIPE,SIG_IGN); diff --git a/src/FileUtils.cxx b/src/FileUtils.cxx index a6be931..68e81f4 100644 --- a/src/FileUtils.cxx +++ b/src/FileUtils.cxx @@ -63,7 +63,7 @@ namespace TiCC { } bool isFile( const string& name ){ - /// check if 'name' an accessible file + /// check if 'name' a regular file try{ filesystem::path the_path(name); return filesystem::is_regular_file(the_path); @@ -357,7 +357,7 @@ namespace TiCC { close(); delete _os; if ( !_keep ){ - remove( _temp_name.c_str() ); + filesystem::remove( _temp_name ); } } diff --git a/src/LogStream.cxx b/src/LogStream.cxx index cb477c9..5ae5385 100755 --- a/src/LogStream.cxx +++ b/src/LogStream.cxx @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -40,12 +41,12 @@ //#define LSDEBUG using std::ostream; +using std::ofstream; using std::streambuf; using std::cerr; using std::endl; using std::bad_cast; using std::string; -using std::to_string; namespace TiCC { LogStream::LogStream( int ) : @@ -64,22 +65,10 @@ namespace TiCC { /// create a LogStream connected to cerr } - LogStream::LogStream( const string& message, LogFlag stamp ) : - ostream( &buf ), - buf( cerr, message, stamp ), - single_threaded_mode(false) { - /// create a LogStream connected to cerr - /*! - \param message the prefix message - \param stamp the stamping flag to use - */ - } - LogStream::LogStream( ostream& as, - const string& message, LogFlag stamp ) : ostream( &buf ), - buf( as, message, stamp ), + buf( as, "", stamp ), single_threaded_mode(false){ /// create a LogStream connected to an output stream /*! @@ -89,49 +78,6 @@ namespace TiCC { */ } - LogStream::LogStream( const LogStream& ls, - const string& message, - LogFlag stamp ): - ostream( &buf ), - buf( ls.buf.AssocStream(), - ls.buf.Message(), - stamp ), - single_threaded_mode( ls.single_threaded_mode ){ - /// create a LogStream connected to a LogStream - /*! - \param ls a LogStream to connect to - \param message the prefix message to append to the parents message - \param stamp the stamping flag to use - - the new Stream takes all properties from the parent, except for the - message and the stamp flag - */ - buf.Level( ls.buf.Level() ); - buf.Threshold( ls.buf.Threshold() ); - addmessage( message ); - } - - LogStream::LogStream( const LogStream& ls, - const string& message ): - ostream( &buf ), - buf( ls.buf.AssocStream(), - ls.buf.Message(), - ls.buf.StampFlag() ), - single_threaded_mode( ls.single_threaded_mode ){ - /// create a LogStream connected to a LogStream - /*! - \param ls a LogStream to connect to - \param message the prefix message to append to the parents message - - the new Stream takes all properties from the parent, except for the - message - */ - buf.Level( ls.buf.Level() ); - buf.Threshold( ls.buf.Threshold() ); - addmessage( message ); - } - - LogStream::LogStream( const LogStream *ls ): ostream( &buf ), buf( ls->buf.AssocStream(), @@ -147,7 +93,13 @@ namespace TiCC { buf.Threshold( ls->buf.Threshold() ); } - void LogStream::addmessage( const string& s ){ + LogStream *LogStream::create( const string& filename, + std::ios_base::openmode mode ){ + ofstream os( filename, mode ); + return new LogStream( os ); + } + + void LogStream::add_message( const string& s ){ /// append a string to the current messsage if ( !s.empty() ){ string tmp = buf.Message(); @@ -156,10 +108,10 @@ namespace TiCC { } } - void LogStream::addmessage( const int i ){ + void LogStream::add_message( const int i ){ /// append a number to the current messsage - string m = "-" + to_string(i); - addmessage( m ); + string m = "-" + std::to_string(i); + add_message( m ); } static bool static_init = false; @@ -309,10 +261,10 @@ namespace TiCC { /// is the current level below the threshold? if ( !bad() ){ #ifdef LSDEBUG - cerr << "IsBlocking( " << getlevel() << "," << getthreshold() << ")" - << " ==> " << ( getlevel() < getthreshold() ) << endl; + cerr << "IsBlocking( " << get_level() << "," << get_threshold() << ")" + << " ==> " << ( get_level() < get_threshold() ) << endl; #endif - return getlevel() < getthreshold(); + return get_level() < get_threshold(); } else { return true; @@ -336,9 +288,9 @@ namespace TiCC { throw( "LogStreams FATAL error: No Stream supplied! " ); } if ( os->single_threaded() || init_mutex() ){ - my_level = os->getthreshold(); + my_level = os->get_threshold(); my_stream = os; - os->setthreshold( LogNormal ); + os->set_threshold( LogNormal ); } } @@ -346,15 +298,15 @@ namespace TiCC { /// create a Log object on the LogStream with Normal threshold if ( os.single_threaded() || init_mutex() ){ my_stream = &os; - my_level = os.getthreshold(); - os.setthreshold( LogNormal ); + my_level = os.get_threshold(); + os.set_threshold( LogNormal ); } } Log::~Log(){ /// destroy the Log object my_stream->flush(); - my_stream->setthreshold( my_level ); + my_stream->set_threshold( my_level ); if ( !my_stream->single_threaded() ){ mutex_release(); } @@ -363,7 +315,7 @@ namespace TiCC { LogStream& Log::operator *(){ /// return the LogStream from the Log object #ifdef DARE_TO_OPTIMIZE - if ( my_stream->getlevel() >= my_stream->getthreshold() ){ + if ( my_stream->get_level() >= my_stream->get_threshold() ){ return *my_stream; } else { @@ -381,8 +333,8 @@ namespace TiCC { } if ( os->single_threaded() || init_mutex() ){ my_stream = os; - my_level = os->getthreshold(); - os->setthreshold( LogDebug ); + my_level = os->get_threshold(); + os->set_threshold( LogDebug ); } } @@ -390,15 +342,15 @@ namespace TiCC { /// create a Dbg object on the LogStream with Debug threshold if ( os.single_threaded() || init_mutex() ){ my_stream = &os; - my_level = os.getthreshold(); - os.setthreshold( LogDebug ); + my_level = os.get_threshold(); + os.set_threshold( LogDebug ); } } Dbg::~Dbg(){ /// destroy the Dbg object my_stream->flush(); - my_stream->setthreshold( my_level ); + my_stream->set_threshold( my_level ); if ( !my_stream->single_threaded() ){ mutex_release(); } @@ -407,7 +359,7 @@ namespace TiCC { LogStream& Dbg::operator *() { /// return the LogStream from the Dbg object #ifdef DARE_TO_OPTIMIZE - if ( my_stream->getlevel() >= my_stream->getthreshold() ){ + if ( my_stream->get_level() >= my_stream->get_threshold() ){ return *my_stream; } else { @@ -425,8 +377,8 @@ namespace TiCC { } if ( os->single_threaded() || init_mutex() ){ my_stream = os; - my_level = os->getthreshold(); - os->setthreshold( LogHeavy ); + my_level = os->get_threshold(); + os->set_threshold( LogHeavy ); } } @@ -434,15 +386,15 @@ namespace TiCC { /// create a xDbg object on the LogStream with Heavy threshold if ( os.single_threaded() || init_mutex() ){ my_stream = &os; - my_level = os.getthreshold(); - os.setthreshold( LogHeavy ); + my_level = os.get_threshold(); + os.set_threshold( LogHeavy ); } } xDbg::~xDbg(){ /// destroy the xDbg object my_stream->flush(); - my_stream->setthreshold( my_level ); + my_stream->set_threshold( my_level ); if ( !my_stream->single_threaded() ){ mutex_release(); } @@ -451,7 +403,7 @@ namespace TiCC { LogStream& xDbg::operator *(){ /// return the LogStream from the xDbg object #ifdef DARE_TO_OPTIMIZE - if ( my_stream->getlevel() >= my_stream->getthreshold() ){ + if ( my_stream->get_level() >= my_stream->get_threshold() ){ return *my_stream; } else { @@ -469,8 +421,8 @@ namespace TiCC { } if ( os->single_threaded() || init_mutex() ){ my_stream = os; - my_level = os->getthreshold(); - os->setthreshold( LogExtreme ); + my_level = os->get_threshold(); + os->set_threshold( LogExtreme ); } } @@ -478,15 +430,15 @@ namespace TiCC { /// create a xxDbg object on the LogStream with Extreme threshold if ( os.single_threaded() || init_mutex() ){ my_stream = &os; - my_level = os.getthreshold(); - os.setthreshold( LogExtreme ); + my_level = os.get_threshold(); + os.set_threshold( LogExtreme ); } } xxDbg::~xxDbg(){ /// destroy the xxDbg object my_stream->flush(); - my_stream->setthreshold( my_level ); + my_stream->set_threshold( my_level ); if ( !my_stream->single_threaded() ){ mutex_release(); } @@ -495,7 +447,7 @@ namespace TiCC { LogStream& xxDbg::operator *(){ /// return the LogStream from the xxDbg object #ifdef DARE_TO_OPTIMIZE - if ( my_stream->getlevel() >= my_stream->getthreshold() ){ + if ( my_stream->get_level() >= my_stream->get_threshold() ){ return *my_stream; } else { diff --git a/src/Makefile.am b/src/Makefile.am index 2b8aaa3..a3fab6f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,7 +4,7 @@ AM_CXXFLAGS = -g -O3 -std=c++17 -W -Wall -pedantic LDADD = libticcutils.la lib_LTLIBRARIES = libticcutils.la -libticcutils_la_LDFLAGS = -version-info 9:0:0 +libticcutils_la_LDFLAGS = -version-info 10:0:0 libticcutils_la_SOURCES = LogStream.cxx StringOps.cxx \ Configuration.cxx Timer.cxx XMLtools.cxx zipper.cxx \ diff --git a/src/ServerBase.cxx b/src/ServerBase.cxx index f755494..b60da36 100644 --- a/src/ServerBase.cxx +++ b/src/ServerBase.cxx @@ -94,7 +94,7 @@ namespace TiCCServer { ServerBase::ServerBase( const Configuration *config, void *callback_data ): - _my_log("BasicServer"), + _my_log(), _do_daemon( true ), _debug( false ), _max_conn( 25 ), @@ -159,7 +159,7 @@ namespace TiCCServer { else { _name = _protocol + "-server"; } - _my_log.message( _name ); + _my_log.set_message( _name ); value = _config->lookUp( "debug" ); if ( !value.empty() ){ if ( value == "no" ){ diff --git a/src/XMLtools.cxx b/src/XMLtools.cxx index c848b36..c0b06e8 100644 --- a/src/XMLtools.cxx +++ b/src/XMLtools.cxx @@ -38,53 +38,107 @@ using namespace std; namespace TiCC { - XmlDoc::XmlDoc( const string& elem ){ - /// create an XmlDoc with a root node - /*! - \param elem the tag of the root node - */ - the_doc = xmlNewDoc( to_xmlChar("1.0") ); - MakeRoot( elem ); + xmlDoc *create_xmlDocument( const std::string& root_name ){ + xmlDoc *result= xmlNewDoc( TiCC::to_xmlChar("1.0") ); + xmlNode *root = xmlNewDocNode( result, + 0, + TiCC::to_xmlChar(root_name), + 0 ); + xmlDocSetRootElement( result, root ); + return result; } - const string XmlDoc::toString() const { - /// serialize a complete XmlDoc to an UTF-8 string + xmlNode *getRoot( xmlDoc *doc ){ + return xmlDocGetRootElement(doc); + } + + const string serialize( const xmlDoc& doc ) { + /// serialize a complete xmlDoc to an UTF-8 string xmlChar *buf; int size; - xmlDocDumpFormatMemoryEnc( the_doc, &buf, &size, "UTF-8", 1 ); - const string result = string( to_char(buf), size ); + xmlDocDumpFormatMemoryEnc( const_cast(&doc), &buf, &size, "UTF-8", 1 ); + const string result = to_string( buf, size ); xmlFree( buf ); return result; } - xmlNode *XmlDoc::getRoot() const { - /// return the root node - if ( the_doc ){ - return xmlDocGetRootElement(the_doc); - } - return 0; - } - - void XmlDoc::setRoot( xmlNode *node ){ - /// set the root node - if ( the_doc ){ - xmlDocSetRootElement(the_doc, node ); + bool isNCName( const string& s ){ + /// test if a string is a valid NCName value + /*! + \param s the inputstring + \return true if \e s may be used as an NCName (e.g. for xml:id) + */ + int test = xmlValidateNCName( to_xmlChar(s), 0 ); + if ( test != 0 ){ + return false; } + return true; } - xmlNode *XmlDoc::MakeRoot( const string& elem ){ - /// create a root node with tag \e elem + string create_NCName( const string& s ){ + /// create a valid NCName /*! - \param elem the tag of the new root node - \return the newly created node + \param s a string to be used as template + \return a string that is a valid NCname + + Make sure these prerequisites are met: + An xsd:NCName value must start with either a letter or underscore ( _ ) + and may contain only letters, digits, underscores ( _ ), hyphens ( - ), + and periods ( . ). */ - xmlNode *root; - root = xmlNewDocNode( the_doc, - 0, - to_xmlChar(elem.c_str()), - 0 ); - xmlDocSetRootElement( the_doc, root ); - return root; + if ( isNCName( s ) ){ + return s; + } + else { + string result = s; + while ( !result.empty() + && ( result.front() == '.' + || result.front() == '-' + || !isalpha(result.front() ) ) ){ + if ( result.front() == '_' ){ + break; + } + result.erase(result.begin()); + } + if ( result.empty() ){ + throw runtime_error( "unable to create a valid NCName from '" + + s + "', would be empty" ); + } + if ( isNCName( result ) ){ + return result; + } + else { + auto it = result.begin(); + while ( it != result.end() ){ + if ( *it == ' ' ){ + // replace spaces by '_' + *it = '_'; + ++it; + } + else if ( *it == '-' + || *it == '_' + || *it == '.' ){ + // not alphanumeric, but allowed + ++it; + } + else if ( !isalnum(*it) ){ + it = result.erase(it); + } + else { + ++it; + } + } + if ( result.empty() ){ + throw runtime_error( "unable to create a valid NCName from '" + + s + "', (empty result)" ); + } + else if ( !isNCName( result ) ){ + throw runtime_error( "unable to create a valid NCName from '" + + s + "'" ); + } + return result; + } + } } string getNS( const xmlNode *node, string& prefix ){ @@ -99,9 +153,9 @@ namespace TiCC { const xmlNs *p = node->ns; if ( p ){ if ( p->prefix ){ - prefix = to_char(p->prefix); + prefix = to_string(p->prefix); } - result = to_char(p->href); + result = to_string(p->href); } return result; } @@ -118,9 +172,9 @@ namespace TiCC { string pre; string val; if ( p->prefix ){ - pre = to_char(p->prefix); + pre = to_string(p->prefix); } - val = to_char(p->href); + val = to_string(p->href); result[pre] = val; p = p->next; } @@ -139,9 +193,9 @@ namespace TiCC { string pre; string val; if ( p->prefix ){ - pre = to_char(p->prefix); + pre = to_string(p->prefix); } - val = to_char(p->href); + val = to_string(p->href); result[pre] = val; p = p->next; } @@ -159,7 +213,7 @@ namespace TiCC { \return a list of all matching nodes */ list nodes; - xmlXPathObject* result = xmlXPathEval( to_xmlChar(xpath.c_str()), ctxt); + xmlXPathObject* result = xmlXPathEval( to_xmlChar(xpath), ctxt); if ( result ){ if (result->type != XPATH_NODESET) { xmlXPathFreeObject(result); @@ -202,13 +256,13 @@ namespace TiCC { if ( key.empty() ){ // the anonymous namespace xmlXPathRegisterNs( ctxt, - to_xmlChar(defaultP.c_str()), - to_xmlChar(value.c_str()) ); + to_xmlChar(defaultP), + to_xmlChar(value) ); } else { xmlXPathRegisterNs( ctxt, - to_xmlChar(key.c_str()), - to_xmlChar(value.c_str()) ); + to_xmlChar(key), + to_xmlChar(value) ); } } } @@ -303,11 +357,11 @@ namespace TiCC { return xPath( root, xpath ); } - string serialize( const xmlNode& node ){ + const string serialize( const xmlNode& node ){ /// serialize an xmlNode to a string (XML fragment) xmlBuffer *buf = xmlBufferCreate(); xmlNodeDump( buf, 0, const_cast(&node), 0, 0 ); - string result = to_char(xmlBufferContent( buf )); + const string result = to_string(xmlBufferContent( buf )); xmlBufferFree( buf ); return result; } diff --git a/src/runtest.cxx b/src/runtest.cxx index a7a6c39..5305b9b 100644 --- a/src/runtest.cxx +++ b/src/runtest.cxx @@ -46,13 +46,14 @@ #include "ticcutils/Unicode.h" #include "ticcutils/json.hpp" #include "ticcutils/enum_flags.h" +#include "ticcutils/XMLtools.h" using namespace std; using namespace TiCC; using namespace icu; void helper(){ - throw runtime_error("fout"); + throw runtime_error("expected_error"); } int helper2(){ @@ -846,30 +847,35 @@ void test_configuration( const string& path ){ void test_logstream( const string& path ){ ofstream uit( "/tmp/testls.1" ); LogStream ls( uit ); - ls.setstamp( NoStamp ); - *Log( ls ) << "test 1 level=" << ls.getlevel() << " threshold=" << ls.getthreshold() << endl; + ls.set_stamp( NoStamp ); + *Log( ls ) << "test 1 level=" << ls.get_level() << " threshold=" + << ls.get_threshold() << endl; *Dbg( ls ) << "debug 1" << endl; *xDbg( ls ) << "x_debug 1" << endl; *xxDbg( ls ) << "xx_debug 1" << endl; - ls.setlevel( LogSilent ); - *Log( ls ) << "test 2 level=" << ls.getlevel() << " threshold=" << ls.getthreshold() << endl; + ls.set_level( LogSilent ); + *Log( ls ) << "test 2 level=" << ls.get_level() << " threshold=" + << ls.get_threshold() << endl; *Dbg( ls ) << "debug 2" << endl; *xDbg( ls ) << "x_debug 2" << endl; *xxDbg( ls ) << "xx_debug 2" << endl; - ls.setlevel( LogDebug ); - *Log( ls ) << "test 3 level=" << ls.getlevel() << " threshold=" << ls.getthreshold() << endl; + ls.set_level( LogDebug ); + *Log( ls ) << "test 3 level=" << ls.get_level() << " threshold=" + << ls.get_threshold() << endl; *Dbg( ls ) << "debug 3" << endl; *xDbg( ls ) << "x_debug 3" << endl; *xxDbg( ls ) << "xx_debug 3" << endl; - ls.setlevel( LogExtreme ); - *Log( ls ) << "test 4 level=" << ls.getlevel() << " threshold=" << ls.getthreshold() << endl; + ls.set_level( LogExtreme ); + *Log( ls ) << "test 4 level=" << ls.get_level() << " threshold=" + << ls.get_threshold() << endl; *Dbg( ls ) << "debug 4" << endl; *xDbg( ls ) << "x_debug 4" << endl; *xxDbg( ls ) << "xx_debug 4" << endl; - ls.setlevel( LogHeavy ); - *Log( ls ) << "test 5 level=" << ls.getlevel() << " threshold=" << ls.getthreshold() << endl; - ls.addmessage( "AHA:" ); - ls.setstamp( StampMessage ); + ls.set_level( LogHeavy ); + *Log( ls ) << "test 5 level=" << ls.get_level() << " threshold=" + << ls.get_threshold() << endl; + ls.add_message( "AHA:" ); + ls.set_stamp( StampMessage ); *Dbg( ls ) << "debug 5" << endl; *xDbg( ls ) << "x_debug 5" << endl; *xxDbg( ls ) << "xx_debug 5" << endl; @@ -1136,11 +1142,25 @@ enum class class_flags { nope = 0, ok = 1, warning = 1<<1, error = 1<<2 }; DEFINE_ENUM_FLAG_OPERATORS(flags); DEFINE_ENUM_FLAG_OPERATORS(class_flags); +std::ostream& operator<<( std::ostream& os, const flags& f ){ + os << int(f); + return os; +} + +std::ostream& operator<<( std::ostream& os, const class_flags& f ){ + os << int(f); + return os; +} + void test_enum_flags() { { flags f = flags::Two|flags::Four; + cerr << f << endl; + cerr << (f & (flags::Two|flags::Four) ) << endl; + cerr << (f & flags::Two) << endl; // cppcheck-suppress knownConditionTrueFalse assertTrue( f == 6 ); + assertTrue( f % (flags::Two|flags::Four) ); f = ~f; // cppcheck-suppress knownConditionTrueFalse assertEqual( f, -7 ); @@ -1153,17 +1173,23 @@ void test_enum_flags() { { // DEFINE_ENUM_FLAGS works for both 'enum' and 'enum class' // BUT: the assertion macro's have a problem with the latter - // needs work. Now we need an explixit cast + // needs work. Now we need an explicit cast class_flags f = class_flags::warning|class_flags::error; std::stringstream ss; ss << f; assertEqual( ss.str(), "6" ); // cppcheck-suppress knownConditionTrueFalse assertTrue( (int)f == 6 ); + assertTrue( f%(class_flags::warning|class_flags::error) ); + assertTrue( f%class_flags::warning ); + assertTrue( f%class_flags::error ); + assertFalse( f%class_flags::ok ); f = ~f; assertEqual( int(f), -7 ); f &= class_flags::ok; assertEqual( (int)f, 1 ); + assertTrue( (f%class_flags::ok) ); + assertFalse( (f%class_flags::warning) ); } } @@ -1191,7 +1217,7 @@ private: \ template \ static constexpr std::false_type check(...); \ \ - typedef decltype(check(0)) type; \ + using type = decltype(check(0)); \ \ public: \ static constexpr bool value = type::value; \ @@ -1199,6 +1225,7 @@ public: \ ADD_FUN_CHECK( string_fun ) ADD_FUN_CHECK( unistring_fun ) +ADD_FUN_CHECK( int_fun ) void test_templates(){ @@ -1211,18 +1238,37 @@ void test_templates(){ bool unistring_fun( const icu::UnicodeString& ){ return true; } + int int_fun( const int& i, int j ){ + return i+j; + } }; - bool test_string = has_string_fun::value; - assertEqual( test_string, true ); - test_string = has_unistring_fun::value; - assertEqual( test_string, true ); - test_string = has_string_fun::value; - assertEqual( test_string, true ); - test_string = has_unistring_fun::value; - assertEqual( test_string, false ); - test_string = has_string_fun::value; - assertEqual( test_string, false ); + bool test_val = has_string_fun::value; + assertEqual( test_val, true ); + test_val = has_unistring_fun::value; + assertEqual( test_val, true ); + test_val = has_string_fun::value; + assertEqual( test_val, true ); + test_val = has_unistring_fun::value; + assertEqual( test_val, false ); + test_val = has_string_fun::value; + assertEqual( test_val, false ); + test_val = has_int_fun::value; + assertEqual( test_val, true ); + test_val = has_int_fun::value; + assertEqual( test_val, true ); + test_val = has_int_fun::value; + assertEqual( test_val, true ); +} + +void test_ncname(){ + assertFalse( isNCName("123") ); + assertTrue( isNCName("_123") ); + assertEqual( create_NCName( "12?name" ), "name" ); + assertEqual( create_NCName("aap!noot"), "aapnoot" ); + assertEqual( create_NCName("A#12!3"), "A123" ); + assertEqual( create_NCName(".-_!A#12!3"), "_A123" ); + assertEqual( create_NCName("_appel-taart.met slagroom_"), "_appel-taart.met_slagroom_" ); } int main( const int argc, const char* argv[] ){ @@ -1264,6 +1310,7 @@ int main( const int argc, const char* argv[] ){ test_lowercase(); test_unicodehash(); test_realpath(); + test_ncname(); string testdir; bool dummy; opts1.is_present( 'd', testdir, dummy ); diff --git a/src/testlogstream.cxx b/src/testlogstream.cxx index 7f5dd7f..9381282 100644 --- a/src/testlogstream.cxx +++ b/src/testlogstream.cxx @@ -42,7 +42,8 @@ using namespace TiCC; class Sub1 { public: explicit Sub1( LogStream& log ){ - ls = new LogStream( log, "-SUB1" ); + ls = new LogStream( &log ); + ls->set_message( "-SUB1" ); *Log(ls) << "created a sub1 " << endl; } ~Sub1(){ delete ls; }; @@ -75,7 +76,9 @@ class Sub2 { class Sub3 { public: explicit Sub3( Sub2& s ){ - ls = new LogStream( s.ls, "-SUB3", StampMessage ); + ls = new LogStream( s.ls ); + ls->set_stamp( StampMessage ); + ls->set_message( "-SUB3-" ); *Log(ls) << "created a sub3 " << endl; } ~Sub3(){ delete ls; }; @@ -91,7 +94,8 @@ class Sub3 { }; int main(){ - LogStream the_log( "main-log" ); + LogStream the_log; + the_log.set_message( "main-log" ); Sub1 sub1( the_log ); Sub2 sub2( &the_log ); assert( IsActive( the_log ) );