diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5554a39e..fa021710 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,11 +20,11 @@ repos: - id: destroyed-symlinks - id: check-executables-have-shebangs - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v19.1.1 + rev: v19.1.4 hooks: - id: clang-format - repo: https://github.com/PyCQA/pylint - rev: v3.3.1 + rev: v3.3.2 hooks: - id: pylint exclude: ^(.cmake-format.py|conan/conanfile.py|scripts/genignore.py) @@ -52,6 +52,6 @@ repos: language: ruby files: \.(md|mdown|markdown)$ - repo: https://github.com/fsfe/reuse-tool - rev: v4.0.3 + rev: v5.0.2 hooks: - id: reuse diff --git a/CMakeLists.txt b/CMakeLists.txt index b6200d3c..8a72ba7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,18 +121,14 @@ find_path(BOOST_OPTIONAL_DIR NAMES boost/optional.hpp) if(BOOST_OPTIONAL_DIR) message(STATUS "Found boost/optional.hpp in ${BOOST_OPTIONAL_DIR}") include_directories(${BOOST_OPTIONAL_DIR}) - add_definitions(-DBOOST_OPTIONAL_FOUND) endif() set(CMAKE_INCLUDE_CURRENT_DIR TRUE) set(CMAKE_AUTOMOC TRUE) set(CMAKE_AUTORCC ON) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -if(TARGET Qt6::Core) - set(CMAKE_CXX_STANDARD 17) -endif() # Default to hidden visibility for symbols set(CMAKE_C_VISIBILITY_PRESET hidden) diff --git a/docs/CHANGES_2_3.txt b/docs/CHANGES_2_3.txt index 76b14952..85f5c0f2 100644 --- a/docs/CHANGES_2_3.txt +++ b/docs/CHANGES_2_3.txt @@ -1,11 +1,13 @@ General: ======== -* +* C++17 is now required. Qt-5.15 is still supported, in addition to the latest Qt6 versions. + Client-side: ============ * Server-side: ============ -* +* To avoid mixing up raw-xml requests in the same server object (#288), KDSoap now creates a server object for each incoming connection. + Make sure your server object is ready to be created multiple times (this was already a requirement when enabling multi-threading with setThreadPool()). diff --git a/examples/bank_gui/mainwindow.cpp b/examples/bank_gui/mainwindow.cpp index f97fdd98..a7c60b74 100644 --- a/examples/bank_gui/mainwindow.cpp +++ b/examples/bank_gui/mainwindow.cpp @@ -22,10 +22,7 @@ #include #include #include - -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // We enable C++17 with Qt6, and std::random_shuffle is gone in 17 #include -#endif #include @@ -91,13 +88,9 @@ MainWindow::MainWindow(QWidget *parent) void MainWindow::clearResults() { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // We enable C++17 with Qt6, and std::random_shuffle is gone in 17 std::random_device rd; std::mt19937 g(rd()); std::shuffle(mBankCodes.begin(), mBankCodes.end(), g); -#else - std::random_shuffle(mBankCodes.begin(), mBankCodes.end()); -#endif for (int row = 0; row < mBankCodes.count(); ++row) { auto *item = new QTableWidgetItem(mBankCodes.at(row)); mTableWidget->setItem(row, Columns::Code, item); diff --git a/kdwsdl2cpp/libkode b/kdwsdl2cpp/libkode index 425ff918..8ca563b4 160000 --- a/kdwsdl2cpp/libkode +++ b/kdwsdl2cpp/libkode @@ -1 +1 @@ -Subproject commit 425ff9189af08c7e168c931e3c9a3e9911387da9 +Subproject commit 8ca563b4abf97428455e8d552061c02e135de140 diff --git a/kdwsdl2cpp/src/converter.cpp b/kdwsdl2cpp/src/converter.cpp index 8e66608c..b5541272 100644 --- a/kdwsdl2cpp/src/converter.cpp +++ b/kdwsdl2cpp/src/converter.cpp @@ -99,7 +99,7 @@ class TypeCollector void registerDerivedClasses() { XSD::ComplexType::List complexTypes = m_allTypes.complexTypes(); - for (const XSD::ComplexType &derivedType : qAsConst(complexTypes)) { + for (const XSD::ComplexType &derivedType : std::as_const(complexTypes)) { const QName base = derivedType.baseTypeName(); if (!base.isEmpty()) { // Look for the base class and register type. Linear search, maybe we should use a QHash... @@ -120,7 +120,7 @@ class TypeCollector QSet typesToProcess = m_allUsedTypes; do { m_alsoUsedTypes.clear(); - for (const QName &typeName : qAsConst(typesToProcess)) { + for (const QName &typeName : std::as_const(typesToProcess)) { if (typeName.isEmpty()) { continue; } @@ -222,7 +222,7 @@ class MessageCollector PortType portType = wsdl.findPortType(binding.portTypeName()); const Operation::List operations = portType.operations(); // qDebug() << "portType" << portType.name() << operations.count() << "operations"; - for (const Operation &operation : qAsConst(operations)) { + for (const Operation &operation : std::as_const(operations)) { // qDebug() << " operation" << operation.operationType() << operation.name(); switch (operation.operationType()) { case Operation::OneWayOperation: @@ -298,7 +298,7 @@ void Converter::cleanupUnusedTypes() QSet usedTypesStrings; // for debug QSet usedElementNames; Message::List newMessages; - for (const QName &messageName : qAsConst(usedMessageNames)) { + for (const QName &messageName : std::as_const(usedMessageNames)) { // qDebug() << "used message:" << messageName; Message message = mWSDL.findMessage(messageName); newMessages.append(message); @@ -395,13 +395,13 @@ void Converter::convertTypes() XSD::SimpleType::List simpleTypes = types.simpleTypes(); qDebug() << "Converting" << simpleTypes.count() << "simple types"; - for (const XSD::SimpleType &simpleType : qAsConst(simpleTypes)) { + for (const XSD::SimpleType &simpleType : std::as_const(simpleTypes)) { convertSimpleType(&simpleType, simpleTypes); } XSD::ComplexType::List complexTypes = types.complexTypes(); qDebug() << "Converting" << complexTypes.count() << "complex types"; - for (const XSD::ComplexType &complexType : qAsConst(complexTypes)) { + for (const XSD::ComplexType &complexType : std::as_const(complexTypes)) { convertComplexType(&complexType); } } diff --git a/kdwsdl2cpp/src/converter_clientstub.cpp b/kdwsdl2cpp/src/converter_clientstub.cpp index b5c07df8..f1a86fa0 100644 --- a/kdwsdl2cpp/src/converter_clientstub.cpp +++ b/kdwsdl2cpp/src/converter_clientstub.cpp @@ -82,7 +82,7 @@ bool Converter::convertClientService() QSet uniqueBindings = mWSDL.uniqueBindings(service); // qDebug() << "Looking at" << service.name() << uniqueBindings; - for (const QName &bindingName : qAsConst(uniqueBindings)) { + for (const QName &bindingName : std::as_const(uniqueBindings)) { const Binding binding = mWSDL.findBinding(bindingName); QString className = KODE::Style::className(service.name()); @@ -360,7 +360,7 @@ bool Converter::convertClientService() } } // end of for each operation - for (const SoapBinding::Header &header : qAsConst(soapHeaders)) { + for (const SoapBinding::Header &header : std::as_const(soapHeaders)) { createHeader(header, newClass); } bindingClasses.append(newClass); @@ -374,7 +374,7 @@ bool Converter::convertClientService() } // for each operation, create a job class - for (const Operation &operation : qAsConst(operations)) { + for (const Operation &operation : std::as_const(operations)) { Operation::OperationType opType = operation.operationType(); if (opType != Operation::SolicitResponseOperation && opType != Operation::RequestResponseOperation) { continue; @@ -495,7 +495,7 @@ bool Converter::convertClientService() slotCode += QLatin1String("_reply = _reply.childValues().at(0);") + COMMENT; } - for (const Part &part : qAsConst(outputParts)) { + for (const Part &part : std::as_const(outputParts)) { const QString varName = mNameMapper.escape(QLatin1String("result") + upperlize(part.name())); const KODE::MemberVariable member(varName, QString()); slotCode.addBlock( @@ -504,7 +504,7 @@ bool Converter::convertClientService() addJobResultMember(jobClass, part, varName, inputGetters); } } - for (const SoapBinding::Header &header : qAsConst(outputHeaders)) { + for (const SoapBinding::Header &header : std::as_const(outputHeaders)) { const QName messageName = header.message(); const QString partName = header.part(); const Message message = mWSDL.findMessage(messageName); @@ -761,7 +761,7 @@ bool Converter::convertClientCall(const Operation &operation, const Binding &bin code.unindent(); Q_ASSERT(soapStyle(binding) == SoapBinding::DocumentStyle); // RPC with multiple return values? impossible, we generate a single wrapper - for (const Part &part : qAsConst(outParts)) { + for (const Part &part : std::as_const(outParts)) { const QString argType = mTypeMap.localType(part.type(), part.element()); Q_ASSERT(!argType.isEmpty()); const QString lowerName = lowerlize(part.name()); diff --git a/kdwsdl2cpp/src/converter_complextype.cpp b/kdwsdl2cpp/src/converter_complextype.cpp index 730b0c69..67884513 100644 --- a/kdwsdl2cpp/src/converter_complextype.cpp +++ b/kdwsdl2cpp/src/converter_complextype.cpp @@ -573,7 +573,7 @@ void Converter::createComplexTypeSerializer(KODE::Class &newClass, const XSD::Co if (elements.at(0).isQualified()) { marshalCode += QLatin1String("mainValue.setQualified(true);") + COMMENT; } - demarshalCode += "for (const KDSoapValue& val : qAsConst(args)) {"; + demarshalCode += "for (const KDSoapValue& val : std::as_const(args)) {"; demarshalCode.indent(); demarshalCode += "const QString _name = val.name();"; } else { @@ -614,7 +614,7 @@ void Converter::createComplexTypeSerializer(KODE::Class &newClass, const XSD::Co demarshalCode.addBlock(deserializer.demarshalArray("val")); } else { bool first = true; - for (const XSD::Element &elem : qAsConst(elements)) { + for (const XSD::Element &elem : std::as_const(elements)) { const QString elemName = elem.name(); const QString typeName = mTypeMap.localType(elem.type()); @@ -688,12 +688,12 @@ void Converter::createComplexTypeSerializer(KODE::Class &newClass, const XSD::Co marshalCode += "KDSoapValueList attribs;"; demarshalCode += "const QList attribs = args.attributes();"; - demarshalCode += "for (const KDSoapValue& val : qAsConst(attribs)) {"; + demarshalCode += "for (const KDSoapValue& val : std::as_const(attribs)) {"; demarshalCode.indent(); demarshalCode += "const QString _name = val.name();"; bool first = true; - for (const XSD::Attribute &attribute : qAsConst(attributes)) { + for (const XSD::Attribute &attribute : std::as_const(attributes)) { const QString attrName = attribute.name(); if (attrName.isEmpty()) { continue; diff --git a/kdwsdl2cpp/src/converter_serverstub.cpp b/kdwsdl2cpp/src/converter_serverstub.cpp index ffab4c29..d13fba4b 100644 --- a/kdwsdl2cpp/src/converter_serverstub.cpp +++ b/kdwsdl2cpp/src/converter_serverstub.cpp @@ -21,7 +21,7 @@ void Converter::convertServerService() QSet uniqueBindings = mWSDL.uniqueBindings(service); - for (const QName &bindingName : qAsConst(uniqueBindings)) { + for (const QName &bindingName : std::as_const(uniqueBindings)) { // qDebug() << "binding" << bindingName; const Binding binding = mWSDL.findBinding(bindingName); @@ -161,7 +161,7 @@ void Converter::generateServerMethod(KODE::Code &code, const Binding &binding, c // bool isBuiltin = false; // bool isComplex = false; Part retPart; - for (const Part &outPart : qAsConst(outParts) /* only one */) { + for (const Part &outPart : std::as_const(outParts) /* only one */) { retType = mTypeMap.localType(outPart.type(), outPart.element()); retInputType = mTypeMap.localInputType(outPart.type(), outPart.element()); // isBuiltin = mTypeMap.isBuiltinType( outPart.type(), outPart.element() ); diff --git a/kdwsdl2cpp/src/converter_simpletype.cpp b/kdwsdl2cpp/src/converter_simpletype.cpp index 3f19d8ed..1a71bec4 100644 --- a/kdwsdl2cpp/src/converter_simpletype.cpp +++ b/kdwsdl2cpp/src/converter_simpletype.cpp @@ -185,7 +185,7 @@ void Converter::convertSimpleType(const XSD::SimpleType *type, const XSD::Simple baseCtor.addArgument(mTypeMap.localInputType(currentType, QName()) + " value"); QString beginLine = "setValue("; QString endLine = ")"; - for (const QName &base : qAsConst(parentBasicTypes)) { + for (const QName &base : std::as_const(parentBasicTypes)) { beginLine += mTypeMap.localType(base) + '('; endLine += ')'; } @@ -294,7 +294,7 @@ void Converter::createSimpleTypeSerializer(KODE::Class &newClass, const XSD::Sim const QStringList enums = type->facetEnums(); NameMapper nameMapper; QStringList escapedEnums; - for (const QString &facetEnum : qAsConst(enums)) { + for (const QString &facetEnum : std::as_const(enums)) { escapedEnums.append(nameMapper.escape(escapeEnum(facetEnum))); } diff --git a/kdwsdl2cpp/src/creator.cpp b/kdwsdl2cpp/src/creator.cpp index ca5ffd4a..5566ea7c 100644 --- a/kdwsdl2cpp/src/creator.cpp +++ b/kdwsdl2cpp/src/creator.cpp @@ -53,7 +53,7 @@ void Creator::setImplementationFileName(const QString &implementationFileName) void Creator::setClasses(const KODE::Class::List &list) { - for (const KODE::Class &newClass : qAsConst(list)) { + for (const KODE::Class &newClass : std::as_const(list)) { _file.insertClass(newClass); } } diff --git a/kdwsdl2cpp/wsdl/binding.cpp b/kdwsdl2cpp/wsdl/binding.cpp index dc143adf..e42de735 100644 --- a/kdwsdl2cpp/wsdl/binding.cpp +++ b/kdwsdl2cpp/wsdl/binding.cpp @@ -102,7 +102,7 @@ void Binding::saveXML(ParserContext *context, QDomDocument &document, QDomElemen mSoapBinding.synthesizeBinding(context, document, element); - for (const BindingOperation &operation : qAsConst(mOperations)) { + for (const BindingOperation &operation : std::as_const(mOperations)) { operation.saveXML(&mSoapBinding, context, document, element); } } diff --git a/kdwsdl2cpp/wsdl/definitions.cpp b/kdwsdl2cpp/wsdl/definitions.cpp index 163c7419..f7fd294f 100644 --- a/kdwsdl2cpp/wsdl/definitions.cpp +++ b/kdwsdl2cpp/wsdl/definitions.cpp @@ -176,7 +176,7 @@ void Definitions::fixUpDefinitions(/*ParserContext *context, const QDomElement & if (mServices.isEmpty()) { if (!mBindings.isEmpty()) { qDebug() << "No service tag found in the wsdl file, generating one service per binding"; - for (const Binding &bind : qAsConst(mBindings)) { + for (const Binding &bind : std::as_const(mBindings)) { Service service(mTargetNamespace); service.setName(bind.name() + "Service"); @@ -194,7 +194,7 @@ void Definitions::fixUpDefinitions(/*ParserContext *context, const QDomElement & } else { Q_ASSERT(!mPortTypes.isEmpty()); qDebug() << "No service or binding tag found in the wsdl file, generating only messages"; - for (const PortType &portType : qAsConst(mPortTypes)) { + for (const PortType &portType : std::as_const(mPortTypes)) { Binding binding(mTargetNamespace); binding.setName(portType.name() + "Binding"); binding.setPortTypeName(QName(portType.nameSpace(), portType.name())); diff --git a/kdwsdl2cpp/wsdl/message.cpp b/kdwsdl2cpp/wsdl/message.cpp index 99f5a80b..00b0e68a 100644 --- a/kdwsdl2cpp/wsdl/message.cpp +++ b/kdwsdl2cpp/wsdl/message.cpp @@ -48,7 +48,7 @@ Part::List Message::parts() const Part Message::partByName(const QString &name) const { - for (const Part &part : qAsConst(mParts)) { + for (const Part &part : std::as_const(mParts)) { if (part.name() == name) { // # namespace comparison needed too? return part; } @@ -93,7 +93,7 @@ void Message::saveXML(ParserContext *context, QDomDocument &document, QDomElemen context->messageHandler()->warning(QLatin1String("Message: 'name' required")); } - for (const Part &part : qAsConst(mParts)) { + for (const Part &part : std::as_const(mParts)) { part.saveXML(context, document, element); } } diff --git a/kdwsdl2cpp/wsdl/operation.cpp b/kdwsdl2cpp/wsdl/operation.cpp index 614e5bed..82811f85 100644 --- a/kdwsdl2cpp/wsdl/operation.cpp +++ b/kdwsdl2cpp/wsdl/operation.cpp @@ -153,7 +153,7 @@ void Operation::saveXML(ParserContext *context, QDomDocument &document, QDomElem case SolicitResponseOperation: mOutput.saveXML(context, QLatin1String("output"), document, element); mInput.saveXML(context, QLatin1String("input"), document, element); - for (const Fault &fault : qAsConst(mFaults)) { + for (const Fault &fault : std::as_const(mFaults)) { fault.saveXML(context, document, element); } break; @@ -164,7 +164,7 @@ void Operation::saveXML(ParserContext *context, QDomDocument &document, QDomElem default: mInput.saveXML(context, QLatin1String("input"), document, element); mOutput.saveXML(context, QLatin1String("output"), document, element); - for (const Fault &fault : qAsConst(mFaults)) { + for (const Fault &fault : std::as_const(mFaults)) { fault.saveXML(context, document, element); } break; diff --git a/kdwsdl2cpp/wsdl/porttype.cpp b/kdwsdl2cpp/wsdl/porttype.cpp index a033af25..8b7d7c86 100644 --- a/kdwsdl2cpp/wsdl/porttype.cpp +++ b/kdwsdl2cpp/wsdl/porttype.cpp @@ -81,7 +81,7 @@ void PortType::saveXML(ParserContext *context, QDomDocument &document, QDomEleme context->messageHandler()->warning(QLatin1String("PortType: 'name' required")); } - for (const Operation &operation : qAsConst(mOperations)) { + for (const Operation &operation : std::as_const(mOperations)) { operation.saveXML(context, document, element); } } diff --git a/kdwsdl2cpp/wsdl/service.cpp b/kdwsdl2cpp/wsdl/service.cpp index 7cfe934c..cafd5c6e 100644 --- a/kdwsdl2cpp/wsdl/service.cpp +++ b/kdwsdl2cpp/wsdl/service.cpp @@ -84,7 +84,7 @@ void Service::saveXML(ParserContext *context, const Binding::List *bindings, QDo context->messageHandler()->warning(QLatin1String("Service: 'name' required")); } - for (const Port &port : qAsConst(mPorts)) { + for (const Port &port : std::as_const(mPorts)) { port.saveXML(context, bindings, document, element); } } diff --git a/kdwsdl2cpp/wsdl/soapbinding.cpp b/kdwsdl2cpp/wsdl/soapbinding.cpp index c68a4212..8a003c07 100644 --- a/kdwsdl2cpp/wsdl/soapbinding.cpp +++ b/kdwsdl2cpp/wsdl/soapbinding.cpp @@ -938,7 +938,7 @@ void SoapBinding::synthesizePort(ParserContext *context, QDomDocument &document, bool SoapBinding::Headers::contains(const Header &other) const { - for (const Header &header : qAsConst(*this)) { + for (const Header &header : std::as_const(*this)) { if (header.mMessage == other.mMessage && header.mPart == other.mPart && header.mUse == other.mUse && #if 0 header.mEncodingStyle == other.mEncodingStyle && diff --git a/src/KDSoapClient/KDSoapMessage.cpp b/src/KDSoapClient/KDSoapMessage.cpp index 6b6d5c97..0ec4af2a 100644 --- a/src/KDSoapClient/KDSoapMessage.cpp +++ b/src/KDSoapClient/KDSoapMessage.cpp @@ -199,7 +199,7 @@ void KDSoapMessage::setUse(Use use) KDSoapMessage KDSoapHeaders::header(const QString &name) const { - for (const KDSoapMessage &header : qAsConst(*this)) { + for (const KDSoapMessage &header : std::as_const(*this)) { if (header.name() == name) { return header; } @@ -209,7 +209,7 @@ KDSoapMessage KDSoapHeaders::header(const QString &name) const KDSoapMessage KDSoapHeaders::header(const QString &name, const QString &namespaceUri) const { - for (const KDSoapMessage &header : qAsConst(*this)) { + for (const KDSoapMessage &header : std::as_const(*this)) { // qDebug() << "header(" << name << "," << namespaceUri << "): Looking at" << header.name() << "," << header.namespaceUri(); if (header.name() == name && (namespaceUri.isEmpty() || header.namespaceUri() == namespaceUri)) { return header; diff --git a/src/KDSoapClient/KDSoapMessageAddressingProperties.cpp b/src/KDSoapClient/KDSoapMessageAddressingProperties.cpp index 76174a94..013164da 100644 --- a/src/KDSoapClient/KDSoapMessageAddressingProperties.cpp +++ b/src/KDSoapClient/KDSoapMessageAddressingProperties.cpp @@ -289,7 +289,7 @@ static void writeKDSoapValueVariant(QXmlStreamWriter &writer, const KDSoapValue static void writeKDSoapValueListHierarchy(KDSoapNamespacePrefixes &namespacePrefixes, QXmlStreamWriter &writer, const QString &addressingNS, const KDSoapValueList &values) { - for (const KDSoapValue &value : qAsConst(values)) { + for (const KDSoapValue &value : std::as_const(values)) { const QString topLevelName = value.name(); writer.writeStartElement(addressingNS, topLevelName); @@ -363,7 +363,7 @@ void KDSoapMessageAddressingProperties::writeMessageAddressingProperties(KDSoapN writer.writeEndElement(); } - for (const KDSoapMessageRelationship::Relationship &relationship : qAsConst(d->relationships)) { + for (const KDSoapMessageRelationship::Relationship &relationship : std::as_const(d->relationships)) { if (relationship.uri.isEmpty()) { continue; } diff --git a/src/KDSoapClient/KDSoapMessageReader.cpp b/src/KDSoapClient/KDSoapMessageReader.cpp index edf05efc..0fe64d1d 100644 --- a/src/KDSoapClient/KDSoapMessageReader.cpp +++ b/src/KDSoapClient/KDSoapMessageReader.cpp @@ -22,7 +22,7 @@ static QStringView namespaceForPrefix(const QXmlStreamNamespaceDeclarations &decls, const QString &prefix) { - for (const QXmlStreamNamespaceDeclaration &decl : qAsConst(decls)) { + for (const QXmlStreamNamespaceDeclaration &decl : std::as_const(decls)) { if (decl.prefix() == prefix) { return decl.namespaceUri(); } diff --git a/src/KDSoapClient/KDSoapMessageWriter.cpp b/src/KDSoapClient/KDSoapMessageWriter.cpp index cdffe40a..bee6c049 100644 --- a/src/KDSoapClient/KDSoapMessageWriter.cpp +++ b/src/KDSoapClient/KDSoapMessageWriter.cpp @@ -67,10 +67,10 @@ QByteArray KDSoapMessageWriter::messageToXml(const KDSoapMessage &message, const // and xsi:type attributes that refer to n1, which isn't defined in the body... namespacePrefixes.writeNamespace(writer, messageNamespace, QLatin1String("n1") /*make configurable?*/); writer.writeStartElement(soapEnvelope, QLatin1String("Header")); - for (const KDSoapMessage &header : qAsConst(persistentHeaders)) { + for (const KDSoapMessage &header : std::as_const(persistentHeaders)) { header.writeChildren(namespacePrefixes, writer, header.use(), messageNamespace, true); } - for (const KDSoapMessage &header : qAsConst(headers)) { + for (const KDSoapMessage &header : std::as_const(headers)) { header.writeChildren(namespacePrefixes, writer, header.use(), messageNamespace, true); } if (message.hasMessageAddressingProperties()) { diff --git a/src/KDSoapClient/KDSoapPendingCall.cpp b/src/KDSoapClient/KDSoapPendingCall.cpp index 8c2029d3..75ce7ebb 100644 --- a/src/KDSoapClient/KDSoapPendingCall.cpp +++ b/src/KDSoapClient/KDSoapPendingCall.cpp @@ -22,7 +22,7 @@ static void debugHelper(const QByteArray &data, const QListvalue(); - for (const QXmlStreamNamespaceDeclaration &decl : qAsConst(d->m_localNamespaceDeclarations)) { + for (const QXmlStreamNamespaceDeclaration &decl : std::as_const(d->m_localNamespaceDeclarations)) { writer.writeNamespace(decl.namespaceUri().toString(), decl.prefix().toString()); } @@ -416,7 +416,7 @@ KDSoapValueList KDSoapValue::split() const const QStringList list = value().toString().split(QLatin1Char(' '), QString::SkipEmptyParts); #endif valueList.reserve(list.count()); - for (const QString &part : qAsConst(list)) { + for (const QString &part : std::as_const(list)) { KDSoapValue value(*this); value.setValue(part); valueList << value; @@ -426,7 +426,7 @@ KDSoapValueList KDSoapValue::split() const KDSoapValue KDSoapValueList::child(const QString &name) const { - for (const KDSoapValue &val : qAsConst(*this)) { + for (const KDSoapValue &val : std::as_const(*this)) { if (val.name() == name) { return val; } diff --git a/src/KDSoapServer/KDSoapServerSocket.cpp b/src/KDSoapServer/KDSoapServerSocket.cpp index 6533cf7d..48b44e8f 100644 --- a/src/KDSoapServer/KDSoapServerSocket.cpp +++ b/src/KDSoapServer/KDSoapServerSocket.cpp @@ -54,6 +54,8 @@ KDSoapServerSocket::~KDSoapServerSocket() { // same as m_owner->socketDeleted, but safe in case m_owner is deleted first emit socketDeleted(this); + + delete m_serverObject; } typedef QMap HeadersMap; @@ -145,7 +147,7 @@ static QByteArray httpResponseHeaders(bool fault, const QByteArray &contentType, KDSoapServerObjectInterface *serverObjectInterface = qobject_cast(serverObject); if (serverObjectInterface) { const KDSoapServerObjectInterface::HttpResponseHeaderItems &additionalItems = serverObjectInterface->additionalHttpResponseHeaderItems(); - for (const KDSoapServerObjectInterface::HttpResponseHeaderItem &headerItem : qAsConst(additionalItems)) { + for (const KDSoapServerObjectInterface::HttpResponseHeaderItem &headerItem : std::as_const(additionalItems)) { httpResponse += headerItem.m_name; httpResponse += ": "; httpResponse += headerItem.m_value; @@ -370,7 +372,7 @@ void KDSoapServerSocket::handleRequest(const QMap &httpH // SOAP 1.2 // Example: application/soap+xml;charset=utf-8;action=ActionHex const QList parts = contentType.split(';'); - for (const QByteArray &part : qAsConst(parts)) { + for (const QByteArray &part : std::as_const(parts)) { if (part.trimmed().startsWith("action=")) { // krazy:exclude=strings soapAction = stripQuotes(part.mid(part.indexOf('=') + 1)); } diff --git a/src/KDSoapServer/KDSoapServerThread.cpp b/src/KDSoapServer/KDSoapServerThread.cpp index 5805e004..454bed05 100644 --- a/src/KDSoapServer/KDSoapServerThread.cpp +++ b/src/KDSoapServer/KDSoapServerThread.cpp @@ -112,7 +112,7 @@ int KDSoapServerThreadImpl::socketCount() { QMutexLocker lock(&m_socketListMutex); int sc = 0; - for (KDSoapSocketList *socketList : qAsConst(m_socketLists)) { + for (KDSoapSocketList *socketList : std::as_const(m_socketLists)) { sc += socketList->socketCount(); } sc += m_incomingConnectionCount.loadAcquire(); diff --git a/src/KDSoapServer/KDSoapSocketList.cpp b/src/KDSoapServer/KDSoapSocketList.cpp index ccd1f5a3..cab30866 100644 --- a/src/KDSoapServer/KDSoapSocketList.cpp +++ b/src/KDSoapServer/KDSoapSocketList.cpp @@ -14,21 +14,18 @@ KDSoapSocketList::KDSoapSocketList(KDSoapServer *server) : m_server(server) - , m_serverObject(server->createServerObject()) , m_totalConnectionCount(0) { Q_ASSERT(m_server); - Q_ASSERT(m_serverObject); } KDSoapSocketList::~KDSoapSocketList() { - delete m_serverObject; } KDSoapServerSocket *KDSoapSocketList::handleIncomingConnection(int socketDescriptor) { - KDSoapServerSocket *socket = new KDSoapServerSocket(this, m_serverObject); + KDSoapServerSocket *socket = new KDSoapServerSocket(this, m_server->createServerObject()); socket->setSocketDescriptor(socketDescriptor); #ifndef QT_NO_SSL @@ -61,7 +58,7 @@ int KDSoapSocketList::socketCount() const void KDSoapSocketList::disconnectAll() { - for (KDSoapServerSocket *socket : qAsConst(m_sockets)) { + for (KDSoapServerSocket *socket : std::as_const(m_sockets)) { socket->close(); // will disconnect } } diff --git a/src/KDSoapServer/KDSoapSocketList_p.h b/src/KDSoapServer/KDSoapSocketList_p.h index 3965ca15..350ee50d 100644 --- a/src/KDSoapServer/KDSoapSocketList_p.h +++ b/src/KDSoapServer/KDSoapSocketList_p.h @@ -45,7 +45,6 @@ public Q_SLOTS: private: KDSoapServer *m_server; - QObject *m_serverObject; QSet m_sockets; QAtomicInt m_totalConnectionCount; }; diff --git a/src/KDSoapServer/KDSoapThreadPool.cpp b/src/KDSoapServer/KDSoapThreadPool.cpp index 1fcdd793..39ea7755 100644 --- a/src/KDSoapServer/KDSoapThreadPool.cpp +++ b/src/KDSoapServer/KDSoapThreadPool.cpp @@ -35,10 +35,10 @@ KDSoapThreadPool::KDSoapThreadPool(QObject *parent) KDSoapThreadPool::~KDSoapThreadPool() { // ask all threads to finish, then delete them all - for (KDSoapServerThread *thread : qAsConst(d->m_threads)) { + for (KDSoapServerThread *thread : std::as_const(d->m_threads)) { thread->quitThread(); } - for (KDSoapServerThread *thread : qAsConst(d->m_threads)) { + for (KDSoapServerThread *thread : std::as_const(d->m_threads)) { thread->wait(); delete thread; } @@ -62,7 +62,7 @@ KDSoapServerThread *KDSoapThreadPool::Private::chooseNextThread() // Try to pick an existing thread int minSocketCount = 0; KDSoapServerThread *bestThread = nullptr; - for (KDSoapServerThread *thr : qAsConst(m_threads)) { + for (KDSoapServerThread *thr : std::as_const(m_threads)) { // We look at the amount of sockets connected to each thread, and pick the less busy one. // Note that this isn't fully accurate, due to Keep-Alive: it's possible for long-term // idling clients to be all on one thread, and active clients on another one, and this @@ -108,7 +108,7 @@ void KDSoapThreadPool::handleIncomingConnection(int socketDescriptor, KDSoapServ int KDSoapThreadPool::numConnectedSockets(const KDSoapServer *server) const { int sc = 0; - for (KDSoapServerThread *thread : qAsConst(d->m_threads)) { + for (KDSoapServerThread *thread : std::as_const(d->m_threads)) { sc += thread->socketCountForServer(server); } return sc; @@ -117,7 +117,7 @@ int KDSoapThreadPool::numConnectedSockets(const KDSoapServer *server) const void KDSoapThreadPool::disconnectSockets(KDSoapServer *server) { QSemaphore readyThreads; - for (KDSoapServerThread *thread : qAsConst(d->m_threads)) { + for (KDSoapServerThread *thread : std::as_const(d->m_threads)) { thread->disconnectSocketsForServer(server, readyThreads); } // Wait for all threads to have disconnected their sockets @@ -127,7 +127,7 @@ void KDSoapThreadPool::disconnectSockets(KDSoapServer *server) int KDSoapThreadPool::totalConnectionCount(const KDSoapServer *server) const { int sc = 0; - for (KDSoapServerThread *thread : qAsConst(d->m_threads)) { + for (KDSoapServerThread *thread : std::as_const(d->m_threads)) { sc += thread->totalConnectionCountForServer(server); } return sc; @@ -135,7 +135,7 @@ int KDSoapThreadPool::totalConnectionCount(const KDSoapServer *server) const void KDSoapThreadPool::resetTotalConnectionCount(const KDSoapServer *server) { - for (KDSoapServerThread *thread : qAsConst(d->m_threads)) { + for (KDSoapServerThread *thread : std::as_const(d->m_threads)) { thread->resetTotalConnectionCountForServer(server); } } diff --git a/testtools/httpserver_p.h b/testtools/httpserver_p.h index 137ad7b5..6bdce5c0 100644 --- a/testtools/httpserver_p.h +++ b/testtools/httpserver_p.h @@ -104,7 +104,7 @@ class HttpServerThread : public QThread QByteArray header(const QByteArray &value) const { QMutexLocker lock(&m_mutex); - return m_headers.value(value); + return m_headers.value(value, m_headers.value(value.toLower())); } /** diff --git a/unittests/serverlib/test_serverlib.cpp b/unittests/serverlib/test_serverlib.cpp index 22e671d2..5d8e4269 100644 --- a/unittests/serverlib/test_serverlib.cpp +++ b/unittests/serverlib/test_serverlib.cpp @@ -39,8 +39,8 @@ Q_DECLARE_METATYPE(QFile::Permissions) static const char *myWsdlNamespace = "http://www.kdab.com/xml/MyWsdl/"; class CountryServerObject; -typedef QMap ServerObjectsMap; -ServerObjectsMap s_serverObjects; +typedef QList ServerObjectsList; +ServerObjectsList s_serverObjects; QMutex s_serverObjectsMutex; class PublicThread : public QThread @@ -88,13 +88,13 @@ class CountryServerObject : public QObject, { // qDebug() << "Server object created in thread" << QThread::currentThread(); QMutexLocker locker(&s_serverObjectsMutex); - s_serverObjects.insert(QThread::currentThread(), this); + s_serverObjects.append(this); } ~CountryServerObject() { QMutexLocker locker(&s_serverObjectsMutex); - Q_ASSERT(s_serverObjects.value(QThread::currentThread()) == this); - s_serverObjects.remove(QThread::currentThread()); + Q_ASSERT(s_serverObjects.contains(this)); + s_serverObjects.removeOne(this); } virtual void processRequest(const KDSoapMessage &request, KDSoapMessage &response, const QByteArray &soapAction) override; @@ -189,7 +189,7 @@ class CountryServerObject : public QObject, { // Should be called in same thread as constructor s_serverObjectsMutex.lock(); - Q_ASSERT(s_serverObjects.value(QThread::currentThread()) == this); + Q_ASSERT(s_serverObjects.contains(this)); s_serverObjectsMutex.unlock(); if (employeeName.isEmpty()) { setFault(QLatin1String("Client.Data"), QLatin1String("Empty employee name"), QLatin1String("CountryServerObject"), @@ -403,7 +403,7 @@ private Q_SLOTS: QCOMPARE(response.childValues().first().value().toString(), expectedCountry()); QCOMPARE(s_serverObjects.count(), 1); - QVERIFY(s_serverObjects.value(&serverThread)); // request handled by server thread itself (no thread pool) + QCOMPARE(s_serverObjects.at(0)->thread(), &serverThread); // request handled by server thread itself (no thread pool) QCOMPARE(server->totalConnectionCount(), 1); delete client; QTest::qWait(100); @@ -533,7 +533,7 @@ private Q_SLOTS: const KDSoapMessage response = client->call(QLatin1String("getEmployeeCountry"), countryMessage()); QCOMPARE(response.childValues().first().value().toString(), expectedCountry()); QCOMPARE(s_serverObjects.count(), 1); - QThread *thread = s_serverObjects.begin().key(); + QThread *thread = s_serverObjects.at(0)->thread(); QVERIFY(thread != qApp->thread()); QVERIFY(thread != &serverThread); QCOMPARE(server->totalConnectionCount(), 1); @@ -547,7 +547,7 @@ private Q_SLOTS: QTest::addColumn("maxThreads"); QTest::addColumn("numRequests"); QTest::addColumn("numClients"); - QTest::addColumn("expectedServerObjects"); + QTest::addColumn("expectedThreads"); // QNetworkAccessManager only does 6 concurrent http requests // (QHttpNetworkConnectionPrivate::defaultHttpChannelCount = 6) @@ -564,7 +564,7 @@ private Q_SLOTS: QFETCH(int, maxThreads); QFETCH(int, numRequests); QFETCH(int, numClients); - QFETCH(int, expectedServerObjects); + QFETCH(int, expectedThreads); { KDSoapThreadPool threadPool; threadPool.setMaxThreadCount(maxThreads); @@ -583,16 +583,18 @@ private Q_SLOTS: m_eventLoop.exec(); QCOMPARE(m_returnMessages.count(), m_expectedMessages); - for (const KDSoapMessage &response : qAsConst(m_returnMessages)) { + for (const KDSoapMessage &response : std::as_const(m_returnMessages)) { QCOMPARE(response.childValues().first().value().toString(), expectedCountry()); } - QCOMPARE(s_serverObjects.count(), expectedServerObjects); - QMapIterator it(s_serverObjects); - while (it.hasNext()) { - QThread *thread = it.next().key(); + QCOMPARE(s_serverObjects.count(), numRequests); + QSet usedThreads; + for (CountryServerObject *obj : qAsConst(s_serverObjects)) { + QThread *thread = obj->thread(); QVERIFY(thread != qApp->thread()); QVERIFY(thread != &serverThread); + usedThreads.insert(thread); } + QCOMPARE(usedThreads.count(), expectedThreads); } QCOMPARE(server->totalConnectionCount(), numClients * numRequests); } @@ -690,7 +692,7 @@ private Q_SLOTS: slotStats(); } if (server->totalConnectionCount() < expectedConnectedSockets) { - for (const KDSoapMessage &response : qAsConst(m_returnMessages)) { + for (const KDSoapMessage &response : std::as_const(m_returnMessages)) { if (response.isFault()) { qDebug() << response.faultAsString(); break; @@ -704,7 +706,7 @@ private Q_SLOTS: qPrintable(QString::number(server->totalConnectionCount()))); QCOMPARE(m_returnMessages.count(), m_expectedMessages); - for (const KDSoapMessage &response : qAsConst(m_returnMessages)) { + for (const KDSoapMessage &response : std::as_const(m_returnMessages)) { QCOMPARE(response.childValues().first().value().toString(), expectedCountry()); } //QCOMPARE(s_serverObjects.count(), expectedServerObjects); @@ -1343,9 +1345,9 @@ private Q_SLOTS: loop.exec(); reply->readAll(); - QVERIFY(reply->rawHeaderList().contains("Access-Control-Allow-Origin")); + QVERIFY(reply->hasRawHeader("Access-Control-Allow-Origin")); QCOMPARE(reply->rawHeader("Access-Control-Allow-Origin").constData(), "*"); - QVERIFY(reply->rawHeaderList().contains("Access-Control-Allow-Headers")); + QVERIFY(reply->hasRawHeader("Access-Control-Allow-Headers")); QCOMPARE(reply->rawHeader("Access-Control-Allow-Headers").constData(), "Content-Type"); } diff --git a/unittests/wsdl_document/test_wsdl_document.cpp b/unittests/wsdl_document/test_wsdl_document.cpp index 90b2d47a..0bff3487 100644 --- a/unittests/wsdl_document/test_wsdl_document.cpp +++ b/unittests/wsdl_document/test_wsdl_document.cpp @@ -191,7 +191,9 @@ private Q_SLOTS: expectedRequestXml.replace("%1", expectedHeader()); QVERIFY(xmlBufferCompare(server.receivedData(), expectedRequestXml)); QCOMPARE(QString::fromUtf8(server.receivedData().constData()), QString::fromUtf8(expectedRequestXml.constData())); - QVERIFY(server.receivedHeaders().contains("SoapAction: \"http://www.kdab.com/AddEmployee\"")); + const QByteArray headers = server.receivedHeaders(); + QVERIFY(headers.contains("SoapAction: \"http://www.kdab.com/AddEmployee\"") + || headers.contains("soapaction: \"http://www.kdab.com/AddEmployee\"")); // Qt >= 6.8 } // Test utf8 @@ -393,7 +395,9 @@ private Q_SLOTS: expectedRequestXml.replace("%1", expectedHeader()); QVERIFY(xmlBufferCompare(server.receivedData(), expectedRequestXml)); QCOMPARE(QString::fromUtf8(server.receivedData().constData()), QString::fromUtf8(expectedRequestXml.constData())); - QVERIFY(server.receivedHeaders().contains("SoapAction: \"http://www.kdab.com/AddEmployee\"")); + const QByteArray headers = server.receivedHeaders(); + QVERIFY(headers.contains("SoapAction: \"http://www.kdab.com/AddEmployee\"") + || headers.contains("soapaction: \"http://www.kdab.com/AddEmployee\"")); #endif } @@ -1237,6 +1241,7 @@ void WsdlDocumentTest::testDisconnectDuringDelayedCall() { TestServerThread serverThread; DocServer *server = serverThread.startThread(); + QPointer serverObject; { MyWsdlDocument service; service.setEndPoint(server->endPoint()); @@ -1246,14 +1251,14 @@ void WsdlDocumentTest::testDisconnectDuringDelayedCall() job->start(); // Wait until the server method is called QTRY_VERIFY(server->lastServerObject()); - QTRY_COMPARE(server->lastServerObject()->m_lastMethodCalled, QString::fromLatin1("delayedAddEmployee")); + serverObject = server->lastServerObject(); + QTRY_COMPARE(serverObject->m_lastMethodCalled, QString::fromLatin1("delayedAddEmployee")); delete job; } // Disconnect the client - // Let the server continue - - QTRY_COMPARE(server->lastServerObject()->m_lastMethodCalled, QString::fromLatin1("slotDelayedResponse")); + // Now that there's one server object per socket (#289), the server object gets deleted before the delayed response + QTRY_VERIFY(serverObject.isNull()); } // Same as testSequenceInResponse (thomas-bayer.wsdl), but as a server test, by calling DocServer on a different path diff --git a/unittests/wsdl_rpc/test_wsdl_rpc.cpp b/unittests/wsdl_rpc/test_wsdl_rpc.cpp index 582ddf0c..80bdc00e 100644 --- a/unittests/wsdl_rpc/test_wsdl_rpc.cpp +++ b/unittests/wsdl_rpc/test_wsdl_rpc.cpp @@ -110,7 +110,9 @@ private Q_SLOTS: expectedRequestXml.replace("%1", expectedHeader); QVERIFY(xmlBufferCompare(server.receivedData(), expectedRequestXml)); QCOMPARE(QString::fromUtf8(server.receivedData().constData()), QString::fromUtf8(expectedRequestXml.constData())); - QVERIFY(server.receivedHeaders().contains("SoapAction: \"http://www.kdab.com/AddEmployee\"")); + const QByteArray headers = server.receivedHeaders(); + QVERIFY(headers.contains("SoapAction: \"http://www.kdab.com/AddEmployee\"") + || headers.contains("soapaction: \"http://www.kdab.com/AddEmployee\"")); // Qt >= 6.8 } // Test utf8