Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package belr for openSUSE:Factory checked in at 2021-10-27 22:21:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/belr (Old) and /work/SRC/openSUSE:Factory/.belr.new.1890 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "belr" Wed Oct 27 22:21:13 2021 rev:11 rq:927658 version:5.0.36 Changes: -------- --- /work/SRC/openSUSE:Factory/belr/belr.changes 2021-07-21 19:07:34.059415318 +0200 +++ /work/SRC/openSUSE:Factory/.belr.new.1890/belr.changes 2021-10-27 22:21:29.983207703 +0200 @@ -1,0 +2,7 @@ +Tue Oct 19 23:24:28 UTC 2021 - Giacomo Comes <gcomes....@gmail.com> - 5.0.36 + +- Update to version 5.0.36: + * Cast on assert to remove warning on x64 + * Remove a useless usage shared_ptr<> in the Parser and Regognizers + +------------------------------------------------------------------- Old: ---- belr-4.5.20.tar.bz2 New: ---- belr-5.0.36.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ belr.spec ++++++ --- /var/tmp/diff_new_pack.cLYxrt/_old 2021-10-27 22:21:30.487207962 +0200 +++ /var/tmp/diff_new_pack.cLYxrt/_new 2021-10-27 22:21:30.491207964 +0200 @@ -19,7 +19,7 @@ %define soname libbelr %define sover 1 Name: belr -Version: 4.5.20 +Version: 5.0.36 Release: 0 Summary: Language recognition library License: GPL-3.0-or-later @@ -31,9 +31,9 @@ Patch0: belr-fix-pkgconfig.patch BuildRequires: cmake BuildRequires: gcc-c++ -BuildRequires: pkgconfig -BuildRequires: pkgconfig(bctoolbox) >= 4.5.0 BuildRequires: libudev-devel +BuildRequires: pkgconfig +BuildRequires: pkgconfig(bctoolbox) >= 5.0.0 %description Belr parses input formatted according to a language defined by an @@ -41,6 +41,7 @@ %package -n %{soname}%{sover} Summary: Language recognition library +Group: Development/Tools/Other %description -n %{soname}%{sover} Belr parses input formatted according to a language defined by an ++++++ belr-4.5.20.tar.bz2 -> belr-5.0.36.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/belr-4.5.20/CMakeLists.txt new/belr-5.0.36/CMakeLists.txt --- old/belr-4.5.20/CMakeLists.txt 2020-10-22 16:31:51.000000000 +0200 +++ new/belr-5.0.36/CMakeLists.txt 2021-09-16 11:45:16.000000000 +0200 @@ -1,6 +1,6 @@ ############################################################################ # CMakeLists.txt -# Copyright (C) 2010-2019 Belledonne Communications, Grenoble France +# Copyright (C) 2010-2021 Belledonne Communications, Grenoble France # ############################################################################ # @@ -20,8 +20,12 @@ # ############################################################################ -cmake_minimum_required(VERSION 3.1) -project(BELR VERSION 4.5.0 LANGUAGES C CXX) + +# CMake 3.13 required for new Flexisip build process. +# See [CMP077](https://cmake.org/cmake/help/v3.13/policy/CMP0077.html). +cmake_minimum_required(VERSION 3.13) + +project(BELR VERSION 5.0.0 LANGUAGES C CXX) set(BELR_SO_VERSION "1") @@ -32,6 +36,10 @@ option(ENABLE_TESTS "Enable compilation of unit tests." YES) option(ENABLE_PACKAGE_SOURCE "Create 'package_source' target for source archive making (CMake >= 3.11)" OFF) +# Hidden non-cache options: +# * DISABLE_BC_PACKAGE_SEARCH: skip find_package() for every BC package (bctoolbox, ortp, etc.) + + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") if(NOT CPACK_GENERATOR AND NOT CMAKE_INSTALL_RPATH AND CMAKE_INSTALL_PREFIX) @@ -50,7 +58,9 @@ # find_package should be invoked here to check for libraries - however do NOT # call include_directories here (see below) -find_package(bctoolbox 0.0.5 REQUIRED OPTIONAL_COMPONENTS tester) +if(NOT DISABLE_BC_PACKAGE_SEARCH) + find_package(bctoolbox 0.0.5 REQUIRED OPTIONAL_COMPONENTS tester) +endif() set(LINK_FLAGS ) @@ -131,9 +141,11 @@ set(EXPORT_TARGET_NAME belr) set(ConfigPackageLocation "${CMAKE_INSTALL_LIBDIR}/cmake/${EXPORT_TARGET_NAME}") -export(EXPORT ${EXPORT_TARGET_NAME}Targets - FILE "${CMAKE_CURRENT_BINARY_DIR}/${EXPORT_TARGET_NAME}Targets.cmake" -) +if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS) + export(EXPORT ${EXPORT_TARGET_NAME}Targets + FILE "${CMAKE_CURRENT_BINARY_DIR}/${EXPORT_TARGET_NAME}Targets.cmake" + ) +endif() configure_package_config_file(cmake/BelrConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${EXPORT_TARGET_NAME}Config.cmake" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/belr-4.5.20/include/belr/belr.h new/belr-5.0.36/include/belr/belr.h --- old/belr-4.5.20/include/belr/belr.h 2020-10-22 16:31:51.000000000 +0200 +++ new/belr-5.0.36/include/belr/belr.h 2021-09-16 11:45:16.000000000 +0200 @@ -68,7 +68,7 @@ void setName(const std::string &name); const std::string &getName()const; - BELR_PUBLIC size_t feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos); + BELR_PUBLIC size_t feed(ParserContextBase &ctx, const std::string &input, size_t pos); unsigned int getId()const{ return mId; } @@ -84,7 +84,7 @@ /*returns true if the transition map is complete, false otherwise*/ virtual bool _getTransitionMap(TransitionMap *mask); virtual void _optimize(int recursionLevel)=0; - virtual size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) = 0; + virtual size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) = 0; std::string mName; unsigned int mId = 0; @@ -108,7 +108,7 @@ CharRecognizer(int to_recognize, bool caseSensitive=false); CharRecognizer(BinaryGrammarBuilder &istr); private: - size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override; + size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) override; void _optimize(int recursionLevel) override; virtual void _serialize(BinaryOutputStream &fstr) override; @@ -123,11 +123,11 @@ Selector(BinaryGrammarBuilder &istr); protected: void _optimize(int recursionLevel) override; - size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override; + size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) override; bool _getTransitionMap(TransitionMap *mask) override; virtual void _serialize(BinaryOutputStream &fstr) override; - size_t _feedExclusive(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos); + size_t _feedExclusive(ParserContextBase &ctx, const std::string &input, size_t pos); std::list<std::shared_ptr<Recognizer>> mElements; bool mIsExclusive = false; @@ -139,7 +139,7 @@ ExclusiveSelector(); ExclusiveSelector(BinaryGrammarBuilder &istr); private: - size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override; + size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) override; }; class Sequence : public Recognizer{ @@ -154,7 +154,7 @@ void _optimize(int recursionLevel) override; private: - size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override; + size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) override; std::list<std::shared_ptr<Recognizer>> mElements; }; @@ -171,7 +171,7 @@ void _optimize(int recursionLevel) override; private: - size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override; + size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) override; std::shared_ptr<Recognizer> mRecognizer; int mMin = 0; @@ -195,7 +195,7 @@ private: virtual void _serialize(BinaryOutputStream &fstr) override; void _optimize(int recursionLevel) override; - size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override; + size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) override; int mBegin; int mEnd; @@ -210,7 +210,7 @@ private: void _optimize(int recursionLevel) override; virtual void _serialize(BinaryOutputStream &fstr) override; - size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override; + size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) override; std::string mLiteral; size_t mLiteralSize; @@ -237,7 +237,7 @@ private: void _optimize(int recursionLevel) override; virtual void _serialize(BinaryOutputStream &fstr) override; - size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override; + size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) override; std::shared_ptr<Recognizer> mRecognizer; }; @@ -259,7 +259,7 @@ private: void _optimize(int recursionLevel) override; virtual void _serialize(BinaryOutputStream &fstr) override; - size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override; + size_t _feed(ParserContextBase &ctx, const std::string &input, size_t pos) override; std::shared_ptr<Recognizer> mRecognizer; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/belr-4.5.20/include/belr/parser.h new/belr-5.0.36/include/belr/parser.h --- old/belr-4.5.20/include/belr/parser.h 2020-10-22 16:31:51.000000000 +0200 +++ new/belr-5.0.36/include/belr/parser.h 2021-09-16 11:45:16.000000000 +0200 @@ -46,6 +46,12 @@ return std::static_pointer_cast<typename T::element_type>(sp); } + +//template <class T, class U> +//inline std::shared_ptr<T> universal_pointer_cast(const std::shared_ptr<U>& sp){ +// return std::static_pointer_cast<T>(sp); +//} + template <class T, class U> inline T universal_pointer_cast(U * p){ return static_cast<T>(p); @@ -85,7 +91,9 @@ inline void _invokeWithChild(_parserElementT obj, typename std::enable_if<std::is_floating_point<_valueT>::value, _parserElementT>::type child){ } template <typename _valueT> - inline void _invokeWithChild(_parserElementT obj, typename std::enable_if<std::is_convertible<_valueT, _parserElementT>::value, _parserElementT>::type child){ + inline void _invokeWithChild( + typename std::enable_if< std::is_convertible<typename _functorT::first_argument_type, _parserElementT>::value, _parserElementT>::type obj, + typename std::enable_if< std::is_convertible<_valueT, _parserElementT>::value, _parserElementT>::type child ){ mFunc(universal_pointer_cast<typename std::remove_reference<typename _functorT::first_argument_type>::type>(obj), universal_pointer_cast<typename std::remove_reference<typename _functorT::second_argument_type>::type>(child)); } @@ -126,6 +134,7 @@ std::shared_ptr<HandlerContext<_parserElementT>> mCachedContext; }; + template <typename _createElementFn, typename _parserElementT> class ParserHandler : public ParserHandlerBase<_parserElementT>{ public: @@ -147,7 +156,6 @@ } template <typename _funcT> typename std::enable_if<std::is_convertible<_funcT, std::function<_derivedParserElementT()>>::value, _derivedParserElementT>::type _invoke(const std::string &value, size_t begin, size_t count){ - // Case where the create func accepts two strings for rulename and matched characters. return mHandlerCreateFunc(); } _createElementFn mHandlerCreateFunc; @@ -293,11 +301,11 @@ BELR_PUBLIC std::shared_ptr<DebugElement> parseInput(const std::string &rulename, const std::string &input, size_t *parsed_size); }; -//Utility functions for handlers/collectors objects instantiation and properties accessors -template <typename _retT> -inline std::function< std::shared_ptr<_retT> ()> make_fn() { - return std::bind(&std::make_shared<_retT>); -} +// +// Utility functions for handlers/collectors objects instantiation and properties accessors +// + +/* For parser relying on raw pointers */ template <typename _retT> inline std::function< _retT ()> make_fn(_retT (*arg)()){ @@ -329,6 +337,13 @@ return std::function< void (_klassT*,_argT)>(std::mem_fn(arg)); } +/* For parsers using shared_ptr<> */ + +template <typename _retT> +inline std::function< std::shared_ptr<_retT> ()> make_fn() { + return std::bind(&std::make_shared<_retT>); +} + template <typename _klassT, typename _argT> inline std::function< void (std::shared_ptr<_klassT>,_argT)> make_sfn(void (_klassT::*arg)(_argT)){ return std::function< void (std::shared_ptr<_klassT>,_argT)>(std::mem_fn(arg)); @@ -487,7 +502,7 @@ if (mHandlerStack.empty()){ fatal("Cannot parse when mHandlerStack is empty. You must define a top-level rule handler."); } - lctx.set(ctx,rec,mHandlerStack.back()->getLastIterator()); + lctx.set(ctx, rec, mHandlerStack.back()->getLastIterator()); } template <typename _parserElementT> @@ -615,14 +630,21 @@ _parserElementT Parser<_parserElementT>::parseInput(const std::string &rulename, const std::string &input, size_t *parsed_size){ size_t parsed; std::shared_ptr<Recognizer> rec=mGrammar->getRule(rulename); - auto pctx=std::make_shared<ParserContext<_parserElementT>>(*this); + ParserContext<_parserElementT> pctx(*this); + + auto h=getHandler(rec->getId()); + if (!h){ + std::ostringstream str; + str<<"There is no handler for rule '"<<rulename<<"'."; + fatal(str.str().c_str()); + } //auto t_start = std::chrono::high_resolution_clock::now(); parsed=rec->feed(pctx, input, 0); //auto t_end = std::chrono::high_resolution_clock::now(); //cout<<"Recognition done in "<<std::chrono::duration<double, std::milli>(t_end-t_start).count()<<" milliseconds"<<std::endl; if (parsed_size) *parsed_size=parsed; - auto ret= pctx->createRootObject(input, parsed); + auto ret= pctx.createRootObject(input, parsed); return ret; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/belr-4.5.20/src/CMakeLists.txt new/belr-5.0.36/src/CMakeLists.txt --- old/belr-4.5.20/src/CMakeLists.txt 2020-10-22 16:31:51.000000000 +0200 +++ new/belr-5.0.36/src/CMakeLists.txt 2021-09-16 11:45:16.000000000 +0200 @@ -60,7 +60,7 @@ else() set(MIN_OS ${CMAKE_OSX_DEPLOYMENT_TARGET}) endif() - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/build/osx/") + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/build/osx/") set_target_properties(belr PROPERTIES FRAMEWORK TRUE MACOSX_FRAMEWORK_IDENTIFIER org.linphone.belr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/belr-4.5.20/src/belr.cpp new/belr-5.0.36/src/belr.cpp --- old/belr-4.5.20/src/belr.cpp 2020-10-22 16:31:51.000000000 +0200 +++ new/belr-5.0.36/src/belr.cpp 2021-09-16 11:45:16.000000000 +0200 @@ -30,6 +30,24 @@ bctbx_fatal("%s", message); } +/* Dummy ParserContext, actually used for optimization phase, to let invoke the feed() function without + * instanciating anything.*/ +class DummyParserContext : public ParserContextBase{ +public: + virtual void beginParse(ParserLocalContext &ctx, const std::shared_ptr<Recognizer> &rec) override{ + } + virtual void endParse(const ParserLocalContext &ctx, const std::string &input, size_t begin, size_t count) override{ + } + virtual std::shared_ptr<HandlerContextBase> branch() override{ + return nullptr; + } + virtual void merge(const std::shared_ptr<HandlerContextBase> &other) override{ + } + virtual void removeBranch(const std::shared_ptr<HandlerContextBase> &other) override{ + } +}; + + // ============================================================================= TransitionMap::TransitionMap(){ @@ -170,7 +188,7 @@ return mName; } -size_t Recognizer::feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t Recognizer::feed(ParserContextBase &ctx, const string &input, size_t pos){ size_t match; #ifdef BELR_DEBUG @@ -178,7 +196,7 @@ #endif ParserLocalContext hctx; - if (ctx) ctx->beginParse(hctx, shared_from_this()); + ctx.beginParse(hctx, shared_from_this()); match=_feed(ctx, input, pos); if (match!=string::npos && match>0){ #ifdef BELR_DEBUG @@ -188,7 +206,7 @@ } #endif } - if (ctx) ctx->endParse(hctx, input, pos, match); + ctx.endParse(hctx, input, pos, match); return match; } @@ -212,7 +230,8 @@ input.resize(2,'\0'); for(int i=0;i<256;++i){ input[0]=i; - if (feed(nullptr,input,0)==1) + DummyParserContext pctx; + if (feed(pctx,input,0)==1) mask->mPossibleChars[i]=true; } return true; @@ -237,7 +256,7 @@ } } -size_t CharRecognizer::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t CharRecognizer::_feed(ParserContextBase &ctx, const string &input, size_t pos){ int c = (unsigned char)input[pos]; if (mCaseSensitive){ return c == mToRecognize ? 1 : string::npos; @@ -278,7 +297,7 @@ return true; } -size_t Selector::_feedExclusive(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t Selector::_feedExclusive(ParserContextBase &ctx, const string &input, size_t pos){ size_t matched=0; for (auto it=mElements.begin(); it!=mElements.end(); ++it){ @@ -290,7 +309,7 @@ return string::npos; } -size_t Selector::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t Selector::_feed(ParserContextBase &ctx, const string &input, size_t pos){ if (mIsExclusive) return _feedExclusive(ctx, input, pos); size_t matched=0; @@ -299,20 +318,19 @@ for (auto it=mElements.begin(); it!=mElements.end(); ++it){ shared_ptr<HandlerContextBase> br; - if (ctx) br=ctx->branch(); + br = ctx.branch(); matched=(*it)->feed(ctx, input, pos); if (matched!=string::npos && matched>bestmatch) { bestmatch=matched; - if (bestBranch) ctx->removeBranch(bestBranch); + if (bestBranch) ctx.removeBranch(bestBranch); bestBranch=br; }else{ - if (ctx) - ctx->removeBranch(br); + ctx.removeBranch(br); } } if (bestmatch==0) return string::npos; - if (ctx && bestmatch!=string::npos){ - ctx->merge(bestBranch); + if (bestmatch!=string::npos){ + ctx.merge(bestBranch); } return bestmatch; } @@ -341,6 +359,11 @@ } +/* The purpose of the optimization is to determine if a selector is exclusive, ie that only a single branch can match. + * This is done by examining if the character transitions to jump to each branch (sub-recognizers) do intersect. + * If no, it means that the first branch that will match during the parsing will necessarily be the good one, so that there is no need to + * examine others. + */ void Selector::_optimize(int recursionLevel){ for (auto it=mElements.begin(); it!=mElements.end(); ++it){ (*it)->optimize(recursionLevel); @@ -373,7 +396,7 @@ ExclusiveSelector::ExclusiveSelector(BinaryGrammarBuilder &istr) : Selector(istr){ } -size_t ExclusiveSelector::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t ExclusiveSelector::_feed(ParserContextBase &ctx, const string &input, size_t pos){ return Selector::_feedExclusive(ctx, input, pos); } @@ -395,7 +418,7 @@ } -size_t Sequence::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t Sequence::_feed(ParserContextBase &ctx, const string &input, size_t pos){ size_t matched=0; size_t total=0; @@ -442,7 +465,7 @@ return static_pointer_cast<Loop>(shared_from_this()); } -size_t Loop::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t Loop::_feed(ParserContextBase &ctx, const string &input, size_t pos){ size_t matched=0; size_t total=0; int repeat; @@ -482,7 +505,7 @@ CharRange::CharRange(int begin, int end) : mBegin(begin), mEnd(end){ } -size_t CharRange::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t CharRange::_feed(ParserContextBase &ctx, const string &input, size_t pos){ int c = (unsigned char)input[pos]; if (c >= mBegin && c <= mEnd) return 1; return string::npos; @@ -530,7 +553,7 @@ } -size_t Literal::_feed(const shared_ptr< ParserContextBase >& ctx, const string& input, size_t pos){ +size_t Literal::_feed(ParserContextBase &ctx, const string& input, size_t pos){ size_t i; for(i=0;i<mLiteralSize;++i){ if (::tolower(input[pos+i])!=mLiteral[i]) return string::npos; @@ -569,7 +592,7 @@ return mRecognizer; } -size_t RecognizerPointer::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t RecognizerPointer::_feed(ParserContextBase &ctx, const string &input, size_t pos){ if (mRecognizer){ return mRecognizer->feed(ctx, input, pos); }else{ @@ -601,7 +624,7 @@ return mRecognizer; } -size_t RecognizerAlias::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){ +size_t RecognizerAlias::_feed(ParserContextBase &ctx, const string &input, size_t pos){ if (mRecognizer){ return mRecognizer->feed(ctx, input, pos); }else{ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/belr-4.5.20/tester/grammar-tester.cpp new/belr-5.0.36/tester/grammar-tester.cpp --- old/belr-4.5.20/tester/grammar-tester.cpp 2020-10-22 16:31:51.000000000 +0200 +++ new/belr-5.0.36/tester/grammar-tester.cpp 2021-09-16 11:45:16.000000000 +0200 @@ -108,7 +108,7 @@ shared_ptr<DebugElement> elem = parser->parseInput("sip-message", sipmessage, &pos); BC_ASSERT_TRUE(elem != nullptr); if (!elem) return; - BC_ASSERT_EQUAL(pos, sipmessage.size(), int, "%i"); + BC_ASSERT_EQUAL((int)pos, (int)sipmessage.size(), int, "%i"); BC_ASSERT_TRUE(sipmessage == elem->getValue()); list<shared_ptr<DebugElement>> headerNames; elem->findChildren("header-name", headerNames); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/belr-4.5.20/tester/parser.cpp new/belr-5.0.36/tester/parser.cpp --- old/belr-4.5.20/tester/parser.cpp 2020-10-22 16:31:51.000000000 +0200 +++ new/belr-5.0.36/tester/parser.cpp 2021-09-16 11:45:16.000000000 +0200 @@ -109,7 +109,7 @@ BC_ASSERT_PTR_NOT_NULL(elem); if (!elem) return; - BC_ASSERT_EQUAL(pos, sipmessage.size(), int, "%i"); + BC_ASSERT_EQUAL((int)pos, (int)sipmessage.size(), int, "%i"); sip_response_t *resp = (sip_response_t*)elem; sip_uri_t *from = resp->from; @@ -127,10 +127,171 @@ sip_response_destroy(resp); } +// +// Parser with inheritance. +// + +/* Base class for all parser elements*/ +class Object{ +public: + virtual ~Object() = default; +}; + +/* Base class for SIP headers */ +class SipHeader : public Object{ +public: + SipHeader(const string &headerName) : mHeaderName(headerName){} + const string &getName()const{ + return mHeaderName; + } +protected: + void setHeaderName(const string &headerName){ + mHeaderName = headerName; + } +private: + string mHeaderName; +}; + +/* + * The SipHeaderHolder is a kind of container for all possible types of SIP headers. + * This special type is needed so that it is possible to parse headers in an unitary way (not in a full message). + * It does not have to be part of the parser API. Keep it internal as an utility. + */ +class SipHeaderHolder : public Object{ +public: + SipHeaderHolder(){}; + void setHeader(const shared_ptr<SipHeader> &header){ + mHeader = header; + } + shared_ptr<SipHeader> getHeader()const{ + return mHeader; + } +private: + shared_ptr<SipHeader> mHeader; +}; + +/* + * SIP From + */ +class SipFrom : public SipHeader{ +public: + SipFrom() : SipHeader("From"){}; + void setUri(const string& uri){ + mUri = uri; + } + const string &getUri()const{ + return mUri; + } +private: + string mUri; +}; + +/* + * Extension header + */ +class ExtensionHeader : public SipHeader{ +public: + ExtensionHeader() : SipHeader("generic"){}; + void setName(const string &headerName){ + SipHeader::setHeaderName(headerName); + } + void setValue(const string &headerValue){ + mHeaderValue = headerValue; + } + const string &getValue()const{ + return mHeaderValue; + } +private: + string mHeaderValue; +}; + +/* + * SIP request. Contains headers. + */ +class SipRequest : public Object{ +public: + SipRequest(){}; + void addHeader(const shared_ptr<SipHeader> &header){ + mHeaders.push_back(header); + } + shared_ptr <SipHeader> getHeader(const string &name){ + for (auto h : mHeaders){ + if (strcasecmp(h->getName().c_str(), name.c_str()) == 0) return h; + } + return nullptr; + } + + /* Hide this from the API documentation */ + void addHeaderHolder(const shared_ptr<SipHeaderHolder> &holder){ + if (holder->getHeader()) + addHeader(holder->getHeader()); + } +private: + list<shared_ptr<SipHeader>> mHeaders; +}; + + +static void parser_with_inheritance(void){ + string grammarToParse = bcTesterRes("sipgrammar.txt"); + string sipmessage = openFile(bcTesterRes("register.txt")); + size_t pos = 0; + + BC_ASSERT_TRUE(sipmessage.size() > 0); + + ABNFGrammarBuilder builder; + + //Read grammar put it in object grammar + shared_ptr<Grammar> grammar=builder.createFromAbnfFile(grammarToParse, make_shared<CoreRules>()); + + BC_ASSERT_FALSE(!grammar); + + if (!grammar) return; + + shared_ptr<Parser<shared_ptr<Object>>> parser = make_shared<Parser<shared_ptr<Object>>>(grammar); + /* The request collects headers in a generic way, thanks to the SipHeaderHolder. */ + parser->setHandler("request", make_fn<SipRequest>()) + ->setCollector("message-header", make_sfn(&SipRequest::addHeaderHolder)); + parser->setHandler("from", make_fn<SipFrom>()) + ->setCollector("sip-uri", make_sfn(&SipFrom::setUri)); + parser->setHandler("extension-header", make_fn<ExtensionHeader>()) + ->setCollector("header-name", make_sfn(&ExtensionHeader::setName)) + ->setCollector("header-value", make_sfn(&ExtensionHeader::setValue)); + + /* The message-header rule (representing all sub-rules of SIP headers) is handled by the SipHeaderHolder. + * It requires explicit collectors for all sub-rules. */ + parser->setHandler("message-header", make_fn<SipHeaderHolder>()) + ->setCollector("from", make_sfn(&SipHeaderHolder::setHeader)) + ->setCollector("extension-header", make_sfn(&SipHeaderHolder::setHeader)); + + // Parse the full message + shared_ptr<Object> elem = parser->parseInput("request", sipmessage, &pos); + BC_ASSERT_TRUE(elem != nullptr); + if (!elem) return; + + BC_ASSERT_EQUAL(pos, sipmessage.size(), size_t, "%zu"); + shared_ptr<SipRequest> request = dynamic_pointer_cast<SipRequest>(elem); + BC_ASSERT_TRUE(request != nullptr); + if (!request) return; + + BC_ASSERT_TRUE(request->getHeader("from") != nullptr); + BC_ASSERT_TRUE(request->getHeader("CustomHeader") != nullptr); + + // Parse a single sip header + + elem = parser->parseInput("message-header", "From: <sip:b...@example.net>\r\n", &pos); + BC_ASSERT_TRUE(elem != nullptr); + if (!elem) return; + auto holder = dynamic_pointer_cast<SipHeaderHolder>(elem); + BC_ASSERT_TRUE(holder != nullptr); + if (!holder) return; + BC_ASSERT_TRUE(dynamic_pointer_cast<SipFrom>(holder->getHeader()) != nullptr); +} + static test_t tests[] = { TEST_NO_TAG("Parser connected to C functions", parser_connected_to_c_functions), + TEST_NO_TAG("Parser with inheritance", parser_with_inheritance) }; test_suite_t parser_suite = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/belr-4.5.20/tester/res/register.txt new/belr-5.0.36/tester/res/register.txt --- old/belr-4.5.20/tester/res/register.txt 2020-10-22 16:31:51.000000000 +0200 +++ new/belr-5.0.36/tester/res/register.txt 2021-09-16 11:45:16.000000000 +0200 @@ -9,6 +9,7 @@ Contact: <sip:smorlat2@78.220.48.77:41076;transport=tls>;+sip.instance="<urn:uuid:2d839989-0bf2-49ba-80b7-2146037f729a>" Expires: 3600 User-Agent: Linphone/3.7.0 (belle-sip/1.3.3) +CustomHeader: some-custom-value Content-Length: 0 Authorization: Digest realm="siptest.linphone.org", nonce="f5Zb2AAAAABXkU1AAAD253sZEAsAAAAA", algorithm=MD5, opaque="+GNywA==", username="smorlat2", uri="sip:siptest.linphone.org", response="f86327204e4c826f47d761c9ad3afdb3", cnonce="faaa9595", nc=00000001, qop=auth