diff --git a/cpp/include/Ice/Config.h b/cpp/include/Ice/Config.h index 9b75d6ec580..79a642b5608 100644 --- a/cpp/include/Ice/Config.h +++ b/cpp/include/Ice/Config.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/cpp/include/Ice/LocalException.h b/cpp/include/Ice/LocalException.h index 5bda1e9b550..3e22493bf71 100644 --- a/cpp/include/Ice/LocalException.h +++ b/cpp/include/Ice/LocalException.h @@ -362,8 +362,8 @@ class ICE_CLASS(ICE_API) TwowayOnlyException : public LocalExceptionHelper(file, line), - operation(operation) + TwowayOnlyException(const char* file, int line, ::std::string operation) : LocalExceptionHelper(file, line), + operation(std::move(operation)) { } diff --git a/cpp/include/Ice/Proxy.h b/cpp/include/Ice/Proxy.h index b603d3e275f..288c49eadc8 100644 --- a/cpp/include/Ice/Proxy.h +++ b/cpp/include/Ice/Proxy.h @@ -824,7 +824,7 @@ class ICE_API ObjectPrx : public Proxy const ::IceInternal::ReferencePtr& _getReference() const { return _reference; } const ::IceInternal::RequestHandlerCachePtr& _getRequestHandlerCache() const { return _requestHandlerCache; } - void _checkTwowayOnly(const std::string&) const; + void _checkTwowayOnly(std::string_view) const; int _hash() const; diff --git a/cpp/include/IceUtil/OutputUtil.h b/cpp/include/IceUtil/OutputUtil.h index c9786071b8c..3418ae1dffc 100644 --- a/cpp/include/IceUtil/OutputUtil.h +++ b/cpp/include/IceUtil/OutputUtil.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace IceUtilInternal { @@ -99,6 +100,9 @@ class ICE_API Output : public OutputBase void spar(char = '('); // Start a paramater list. void epar(char = ')'); // End a paramater list. + void spar(std::string_view); // Start a paramater list. + void epar(std::string_view); // End a paramater list. + private: std::string _blockStart; diff --git a/cpp/src/Ice/InputStream.cpp b/cpp/src/Ice/InputStream.cpp index 45849c86803..9c34bfed47e 100644 --- a/cpp/src/Ice/InputStream.cpp +++ b/cpp/src/Ice/InputStream.cpp @@ -1950,7 +1950,7 @@ Ice::InputStream::EncapsDecoder10::readInstance() // For the 1.0 encoding, the type ID for the base Object class // marks the last slice. // - if(_typeId == Object::ice_staticId()) + if(_typeId == Value::ice_staticId()) { throw NoValueFactoryException(__FILE__, __LINE__, "", mostDerivedId); } @@ -2424,7 +2424,7 @@ Ice::InputStream::EncapsDecoder11::readInstance(int32_t index, PatchFunc patchFu // We pass the "::Ice::Object" ID to indicate that this is the // last chance to preserve the object. // - v = newInstance(Object::ice_staticId()); + v = newInstance(Value::ice_staticId()); if(!v) { v = make_shared(mostDerivedId); diff --git a/cpp/src/Ice/Object.cpp b/cpp/src/Ice/Object.cpp index 591fefdddb3..2f571e9d8c9 100644 --- a/cpp/src/Ice/Object.cpp +++ b/cpp/src/Ice/Object.cpp @@ -18,33 +18,16 @@ namespace Ice const Current emptyCurrent = Current(); } -namespace -{ - -const string object_ids[] = -{ - "::Ice::Object" -}; - -const string object_all[] = -{ - "ice_id", - "ice_ids", - "ice_isA", - "ice_ping" -}; - -} - Ice::Request::~Request() { // Out of line to avoid weak vtable } bool -Ice::Object::ice_isA(string s, const Current&) const +Ice::Object::ice_isA(string s, const Current& current) const { - return s == object_ids[0]; + vector allTypeIds = ice_ids(current); // sorted type IDs + return ::std::binary_search(allTypeIds.begin(), allTypeIds.end(), s); } void @@ -56,19 +39,21 @@ Ice::Object::ice_ping(const Current&) const vector Ice::Object::ice_ids(const Current&) const { - return vector(&object_ids[0], &object_ids[1]); + static const vector allTypeIds = { "::Ice::Object" }; + return allTypeIds; } string Ice::Object::ice_id(const Current&) const { - return object_ids[0]; + return ice_staticId(); } const string& Ice::Object::ice_staticId() { - return object_ids[0]; + static const ::std::string typeId = "::Ice::Object"; + return typeId; } bool @@ -152,14 +137,22 @@ Ice::Object::ice_dispatch(Request& request, std::function r, std::functi bool Ice::Object::_iceDispatch(Incoming& in, const Current& current) { - pair r = equal_range(object_all, object_all + sizeof(object_all) / sizeof(string), current.operation); + static constexpr string_view allOperations[] = + { + "ice_id", + "ice_ids", + "ice_isA", + "ice_ping" + }; + + pair r = equal_range(allOperations, allOperations + 4, current.operation); if(r.first == r.second) { throw OperationNotExistException(__FILE__, __LINE__, current.id, current.facet, current.operation); } - switch(r.first - object_all) + switch(r.first - allOperations) { case 0: { diff --git a/cpp/src/Ice/OutputStream.cpp b/cpp/src/Ice/OutputStream.cpp index ebc55f174e8..667502b5c52 100644 --- a/cpp/src/Ice/OutputStream.cpp +++ b/cpp/src/Ice/OutputStream.cpp @@ -949,7 +949,7 @@ Ice::OutputStream::EncapsEncoder10::endInstance() // // Write the Object slice. // - startSlice(Object::ice_staticId(), -1, true); + startSlice(Value::ice_staticId(), -1, true); _stream->writeSize(0); // For compatibility with the old AFM. endSlice(); } diff --git a/cpp/src/Ice/Proxy.cpp b/cpp/src/Ice/Proxy.cpp index 78b202aa977..943a274c0d3 100644 --- a/cpp/src/Ice/Proxy.cpp +++ b/cpp/src/Ice/Proxy.cpp @@ -58,11 +58,11 @@ Ice::ObjectPrx::ObjectPrx(ReferencePtr&& ref) : } void -Ice::ObjectPrx::_checkTwowayOnly(const string& name) const +Ice::ObjectPrx::_checkTwowayOnly(string_view name) const { if (!ice_isTwoway()) { - throw Ice::TwowayOnlyException(__FILE__, __LINE__, name); + throw Ice::TwowayOnlyException(__FILE__, __LINE__, string(name)); } } diff --git a/cpp/src/IceUtil/OutputUtil.cpp b/cpp/src/IceUtil/OutputUtil.cpp index 2584cc8d1a1..dc9746f861f 100644 --- a/cpp/src/IceUtil/OutputUtil.cpp +++ b/cpp/src/IceUtil/OutputUtil.cpp @@ -346,6 +346,21 @@ IceUtilInternal::Output::epar(char c) _out << c; } +void +IceUtilInternal::Output::spar(string_view s) +{ + _emptyBlock = false; + _out << s; + _par = 0; +} + +void +IceUtilInternal::Output::epar(string_view s) +{ + _par = -1; + _out << s; +} + Output& IceUtilInternal::operator<<(Output& out, ios_base& (*val)(ios_base&)) { diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index 831e8d5b047..61bfffa777d 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -1742,57 +1742,6 @@ Slice::Gen::DefaultFactoryVisitor::visitExceptionStart(const ExceptionPtr& p) return false; } -bool -Slice::Gen::DefaultFactoryVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) -{ - OperationList allOps = p->allOperations(); - - C << sp; - - StringList ids = p->ids(); - C << nl << "const ::std::string iceC" << p->flattenedScope() << p->name() << "_ids[" << ids.size() << "] ="; - C << sb; - for (StringList::const_iterator r = ids.begin(); r != ids.end();) - { - C << nl << '"' << *r << '"'; - if (++r != ids.end()) - { - C << ','; - } - } - C << eb << ';'; - - StringList allOpNames; - transform(allOps.begin(), allOps.end(), back_inserter(allOpNames), [](const auto &c) { return c->name(); }); - allOpNames.push_back("ice_id"); - allOpNames.push_back("ice_ids"); - allOpNames.push_back("ice_isA"); - allOpNames.push_back("ice_ping"); - allOpNames.sort(); - allOpNames.unique(); - - C << nl << "const ::std::string iceC" << p->flattenedScope() << p->name() << "_ops[] ="; - C << sb; - for (StringList::const_iterator q = allOpNames.begin(); q != allOpNames.end();) - { - C << nl << '"' << *q << '"'; - if (++q != allOpNames.end()) - { - C << ','; - } - } - C << eb << ';'; - - return true; -} - -void -Slice::Gen::DefaultFactoryVisitor::visitOperation(const OperationPtr& p) -{ - string flatName = "iceC" + p->flattenedScope() + p->name() + "_name"; - C << nl << "const ::std::string " << flatName << " = \"" << p->name() << "\";"; -} - Slice::Gen::ProxyVisitor::ProxyVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport), _useWstring(false) { @@ -1958,8 +1907,6 @@ void Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) { string name = p->name(); - string flatName = "iceC" + p->flattenedScope() + p->name() + "_name"; - InterfaceDefPtr interface = p->interface(); string interfaceScope = fixKwd(interface->scope()); @@ -2222,9 +2169,14 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) // "Custom" implementation in .cpp file // C << sb; + + // TODO: switch to string_view and constexpr. + C << nl << "static const ::std::string operationName = \"" << name << "\";"; + C << sp; + if(p->returnsData()) { - C << nl << "_checkTwowayOnly(" << flatName << ");"; + C << nl << "_checkTwowayOnly(operationName);"; } C << nl << "::std::function read;"; @@ -2263,7 +2215,7 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) C << "*this, read, ex, sent);"; C << sp; - C << nl << "outAsync->invoke(" << flatName << ", "; + C << nl << "outAsync->invoke(operationName, "; C << operationModeToString(p->sendMode(), true) << ", " << opFormatTypeToString(p, true) << ", context,"; C.inc(); C << nl; @@ -2337,11 +2289,14 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) C << inParamsImplDecl << ("const " + getUnqualified("::Ice::Context&", interfaceScope) + " context"); C << epar << " const"; C << sb; + // TODO: switch to string_view and constexpr. + C << nl << "static const ::std::string operationName = \"" << name << "\";"; + C << sp; if(p->returnsData()) { - C << nl << "_checkTwowayOnly(" << flatName << ");"; + C << nl << "_checkTwowayOnly(operationName);"; } - C << nl << "outAsync->invoke(" << flatName << ", "; + C << nl << "outAsync->invoke(operationName, "; C << getUnqualified(operationModeToString(p->sendMode(), true), interfaceScope) << ", " << getUnqualified(opFormatTypeToString(p, true), interfaceScope) << ", context,"; C.inc(); @@ -3231,15 +3186,6 @@ Slice::Gen::InterfaceVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) H << sp; H << nl << "/**"; - H << nl << " * Determines whether this object supports an interface with the given Slice type ID."; - H << nl << " * @param id The fully-scoped Slice type ID."; - H << nl << " * @param current The Current object for the invocation."; - H << nl << " * @return True if this object supports the interface, false, otherwise."; - H << nl << " */"; - H << nl << "bool ice_isA(::std::string id, const " << getUnqualified("::Ice::Current&", scope) - << " current) const override;"; - H << sp; - H << nl << "/**"; H << nl << " * Obtains a list of the Slice type IDs representing the interfaces supported by this object."; H << nl << " * @param current The Current object for the invocation."; H << nl << " * @return A list of fully-scoped type IDs."; @@ -3257,26 +3203,27 @@ Slice::Gen::InterfaceVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) << " current) const override;"; H << sp; H << nl << "/**"; - H << nl << " * Obtains the Slice type ID corresponding to this class."; + H << nl << " * Obtains the Slice type ID corresponding to this interface."; H << nl << " * @return A fully-scoped type ID."; H << nl << " */"; H << nl << "static const ::std::string& ice_staticId();"; - string flatName = "iceC" + p->flattenedScope() + p->name() + "_ids"; - - C << sp; - C << nl << "bool" << nl << scoped.substr(2) << "::ice_isA(::std::string s, const " - << getUnqualified("::Ice::Current&", scope) << ") const"; - C << sb; - C << nl << "return ::std::binary_search(" << flatName << ", " << flatName << " + " << ids.size() << ", s);"; - C << eb; - C << sp; C << nl << "::std::vector<::std::string>" << nl << scoped.substr(2) << "::ice_ids(const " << getUnqualified("::Ice::Current&", scope) << ") const"; C << sb; - C << nl << "return ::std::vector<::std::string>(&" << flatName << "[0], &" << flatName << '[' << ids.size() - << "]);"; + + // These type IDs are sorted alphabetically. + C << nl << "static const ::std::vector<::std::string> allTypeIds = "; + C.spar("{ "); + for (const auto& typeId : p->ids()) + { + C << '"' + typeId + '"'; + } + C.epar(" }"); + C << ";"; + + C << nl << "return allTypeIds;"; C << eb; C << sp; @@ -3320,8 +3267,6 @@ Slice::Gen::InterfaceVisitor::visitInterfaceDefEnd(const InterfaceDefPtr& p) allOpNames.sort(); allOpNames.unique(); - string flatName = "iceC" + p->flattenedScope() + p->name() + "_ops"; - H << sp; H << nl << "/// \\cond INTERNAL"; H << nl << "virtual bool _iceDispatch(::IceInternal::Incoming&, const " @@ -3335,8 +3280,19 @@ Slice::Gen::InterfaceVisitor::visitInterfaceDefEnd(const InterfaceDefPtr& p) << getUnqualified("::Ice::Current&", scope) << " current)"; C << sb; - C << nl << "::std::pair r = " - << "::std::equal_range(" << flatName << ", " << flatName << " + " << allOpNames.size() + C << sp; + C << nl << "static constexpr ::std::string_view allOperations[] = "; + C.spar("{ "); + for (const auto& opName : allOpNames) + { + C << '"' + opName + '"'; + } + C.epar(" }"); + C << ";"; + + C << sp; + C << nl << "::std::pair r = " + << "::std::equal_range(allOperations, allOperations" << " + " << allOpNames.size() << ", current.operation);"; C << nl << "if(r.first == r.second)"; C << sb; @@ -3344,7 +3300,7 @@ Slice::Gen::InterfaceVisitor::visitInterfaceDefEnd(const InterfaceDefPtr& p) << "(__FILE__, __LINE__, current.id, current.facet, current.operation);"; C << eb; C << sp; - C << nl << "switch(r.first - " << flatName << ')'; + C << nl << "switch(r.first - allOperations)"; C << sb; int i = 0; for(StringList::const_iterator q = allOpNames.begin(); q != allOpNames.end(); ++q) diff --git a/cpp/src/slice2cpp/Gen.h b/cpp/src/slice2cpp/Gen.h index 0c0fd7813b2..bffc74efa7a 100644 --- a/cpp/src/slice2cpp/Gen.h +++ b/cpp/src/slice2cpp/Gen.h @@ -107,10 +107,6 @@ class Gen bool visitClassDefStart(const ClassDefPtr&) final; bool visitExceptionStart(const ExceptionPtr&) final; - // TODO: temporary - move to InterfaceVisitor. - bool visitInterfaceDefStart(const InterfaceDefPtr&) final; - void visitOperation(const OperationPtr&) final; - private: ::IceUtilInternal::Output& C;