desktop/inc/lib/init.hxx | 28 +++---- desktop/qa/desktop_lib/test_desktop_lib.cxx | 6 - desktop/source/lib/init.cxx | 98 ++++++++++++------------- desktop/source/lib/lokinteractionhandler.cxx | 4 - include/editeng/outliner.hxx | 4 - include/sfx2/lokcallback.hxx | 6 + include/sfx2/viewsh.hxx | 4 - include/test/lokcallback.hxx | 4 - include/tools/json_writer.hxx | 11 +- include/vcl/IDialogRenderable.hxx | 2 include/vcl/svapp.hxx | 2 sc/qa/unit/tiledrendering/tiledrendering.cxx | 14 +-- sc/source/ui/undo/undotab.cxx | 4 - sc/source/ui/view/viewfun2.cxx | 4 - sd/source/core/annotations/Annotation.cxx | 12 +-- sfx2/source/control/unoctitm.cxx | 2 sfx2/source/sidebar/SidebarController.cxx | 6 - sfx2/source/view/viewsh.cxx | 4 - sw/qa/extras/tiledrendering/tiledrendering.cxx | 2 sw/qa/extras/uiwriter/uiwriter5.cxx | 5 - sw/qa/extras/uiwriter/uiwriter6.cxx | 5 - sw/qa/extras/uiwriter/uiwriter8.cxx | 5 - sw/qa/uibase/uno/uno.cxx | 32 ++++---- sw/source/core/crsr/bookmark.cxx | 4 - sw/source/core/crsr/crsrsh.cxx | 3 sw/source/core/crsr/viscrs.cxx | 8 +- sw/source/core/docnode/nodes.cxx | 2 sw/source/core/txtnode/atrref.cxx | 2 sw/source/uibase/misc/swruler.cxx | 3 sw/source/uibase/wrtsh/wrtsh3.cxx | 4 - test/source/lokcallback.cxx | 9 +- tools/qa/cppunit/test_json_writer.cxx | 23 ++--- tools/source/misc/json_writer.cxx | 30 +------ vcl/inc/jsdialog/jsdialogbuilder.hxx | 2 vcl/jsdialog/jsdialogbuilder.cxx | 15 +-- vcl/source/app/svapp.cxx | 6 - 36 files changed, 176 insertions(+), 199 deletions(-)
New commits: commit e57d5daaea734ade43e8251120afa031099a0840 Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Mon Apr 3 14:04:44 2023 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Wed Apr 5 17:02:46 2023 +0200 fix leaks when using tools::JsonWriter Specifically in sd/source/core/annotations/Annotation.cxx We seem to end up fixing leaks here often. The current tools::JsonWriter API is just very hard to use correctly. So rather return an OString, which is cheap to copy, and push that down into the LOK code. AFAIK that seems to end up requiring less code and less adhoc copying of data (specifically the queueing code in init.cxx was creating copies when converting to std::string). Ideally, we could have some special API to avoid the new strdup() calls in init.cxx, but not sure how to prevent other people from accidentally using that. Change-Id: Ia33437c1bfd9cc2d54dfb99914d1b72db20335f2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149963 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index cd6636ac2242..edc1b12a0c71 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -86,7 +86,7 @@ namespace desktop { return m_aRectangle.IsEmpty(); } - static RectangleAndPart Create(const std::string& rPayload); + static RectangleAndPart Create(const OString& rPayload); /// Makes sure a rectangle is valid (apparently some code does not like negative coordinates for example). static tools::Rectangle SanitizedRectangle(tools::Long nLeft, tools::Long nTop, tools::Long nWidth, tools::Long nHeight); static tools::Rectangle SanitizedRectangle(const tools::Rectangle& rect); @@ -100,7 +100,7 @@ namespace desktop { virtual ~CallbackFlushHandler() override; virtual void Invoke() override; // TODO This should be dropped and the binary libreOfficeKitViewCallback() variants should be called? - void queue(const int type, const char* data); + void queue(const int type, const OString& data); /// Disables callbacks on this handler. Must match with identical count /// of enableCallbacks. Used during painting and changing views. @@ -117,8 +117,8 @@ namespace desktop { void setViewId( int viewId ) { m_viewId = viewId; } // SfxLockCallbackInterface - virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) override; - virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) override; + virtual void libreOfficeKitViewCallback(int nType, const OString& pPayload) override; + virtual void libreOfficeKitViewCallbackWithViewId(int nType, const OString& pPayload, int nViewId) override; virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart, int nMode) override; virtual void libreOfficeKitViewUpdatedCallback(int nType) override; virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) override; @@ -128,13 +128,13 @@ namespace desktop { private: struct CallbackData { - CallbackData(const char* payload) - : PayloadString(payload ? payload : "(nil)") + CallbackData(OString payload) + : PayloadString(payload) { } - CallbackData(const char* payload, int viewId) - : PayloadString(payload ? payload : "(nil)") + CallbackData(OString payload, int viewId) + : PayloadString(payload) , PayloadObject(viewId) { } @@ -149,7 +149,7 @@ namespace desktop { { // PayloadString will be done on demand } - const std::string& getPayload() const; + const OString& getPayload() const; /// Update a RectangleAndPart object and update PayloadString if necessary. void updateRectangleAndPart(const RectangleAndPart& rRectAndPart); /// Return the parsed RectangleAndPart instance. @@ -165,7 +165,7 @@ namespace desktop { bool isEmpty() const { - return PayloadString.empty() && PayloadObject.which() == 0; + return PayloadString.isEmpty() && PayloadObject.which() == 0; } void clear() { @@ -180,7 +180,7 @@ namespace desktop { bool isCached() const { return PayloadObject.which() != 0; } private: - mutable std::string PayloadString; + mutable OString PayloadString; /// The parsed payload cache. Update validate() when changing this. mutable boost::variant<boost::blank, RectangleAndPart, boost::property_tree::ptree, int> PayloadObject; @@ -204,9 +204,9 @@ namespace desktop { so we split the queue in 2 to make the scanning cache friendly. */ queue_type1 m_queue1; queue_type2 m_queue2; - std::map<int, std::string> m_states; - std::unordered_map<std::string, std::string> m_lastStateChange; - std::unordered_map<int, std::unordered_map<int, std::string>> m_viewStates; + std::map<int, OString> m_states; + std::unordered_map<OString, OString> m_lastStateChange; + std::unordered_map<int, std::unordered_map<int, OString>> m_viewStates; // For some types only the last message matters (see isUpdatedType()) or only the last message // per each viewId value matters (see isUpdatedTypePerViewId()), so instead of using push model diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index a919dbcf4267..3ad89b37416c 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -2578,7 +2578,7 @@ void DesktopLOKTest::testCommentsAddEditDeleteDraw() tools::JsonWriter aJson; addParameter(aJson, "Text", "string", "Comment"); addParameter(aJson, "Author", "string", "LOK User1"); - aCommandArgs = aJson.extractAsOString(); + aCommandArgs = aJson.finishAndGetAsOString(); } pDocument->pClass->postUnoCommand(pDocument, ".uno:InsertAnnotation", aCommandArgs.getStr(), false); @@ -2593,7 +2593,7 @@ void DesktopLOKTest::testCommentsAddEditDeleteDraw() tools::JsonWriter aJson; addParameter(aJson, "Id", "string", OString::number(nCommentId1)); addParameter(aJson, "Text", "string", "Edited comment"); - aCommandArgs = aJson.extractAsOString(); + aCommandArgs = aJson.finishAndGetAsOString(); } pDocument->pClass->postUnoCommand(pDocument, ".uno:EditAnnotation", aCommandArgs.getStr(), false); @@ -2607,7 +2607,7 @@ void DesktopLOKTest::testCommentsAddEditDeleteDraw() { tools::JsonWriter aJson; addParameter(aJson, "Id", "string", OString::number(nCommentId1)); - aCommandArgs = aJson.extractAsOString(); + aCommandArgs = aJson.finishAndGetAsOString(); } pDocument->pClass->postUnoCommand(pDocument, ".uno:DeleteAnnotation", aCommandArgs.getStr(), false); Scheduler::ProcessEventsToIdle(); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index ba1deeee2eae..17ab7b487398 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -517,29 +517,29 @@ static void unoAnyToJson(tools::JsonWriter& rJson, const char * pNodeName, const } } -static int lcl_getViewId(const std::string& payload); +static int lcl_getViewId(std::string_view payload); namespace desktop { -RectangleAndPart RectangleAndPart::Create(const std::string& rPayload) +RectangleAndPart RectangleAndPart::Create(const OString& rPayload) { RectangleAndPart aRet; - if (rPayload.compare(0, 5, "EMPTY") == 0) // payload starts with "EMPTY" + if (rPayload.startsWith("EMPTY")) // payload starts with "EMPTY" { aRet.m_aRectangle = tools::Rectangle(0, 0, SfxLokHelper::MaxTwips, SfxLokHelper::MaxTwips); if (comphelper::LibreOfficeKit::isPartInInvalidation()) { - int nSeparatorPos = rPayload.find(',', 6); + int nSeparatorPos = rPayload.indexOf(',', 6); bool bHasMode = nSeparatorPos > 0; if (bHasMode) { - aRet.m_nPart = std::stol(rPayload.substr(6, nSeparatorPos - 6)); - assert(rPayload.length() > o3tl::make_unsigned(nSeparatorPos)); - aRet.m_nMode = std::stol(rPayload.substr(nSeparatorPos + 1)); + aRet.m_nPart = o3tl::toInt32(rPayload.subView(6, nSeparatorPos - 6)); + assert(rPayload.getLength() > nSeparatorPos); + aRet.m_nMode = o3tl::toInt32(rPayload.subView(nSeparatorPos + 1)); } else { - aRet.m_nPart = std::stol(rPayload.substr(6)); + aRet.m_nPart = o3tl::toInt32(rPayload.subView(6)); aRet.m_nMode = 0; } } @@ -548,8 +548,8 @@ RectangleAndPart RectangleAndPart::Create(const std::string& rPayload) } // Read '<left>, <top>, <width>, <height>[, <part>, <mode>]'. C++ streams are simpler but slower. - const char* pos = rPayload.c_str(); - const char* end = rPayload.c_str() + rPayload.size(); + const char* pos = rPayload.getStr(); + const char* end = rPayload.getStr() + rPayload.getLength(); tools::Long nLeft = rtl_str_toInt64_WithLength(pos, 10, end - pos); while( *pos != ',' ) ++pos; @@ -622,9 +622,9 @@ tools::Rectangle RectangleAndPart::SanitizedRectangle(const tools::Rectangle& re return SanitizedRectangle(rect.Left(), rect.Top(), rect.getOpenWidth(), rect.getOpenHeight()); } -const std::string& CallbackFlushHandler::CallbackData::getPayload() const +const OString& CallbackFlushHandler::CallbackData::getPayload() const { - if(PayloadString.empty()) + if(PayloadString.isEmpty()) { // Do to-string conversion on demand, as many calls will get dropped without // needing the string. @@ -667,7 +667,7 @@ void CallbackFlushHandler::CallbackData::setJson(const boost::property_tree::ptr std::stringstream aJSONStream; constexpr bool bPretty = false; // Don't waste time and bloat logs. boost::property_tree::write_json(aJSONStream, rTree, bPretty); - PayloadString = boost::trim_copy(aJSONStream.str()); + PayloadString = OString(o3tl::trim(aJSONStream.str())); PayloadObject = rTree; } @@ -706,7 +706,7 @@ bool CallbackFlushHandler::CallbackData::validate() const std::stringstream aJSONStream; boost::property_tree::write_json(aJSONStream, getJson(), false); const std::string aExpected = boost::trim_copy(aJSONStream.str()); - return aExpected == getPayload(); + return getPayload() == std::string_view(aExpected); } // View id. @@ -764,7 +764,7 @@ static bool isUpdatedTypePerViewId(int type) } } -static int lcl_getViewId(const std::string& payload) +static int lcl_getViewId(std::string_view payload) { // this is a cheap way how to get the viewId from a JSON message; proper // parsing is terribly expensive, and we just need the viewId here @@ -783,7 +783,7 @@ static int lcl_getViewId(const std::string& payload) } if (numberPos < payload.length() && payload[numberPos] >= '0' && payload[numberPos] <= '9') - return strtol(payload.substr(numberPos).c_str(), nullptr, 10); + return o3tl::toInt32(payload.substr(numberPos)); return 0; } @@ -1597,13 +1597,13 @@ void CallbackFlushHandler::resetUpdatedTypePerViewId( int nType, int nViewId ) } } -void CallbackFlushHandler::libreOfficeKitViewCallback(int nType, const char* pPayload) +void CallbackFlushHandler::libreOfficeKitViewCallback(int nType, const OString& pPayload) { CallbackData callbackData(pPayload); queue(nType, callbackData); } -void CallbackFlushHandler::libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) +void CallbackFlushHandler::libreOfficeKitViewCallbackWithViewId(int nType, const OString& pPayload, int nViewId) { CallbackData callbackData(pPayload, nViewId); queue(nType, callbackData); @@ -1654,7 +1654,7 @@ void CallbackFlushHandler::libreOfficeKitViewAddPendingInvalidateTiles() startTimer(); } -void CallbackFlushHandler::queue(const int type, const char* data) +void CallbackFlushHandler::queue(const int type, const OString& data) { CallbackData callbackData(data); queue(type, callbackData); @@ -1709,9 +1709,9 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) // Suppress invalid payloads. if (type == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR && - aCallbackData.getPayload().find(", 0, 0, ") != std::string::npos && - aCallbackData.getPayload().find("\"hyperlink\":\"\"") == std::string::npos && - aCallbackData.getPayload().find("\"hyperlink\": {}") == std::string::npos) + aCallbackData.getPayload().indexOf(", 0, 0, ") != -1 && + aCallbackData.getPayload().indexOf("\"hyperlink\":\"\"") == -1 && + aCallbackData.getPayload().indexOf("\"hyperlink\": {}") == -1) { // The cursor position is often the relative coordinates of the widget // issuing it, instead of the absolute one that we expect. @@ -1843,8 +1843,8 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) // deleting the duplicate of visible cursor message can cause hyperlink popup not to show up on second/or more click on the same place. // If the hyperlink is not empty we can bypass that to show the popup const bool hyperLinkException = type == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR && - aCallbackData.getPayload().find("\"hyperlink\":\"\"") == std::string::npos && - aCallbackData.getPayload().find("\"hyperlink\": {}") == std::string::npos; + aCallbackData.getPayload().indexOf("\"hyperlink\":\"\"") == -1 && + aCallbackData.getPayload().indexOf("\"hyperlink\": {}") == -1; if(!hyperLinkException) { const int nViewId = aCallbackData.getViewId(); @@ -1866,16 +1866,16 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) case LOK_CALLBACK_STATE_CHANGED: { // Compare the state name=value and overwrite earlier entries with same name. - const auto pos = aCallbackData.getPayload().find('='); - if (pos != std::string::npos) + const auto pos = aCallbackData.getPayload().indexOf('='); + if (pos != -1) { - const std::string name = aCallbackData.getPayload().substr(0, pos + 1); + const std::string_view name = aCallbackData.getPayload().subView(0, pos + 1); // This is needed because otherwise it creates some problems when // a save occurs while a cell is still edited in Calc. if (name != ".uno:ModifiedStatus=") { removeAll(type, [&name] (const CallbackData& elemData) { - return (elemData.getPayload().compare(0, name.size(), name) == 0); + return elemData.getPayload().startsWith(name); } ); } @@ -1893,7 +1893,7 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) // remove only selection ranges and 'EMPTY' messages // always send 'INPLACE' and 'INPLACE EXIT' messages removeAll(type, [] (const CallbackData& elemData) - { return (elemData.getPayload().find("INPLACE") == std::string::npos); }); + { return (elemData.getPayload().indexOf("INPLACE") == -1); }); } break; } @@ -2055,9 +2055,9 @@ bool CallbackFlushHandler::processInvalidateTilesEvent(int type, CallbackData& a bool CallbackFlushHandler::processWindowEvent(int type, CallbackData& aCallbackData) { - const std::string& payload = aCallbackData.getPayload(); + const OString& payload = aCallbackData.getPayload(); - boost::property_tree::ptree& aTree = aCallbackData.setJson(payload); + boost::property_tree::ptree& aTree = aCallbackData.setJson(payload.getStr()); const unsigned nLOKWindowId = aTree.get<unsigned>("id", 0); const std::string aAction = aTree.get<std::string>("action", ""); if (aAction == "invalidate") @@ -2299,7 +2299,7 @@ void CallbackFlushHandler::enqueueUpdatedType( int type, const SfxViewShell* vie std::optional<OString> payload = viewShell->getLOKPayload( type, viewId ); if(!payload) return; // No actual payload to send. - CallbackData callbackData(payload->getStr(), viewId); + CallbackData callbackData(*payload, viewId); m_queue1.emplace_back(type); m_queue2.emplace_back(callbackData); SAL_INFO("lok", "Queued updated [" << type << "]: [" << callbackData.getPayload() @@ -2341,13 +2341,13 @@ void CallbackFlushHandler::Invoke() // common code-path for events on this view: if (viewId == -1) { - size_t idx; + sal_Int32 idx; // key-value pairs if (type == LOK_CALLBACK_STATE_CHANGED && - (idx = payload.find('=')) != std::string::npos) + (idx = payload.indexOf('=')) != -1) { - std::string key = payload.substr(0, idx); - std::string value = payload.substr(idx+1); + OString key = payload.copy(0, idx); + OString value = payload.copy(idx+1); const auto stateIt = m_lastStateChange.find(key); if (stateIt != m_lastStateChange.end()) { @@ -2409,7 +2409,7 @@ void CallbackFlushHandler::Invoke() } } - m_pCallback(type, payload.c_str(), m_pData); + m_pCallback(type, payload.getStr(), m_pData); } m_queue1.clear(); @@ -4357,7 +4357,7 @@ static char* getPostIts(LibreOfficeKitDocument* pThis) } tools::JsonWriter aJsonWriter; pDoc->getPostIts(aJsonWriter); - return aJsonWriter.extractData(); + return strdup(aJsonWriter.finishAndGetAsOString().getStr()); } /// Returns the JSON representation of the positions of all the comments in the document @@ -4372,7 +4372,7 @@ static char* getPostItsPos(LibreOfficeKitDocument* pThis) } tools::JsonWriter aJsonWriter; pDoc->getPostItsPos(aJsonWriter); - return aJsonWriter.extractData(); + return strdup(aJsonWriter.finishAndGetAsOString().getStr()); } static char* getRulerState(LibreOfficeKitDocument* pThis) @@ -4386,7 +4386,7 @@ static char* getRulerState(LibreOfficeKitDocument* pThis) } tools::JsonWriter aJsonWriter; pDoc->getRulerState(aJsonWriter); - return aJsonWriter.extractData(); + return strdup(aJsonWriter.finishAndGetAsOString().getStr()); } static void doc_postKeyEvent(LibreOfficeKitDocument* pThis, int nType, int nCharCode, int nKeyCode) @@ -4635,7 +4635,7 @@ public: } unoAnyToJson(aJson, "result", rEvent.Result); - mpCallback->queue(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.extractData()); + mpCallback->queue(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); } virtual void SAL_CALL disposing(const css::lang::EventObject&) override {} @@ -4829,7 +4829,7 @@ static void doc_postUnoCommand(LibreOfficeKitDocument* pThis, const char* pComma tools::JsonWriter aJson; aJson.put("commandName", pCommand); aJson.put("success", bResult); - pDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.extractData()); + pDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); return; } @@ -4867,7 +4867,7 @@ static void doc_postUnoCommand(LibreOfficeKitDocument* pThis, const char* pComma aJson.put("type", "string"); aJson.put("value", "unmodified"); } - pDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.extractData()); + pDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); return; } } @@ -6049,7 +6049,7 @@ static char* getTrackedChanges(LibreOfficeKitDocument* pThis) pDoc->getTrackedChanges(aJson); } - return aJson.extractData(); + return strdup(aJson.finishAndGetAsOString().getStr()); } @@ -6064,7 +6064,7 @@ static char* getTrackedChangeAuthors(LibreOfficeKitDocument* pThis) } tools::JsonWriter aJsonWriter; pDoc->getTrackedChangeAuthors(aJsonWriter); - return aJsonWriter.extractData(); + return strdup(aJsonWriter.finishAndGetAsOString().getStr()); } static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCommand) @@ -6170,7 +6170,7 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo tools::JsonWriter aJsonWriter; pDoc->getRowColumnHeaders(aRectangle, aJsonWriter); - return aJsonWriter.extractData(); + return strdup(aJsonWriter.finishAndGetAsOString().getStr()); } else if (o3tl::starts_with(aCommand, aSheetGeometryData)) { @@ -6236,7 +6236,7 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo // Ignore command's deprecated parameters. tools::JsonWriter aJsonWriter; pDoc->getCellCursor(aJsonWriter); - return aJsonWriter.extractData(); + return strdup(aJsonWriter.finishAndGetAsOString().getStr()); } else if (o3tl::starts_with(aCommand, aFontSubset)) { @@ -6246,7 +6246,7 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo { tools::JsonWriter aJsonWriter; pDoc->getCommandValues(aJsonWriter, aCommand); - return aJsonWriter.extractData(); + return strdup(aJsonWriter.finishAndGetAsOString().getStr()); } else { @@ -7011,7 +7011,7 @@ static char* lo_getFilterTypes(LibreOfficeKit* pThis) } } - return aJson.extractData(); + return strdup(aJson.finishAndGetAsOString().getStr()); } static void lo_setOptionalFeatures(LibreOfficeKit* pThis, unsigned long long const features) diff --git a/desktop/source/lib/lokinteractionhandler.cxx b/desktop/source/lib/lokinteractionhandler.cxx index 09ee2aaa9f90..ec3d2e365c45 100644 --- a/desktop/source/lib/lokinteractionhandler.cxx +++ b/desktop/source/lib/lokinteractionhandler.cxx @@ -120,9 +120,9 @@ void LOKInteractionHandler::postError(css::task::InteractionClassification class std::size_t nView = SfxViewShell::Current() ? SfxLokHelper::getView() : 0; if (m_pLOKDocument && m_pLOKDocument->mpCallbackFlushHandlers.count(nView)) - m_pLOKDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_ERROR, aJson.extractAsOString().getStr()); + m_pLOKDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_ERROR, aJson.finishAndGetAsOString()); else if (m_pLOKit->mpCallback) - m_pLOKit->mpCallback(LOK_CALLBACK_ERROR, aJson.extractAsOString().getStr(), m_pLOKit->mpCallbackData); + m_pLOKit->mpCallback(LOK_CALLBACK_ERROR, aJson.finishAndGetAsOString().getStr(), m_pLOKit->mpCallbackData); } namespace { diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx index 5edf811c59ee..7622138271ee 100644 --- a/include/editeng/outliner.hxx +++ b/include/editeng/outliner.hxx @@ -369,8 +369,8 @@ public: class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI OutlinerViewShell { public: - virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) const = 0; - virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) const = 0; + virtual void libreOfficeKitViewCallback(int nType, const OString& pPayload) const = 0; + virtual void libreOfficeKitViewCallbackWithViewId(int nType, const OString& pPayload, int nViewId) const = 0; virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart, int nMode) const = 0; virtual void libreOfficeKitViewUpdatedCallback(int nType) const = 0; virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) const = 0; diff --git a/include/sfx2/lokcallback.hxx b/include/sfx2/lokcallback.hxx index 02546b8b4d22..6da464e904a7 100644 --- a/include/sfx2/lokcallback.hxx +++ b/include/sfx2/lokcallback.hxx @@ -13,6 +13,7 @@ namespace rtl { +class OString; class OStringBuffer; } namespace tools @@ -32,9 +33,10 @@ class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI SfxLokCallbackInterface public: virtual ~SfxLokCallbackInterface() {} // LibreOfficeKitCallback equivalent. - virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) = 0; + virtual void libreOfficeKitViewCallback(int nType, const rtl::OString& pPayload) = 0; // Callback that explicitly provides view id (which is also included in the payload). - virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) + virtual void libreOfficeKitViewCallbackWithViewId(int nType, const rtl::OString& pPayload, + int nViewId) = 0; // LOK_CALLBACK_INVALIDATE_TILES // nPart is either part, -1 for all-parts, or INT_MIN if diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index de24ef3ef3c1..8589b9b0751b 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -370,8 +370,8 @@ public: /// dump view state for diagnostics void dumpLibreOfficeKitViewState(rtl::OStringBuffer &rState); /// Invokes the registered callback, if there are any. - virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) const override; - virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) const override; + virtual void libreOfficeKitViewCallback(int nType, const OString& pPayload) const override; + virtual void libreOfficeKitViewCallbackWithViewId(int nType, const OString& pPayload, int nViewId) const override; virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart, int nMode) const override; virtual void libreOfficeKitViewUpdatedCallback(int nType) const override; virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) const override; diff --git a/include/test/lokcallback.hxx b/include/test/lokcallback.hxx index 1908838a6cdf..bba7a392ae2d 100644 --- a/include/test/lokcallback.hxx +++ b/include/test/lokcallback.hxx @@ -31,8 +31,8 @@ public: void clear(); /// Set the view id of the associated SfxViewShell. void setLOKViewId(int viewId) { m_viewId = viewId; } - virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) override; - virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, + virtual void libreOfficeKitViewCallback(int nType, const rtl::OString& pPayload) override; + virtual void libreOfficeKitViewCallbackWithViewId(int nType, const rtl::OString& pPayload, int nViewId) override; virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart, int nMode) override; diff --git a/include/tools/json_writer.hxx b/include/tools/json_writer.hxx index d0c057bc63bc..47418c87cb40 100644 --- a/include/tools/json_writer.hxx +++ b/include/tools/json_writer.hxx @@ -42,6 +42,7 @@ class TOOLS_DLLPUBLIC JsonWriter int mSpaceAllocated; int mStartNodeCount; bool mbFirstFieldInNode; + bool mbClosed; // cannot add to it anymore public: JsonWriter(); @@ -75,11 +76,9 @@ public: /// This assumes that this data belongs at this point in the stream, and is valid, and properly encoded void putRaw(std::string_view); - /** Hands ownership of the underlying storage buffer to the caller, - * after this no more document modifications may be written. */ - char* extractData() { return extractDataImpl().first; } - OString extractAsOString(); - std::string extractAsStdString(); + /** Closes the tags, and returns data. + * After this no more document modifications may be written. */ + OString finishAndGetAsOString(); /** returns true if the current JSON data matches the string */ bool isDataEquals(std::string_view) const; @@ -90,7 +89,7 @@ private: void endStruct(); void addCommaBeforeField(); void writeEscapedOUString(const OUString& rPropVal); - std::pair<char*, int> extractDataImpl(); + void closeDocument(); void ensureSpace(int noMoreBytesRequired); void ensureSpaceAndWriteNameColon(std::string_view name, int valSize); void putLiteral(std::string_view propName, std::string_view propValue); diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx index d280aad3f006..49e22c3c5357 100644 --- a/include/vcl/IDialogRenderable.hxx +++ b/include/vcl/IDialogRenderable.hxx @@ -38,7 +38,7 @@ public: const OUString& rAction, const std::vector<LOKPayloadItem>& rPayload = std::vector<LOKPayloadItem>()) const = 0; - virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) const = 0; + virtual void libreOfficeKitViewCallback(int nType, const OString& pPayload) const = 0; /// Emits a LOK_CALLBACK_INVALIDATE_TILES. virtual void notifyInvalidation(tools::Rectangle const *) const = 0; diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx index eacf9e779b5e..d153180e8873 100644 --- a/include/vcl/svapp.hxx +++ b/include/vcl/svapp.hxx @@ -1364,7 +1364,7 @@ public: virtual void notifyWindow(vcl::LOKWindowId nLOKWindowId, const OUString& rAction, const std::vector<vcl::LOKPayloadItem>& rPayload = std::vector<vcl::LOKPayloadItem>()) const override; - virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) const override; + virtual void libreOfficeKitViewCallback(int nType, const OString& pPayload) const override; virtual void notifyInvalidation(tools::Rectangle const *) const override; diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index 9d5d129e4987..3e6accfe2c4b 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -1825,7 +1825,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testGetRowColumnHeadersInvalidation) aView1.m_aInvalidations.clear(); tools::JsonWriter aJsonWriter1; pModelObj->getRowColumnHeaders(tools::Rectangle(0, 15, 19650, 5400), aJsonWriter1); - free(aJsonWriter1.extractData()); + aJsonWriter1.finishAndGetAsOString(); Scheduler::ProcessEventsToIdle(); CPPUNIT_ASSERT(aView1.m_bInvalidateTiles); CPPUNIT_ASSERT_EQUAL(size_t(1), aView1.m_aInvalidations.size()); @@ -1836,7 +1836,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testGetRowColumnHeadersInvalidation) aView1.m_aInvalidations.clear(); tools::JsonWriter aJsonWriter2; pModelObj->getRowColumnHeaders(tools::Rectangle(0, 5400, 19650, 9800), aJsonWriter2); - free(aJsonWriter2.extractData()); + aJsonWriter2.finishAndGetAsOString(); Scheduler::ProcessEventsToIdle(); CPPUNIT_ASSERT(aView1.m_bInvalidateTiles); CPPUNIT_ASSERT_EQUAL(size_t(1), aView1.m_aInvalidations.size()); @@ -1847,7 +1847,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testGetRowColumnHeadersInvalidation) aView1.m_aInvalidations.clear(); tools::JsonWriter aJsonWriter3; pModelObj->getRowColumnHeaders(tools::Rectangle(5400, 5400, 25050, 9800), aJsonWriter3); - free(aJsonWriter3.extractData()); + aJsonWriter3.finishAndGetAsOString(); Scheduler::ProcessEventsToIdle(); CPPUNIT_ASSERT(aView1.m_bInvalidateTiles); CPPUNIT_ASSERT_EQUAL(size_t(1), aView1.m_aInvalidations.size()); @@ -1921,7 +1921,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testRowColumnHeaders) SfxLokHelper::setView(nView1); tools::JsonWriter aJsonWriter1; pModelObj->getRowColumnHeaders(tools::Rectangle(65,723,10410,4695), aJsonWriter1); - OString aHeaders1 = aJsonWriter1.extractAsOString(); + OString aHeaders1 = aJsonWriter1.finishAndGetAsOString(); SfxLokHelper::setView(nView2); // 50% zoom @@ -1929,20 +1929,20 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testRowColumnHeaders) pModelObj->setClientZoom(256, 256, 6636, 6636); tools::JsonWriter aJsonWriter2; pModelObj->getRowColumnHeaders(tools::Rectangle(65,723,10410,4695), aJsonWriter2); - OString aHeaders2 = aJsonWriter2.extractAsOString(); + OString aHeaders2 = aJsonWriter2.finishAndGetAsOString(); // Check vs. view #1 SfxLokHelper::setView(nView1); tools::JsonWriter aJsonWriter3; pModelObj->getRowColumnHeaders(tools::Rectangle(65,723,10410,4695), aJsonWriter3); - OString aHeaders1_2 = aJsonWriter3.extractAsOString(); + OString aHeaders1_2 = aJsonWriter3.finishAndGetAsOString(); CPPUNIT_ASSERT_EQUAL(aHeaders1, aHeaders1_2); // Check vs. view #2 SfxLokHelper::setView(nView2); tools::JsonWriter aJsonWriter4; pModelObj->getRowColumnHeaders(tools::Rectangle(65,723,10410,4695), aJsonWriter4); - OString aHeaders2_2 = aJsonWriter4.extractAsOString(); + OString aHeaders2_2 = aJsonWriter4.finishAndGetAsOString(); CPPUNIT_ASSERT_EQUAL(aHeaders2, aHeaders2_2); SfxLokHelper::setView(nView1); diff --git a/sc/source/ui/undo/undotab.cxx b/sc/source/ui/undo/undotab.cxx index 12d813c7da6c..4237aab46358 100644 --- a/sc/source/ui/undo/undotab.cxx +++ b/sc/source/ui/undo/undotab.cxx @@ -1331,8 +1331,8 @@ void ScUndoPrintRange::DoChange(bool bUndo) else pNewRanges->GetPrintRangesInfo(aJsonWriter); - const std::string message = aJsonWriter.extractAsStdString(); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_PRINT_RANGES, message.c_str()); + const OString message = aJsonWriter.finishAndGetAsOString(); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_PRINT_RANGES, message); } pDocShell->PostPaint( ScRange(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab), PaintPartFlags::Grid ); diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx index ec0458b8e19a..298a54d9ae01 100644 --- a/sc/source/ui/view/viewfun2.cxx +++ b/sc/source/ui/view/viewfun2.cxx @@ -1136,8 +1136,8 @@ void ScViewFunc::SetPrintRanges( bool bEntireSheet, const OUString* pPrint, pNewRanges->GetPrintRangesInfo(aJsonWriter); SfxViewShell* pViewShell = GetViewData().GetViewShell(); - const std::string message = aJsonWriter.extractAsStdString(); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_PRINT_RANGES, message.c_str()); + const OString message = aJsonWriter.finishAndGetAsOString(); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_PRINT_RANGES, message); } pDocSh->GetUndoManager()->AddUndoAction( diff --git a/sd/source/core/annotations/Annotation.cxx b/sd/source/core/annotations/Annotation.cxx index 991412f063d5..850f1a973ff1 100644 --- a/sd/source/core/annotations/Annotation.cxx +++ b/sd/source/core/annotations/Annotation.cxx @@ -340,7 +340,7 @@ const SdPage* getAnnotationPage(const uno::Reference<office::XAnnotation>& xAnno namespace { -std::string lcl_LOKGetCommentPayload(CommentNotificationType nType, uno::Reference<office::XAnnotation> const & rxAnnotation) +OString lcl_LOKGetCommentPayload(CommentNotificationType nType, uno::Reference<office::XAnnotation> const & rxAnnotation) { ::tools::JsonWriter aJsonWriter; { @@ -368,7 +368,7 @@ std::string lcl_LOKGetCommentPayload(CommentNotificationType nType, uno::Referen aJsonWriter.put("rectangle", sRectangle.getStr()); } } - return aJsonWriter.extractData(); + return aJsonWriter.finishAndGetAsOString(); } } // anonymous ns @@ -378,8 +378,8 @@ void LOKCommentNotify(CommentNotificationType nType, const SfxViewShell* pViewSh if (!comphelper::LibreOfficeKit::isActive() || comphelper::LibreOfficeKit::isTiledAnnotations()) return ; - std::string aPayload = lcl_LOKGetCommentPayload(nType, rxAnnotation); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload.c_str()); + OString aPayload = lcl_LOKGetCommentPayload(nType, rxAnnotation); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload); } void LOKCommentNotifyAll(CommentNotificationType nType, uno::Reference<office::XAnnotation> const & rxAnnotation) @@ -388,12 +388,12 @@ void LOKCommentNotifyAll(CommentNotificationType nType, uno::Reference<office::X if (!comphelper::LibreOfficeKit::isActive() || comphelper::LibreOfficeKit::isTiledAnnotations()) return ; - std::string aPayload = lcl_LOKGetCommentPayload(nType, rxAnnotation); + OString aPayload = lcl_LOKGetCommentPayload(nType, rxAnnotation); const SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell) { - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload.c_str()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload); pViewShell = SfxViewShell::GetNext(*pViewShell); } } diff --git a/sfx2/source/control/unoctitm.cxx b/sfx2/source/control/unoctitm.cxx index e329e746881e..bb2510a89435 100644 --- a/sfx2/source/control/unoctitm.cxx +++ b/sfx2/source/control/unoctitm.cxx @@ -542,7 +542,7 @@ void SfxDispatchController_Impl::dispatch( const css::util::URL& aURL, aTree.put("message", "Blocked feature"); aTree.put("viewID", SfxViewShell::Current()->GetViewShellId().get()); - SfxViewShell::Current()->libreOfficeKitViewCallback(LOK_COMMAND_BLOCKED, aTree.extractData()); + SfxViewShell::Current()->libreOfficeKitViewCallback(LOK_COMMAND_BLOCKED, aTree.finishAndGetAsOString()); return; } diff --git a/sfx2/source/sidebar/SidebarController.cxx b/sfx2/source/sidebar/SidebarController.cxx index 703c5020635a..1bd5dc58ee86 100644 --- a/sfx2/source/sidebar/SidebarController.cxx +++ b/sfx2/source/sidebar/SidebarController.cxx @@ -1233,8 +1233,7 @@ void SidebarController::RequestCloseDeck() aJsonWriter.put("type", "dockingwindow"); aJsonWriter.put("text", mpParentWindow->GetText()); aJsonWriter.put("enabled", false); - const std::string message = aJsonWriter.extractAsStdString(); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.c_str()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, aJsonWriter.finishAndGetAsOString()); } else if (pViewShell) { @@ -1242,8 +1241,7 @@ void SidebarController::RequestCloseDeck() aJsonWriter.put("id", mpParentWindow->get_id()); aJsonWriter.put("action", "close"); aJsonWriter.put("jsontype", "sidebar"); - const std::string message = aJsonWriter.extractAsStdString(); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.c_str()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, aJsonWriter.finishAndGetAsOString()); } } diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx index b4e94994f9ee..911629bb8e30 100644 --- a/sfx2/source/view/viewsh.cxx +++ b/sfx2/source/view/viewsh.cxx @@ -1484,7 +1484,7 @@ void SfxViewShell::libreOfficeKitViewInvalidateTilesCallback(const tools::Rectan "SfxViewShell::libreOfficeKitViewInvalidateTilesCallback no callback set!"); } -void SfxViewShell::libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) const +void SfxViewShell::libreOfficeKitViewCallbackWithViewId(int nType, const OString& pPayload, int nViewId) const { if (ignoreLibreOfficeKitViewCallback(nType, pImpl.get())) return; @@ -1497,7 +1497,7 @@ void SfxViewShell::libreOfficeKitViewCallbackWithViewId(int nType, const char* p << lokCallbackTypeToString(nType) << ": [" << pPayload << ']'); } -void SfxViewShell::libreOfficeKitViewCallback(int nType, const char* pPayload) const +void SfxViewShell::libreOfficeKitViewCallback(int nType, const OString& pPayload) const { if (ignoreLibreOfficeKitViewCallback(nType, pImpl.get())) return; diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx index 9f399cfc3452..adbdb7dfeddb 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -1756,7 +1756,7 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testRedlineColors) // Assert that info about exactly one author is returned. tools::JsonWriter aJsonWriter; pXTextDocument->getTrackedChangeAuthors(aJsonWriter); - std::stringstream aStream(aJsonWriter.extractAsOString().getStr()); + std::stringstream aStream(aJsonWriter.finishAndGetAsOString().getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aTree.get_child("authors").size()); diff --git a/sw/qa/extras/uiwriter/uiwriter5.cxx b/sw/qa/extras/uiwriter/uiwriter5.cxx index 791ed35ae3b4..aeb357f1b619 100644 --- a/sw/qa/extras/uiwriter/uiwriter5.cxx +++ b/sw/qa/extras/uiwriter/uiwriter5.cxx @@ -1215,9 +1215,8 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testImageComment) // rendering and on the desktop. tools::JsonWriter aJsonWriter; pTextDoc->getPostIts(aJsonWriter); - char* pChar = aJsonWriter.extractData(); - std::stringstream aStream(pChar); - free(pChar); + OString pChar = aJsonWriter.finishAndGetAsOString(); + std::stringstream aStream(pChar.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("comments")) diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx b/sw/qa/extras/uiwriter/uiwriter6.cxx index 8a90c395a570..cd9253172981 100644 --- a/sw/qa/extras/uiwriter/uiwriter6.cxx +++ b/sw/qa/extras/uiwriter/uiwriter6.cxx @@ -1481,9 +1481,8 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf65535) tools::JsonWriter aJsonWriter; pTextDoc->getPostIts(aJsonWriter); - char* pChar = aJsonWriter.extractData(); - std::stringstream aStream(pChar); - free(pChar); + OString pChar = aJsonWriter.finishAndGetAsOString(); + std::stringstream aStream(pChar.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); OString sCommentText; diff --git a/sw/qa/extras/uiwriter/uiwriter8.cxx b/sw/qa/extras/uiwriter/uiwriter8.cxx index e6a362484cf4..af839114f9b3 100644 --- a/sw/qa/extras/uiwriter/uiwriter8.cxx +++ b/sw/qa/extras/uiwriter/uiwriter8.cxx @@ -1634,9 +1634,8 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf132603) tools::JsonWriter aJsonWriter; pTextDoc->getPostIts(aJsonWriter); - char* pChar = aJsonWriter.extractData(); - std::stringstream aStream(pChar); - free(pChar); + OString pChar = aJsonWriter.finishAndGetAsOString(); + std::stringstream aStream(pChar.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("comments")) diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx index 7a1b731634bd..1336fb39ee6c 100644 --- a/sw/qa/uibase/uno/uno.cxx +++ b/sw/qa/uibase/uno/uno.cxx @@ -234,8 +234,8 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetTextFormFields) pXTextDocument->getCommandValues(aJsonWriter, aCommand); // Then make sure we find the 2 items and ignore the bibliography: - std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData()); - std::stringstream aStream(pJSON.get()); + OString pJSON(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(pJSON.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); // Without the accompanying fix in place, this test would have failed with: @@ -267,8 +267,8 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetDocumentProperties) pXTextDocument->getCommandValues(aJsonWriter, aCommand); // Then make sure we find the 2 properties and ignore the other one: - std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData()); - std::stringstream aStream(pJSON.get()); + OString pJSON(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(pJSON.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); // Without the accompanying fix in place, this test would have failed with: @@ -308,8 +308,8 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetBookmarks) pXTextDocument->getCommandValues(aJsonWriter, aCommand); // Then make sure we get the 2 references but not the bibliography: - std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData()); - std::stringstream aStream(pJSON.get()); + OString pJSON(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(pJSON.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); // Without the accompanying fix in place, this test would have failed with: @@ -345,8 +345,8 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetFields) pXTextDocument->getCommandValues(aJsonWriter, aCommand); // Then make sure we get the 1 refmark: - std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData()); - std::stringstream aStream(pJSON.get()); + OString pJSON(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(pJSON.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); // Without the accompanying fix in place, this test would have failed with: @@ -400,8 +400,8 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetTextFormField) pXTextDocument->getCommandValues(aJsonWriter, aCommand); // Then make sure we find the inserted fieldmark: - std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData()); - std::stringstream aStream(pJSON.get()); + OString pJSON(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(pJSON.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); // Without the accompanying fix in place, this test would have failed with: @@ -432,8 +432,8 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetSections) pXTextDocument->getCommandValues(aJsonWriter, aCommand); // Make sure we find our just inserted section: - std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData()); - std::stringstream aStream(pJSON.get()); + OString pJSON(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(pJSON.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); // Without the accompanying fix in place, this test would have failed with: @@ -464,8 +464,8 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetBookmark) pXTextDocument->getCommandValues(aJsonWriter, aCommand); // Then make sure we find the inserted bookmark: - std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData()); - std::stringstream aStream(pJSON.get()); + OString pJSON(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(pJSON.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); boost::property_tree::ptree aBookmark = aTree.get_child("bookmark"); @@ -498,8 +498,8 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetField) pXTextDocument->getCommandValues(aJsonWriter, aCommand); // Then make sure we find the inserted refmark: - std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData()); - std::stringstream aStream(pJSON.get()); + OString pJSON(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(pJSON.getStr()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); boost::property_tree::ptree aBookmark = aTree.get_child("setRef"); diff --git a/sw/source/core/crsr/bookmark.cxx b/sw/source/core/crsr/bookmark.cxx index faaec4b28377..8e29c521890d 100644 --- a/sw/source/core/crsr/bookmark.cxx +++ b/sw/source/core/crsr/bookmark.cxx @@ -438,7 +438,7 @@ namespace sw::mark aJson.put("DeleteBookmark", fieldCommand); } - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.extractData()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); } void Bookmark::InitDoc(SwDoc& io_rDoc, @@ -603,7 +603,7 @@ namespace sw::mark aJson.put("DeleteTextFormField", fieldCommand); } - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.extractData()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); } void TextFieldmark::InitDoc(SwDoc& io_rDoc, diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index b8dd11dc533f..95fc98b0e99a 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -2157,9 +2157,8 @@ void SwCursorShell::sendLOKCursorUpdates() } } - char* pChar = aJsonWriter.extractData(); + OString pChar = aJsonWriter.finishAndGetAsOString(); GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, pChar); - free(pChar); } void SwCursorShell::RefreshBlockCursor() diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx index dd4db78517a4..910ea2cc13aa 100644 --- a/sw/source/core/crsr/viscrs.cxx +++ b/sw/source/core/crsr/viscrs.cxx @@ -725,8 +725,8 @@ void SwSelPaintRects::HighlightContentControl() aJson.put("alias", pContentControl->GetAlias()); } - std::unique_ptr<char, o3tl::free_delete> pJson(aJson.extractData()); - GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CONTENT_CONTROL, pJson.get()); + OString pJson(aJson.finishAndGetAsOString()); + GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CONTENT_CONTROL, pJson); } if (m_pContentControlOverlay) { @@ -819,8 +819,8 @@ void SwSelPaintRects::HighlightContentControl() { tools::JsonWriter aJson; aJson.put("action", "hide"); - std::unique_ptr<char, o3tl::free_delete> pJson(aJson.extractData()); - GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CONTENT_CONTROL, pJson.get()); + OString pJson(aJson.finishAndGetAsOString()); + GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CONTENT_CONTROL, pJson); } m_pContentControlOverlay.reset(); diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx index c436bc9742c0..06a50c4de33b 100644 --- a/sw/source/core/docnode/nodes.cxx +++ b/sw/source/core/docnode/nodes.cxx @@ -2451,7 +2451,7 @@ void SwNodes::RemoveNode( SwNodeOffset nDelPos, SwNodeOffset nSz, bool bDel ) aJson.put("DeleteSection", fieldCommand); } - SfxViewShell::Current()->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.extractData()); + SfxViewShell::Current()->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); } } diff --git a/sw/source/core/txtnode/atrref.cxx b/sw/source/core/txtnode/atrref.cxx index 5e2306a8b27c..b93b62e7433a 100644 --- a/sw/source/core/txtnode/atrref.cxx +++ b/sw/source/core/txtnode/atrref.cxx @@ -138,7 +138,7 @@ SwTextRefMark::~SwTextRefMark() aJson.put("DeleteField", fieldCommand); } - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.extractData()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); } const sal_Int32* SwTextRefMark::GetEnd() const diff --git a/sw/source/uibase/misc/swruler.cxx b/sw/source/uibase/misc/swruler.cxx index 4166a754bf77..0ccdec2f46a5 100644 --- a/sw/source/uibase/misc/swruler.cxx +++ b/sw/source/uibase/misc/swruler.cxx @@ -284,10 +284,9 @@ void SwCommentRuler::NotifyKit() tools::JsonWriter aJsonWriter; CreateJsonNotification(aJsonWriter); - char* pJsonData = aJsonWriter.extractData(); + OString pJsonData = aJsonWriter.finishAndGetAsOString(); mpViewShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_RULER_UPDATE, pJsonData); - free(pJsonData); } void SwCommentRuler::Update() diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx b/sw/source/uibase/wrtsh/wrtsh3.cxx index 7167b0639bd9..0907794d7c2c 100644 --- a/sw/source/uibase/wrtsh/wrtsh3.cxx +++ b/sw/source/uibase/wrtsh/wrtsh3.cxx @@ -108,9 +108,9 @@ bool SwWrtShell::GotoContentControl(const SwFormatContentControl& rContentContro { tools::JsonWriter aJson; aJson.put("action", "change-picture"); - std::unique_ptr<char, o3tl::free_delete> pJson(aJson.extractData()); + OString pJson(aJson.finishAndGetAsOString()); GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CONTENT_CONTROL, - pJson.get()); + pJson); } else { diff --git a/test/source/lokcallback.cxx b/test/source/lokcallback.cxx index 323b263b7e76..c426d4fd17fd 100644 --- a/test/source/lokcallback.cxx +++ b/test/source/lokcallback.cxx @@ -47,15 +47,16 @@ inline void TestLokCallbackWrapper::callCallback(int nType, const char* pPayload startTimer(); } -void TestLokCallbackWrapper::libreOfficeKitViewCallback(int nType, const char* pPayload) +void TestLokCallbackWrapper::libreOfficeKitViewCallback(int nType, const rtl::OString& pPayload) { - callCallback(nType, pPayload, NO_VIEWID); + callCallback(nType, pPayload.getStr(), NO_VIEWID); } -void TestLokCallbackWrapper::libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, +void TestLokCallbackWrapper::libreOfficeKitViewCallbackWithViewId(int nType, + const rtl::OString& pPayload, int nViewId) { - callCallback(nType, pPayload, nViewId); + callCallback(nType, pPayload.getStr(), nViewId); } void TestLokCallbackWrapper::libreOfficeKitViewInvalidateTilesCallback( diff --git a/tools/qa/cppunit/test_json_writer.cxx b/tools/qa/cppunit/test_json_writer.cxx index 2e0706605745..b3d66fe92b03 100644 --- a/tools/qa/cppunit/test_json_writer.cxx +++ b/tools/qa/cppunit/test_json_writer.cxx @@ -43,11 +43,11 @@ void JsonWriterTest::test1() aJson.put("int", static_cast<sal_Int32>(12)); } - std::unique_ptr<char, o3tl::free_delete> result(aJson.extractData()); + OString result(aJson.finishAndGetAsOString()); - CPPUNIT_ASSERT_EQUAL(std::string("{ \"node\": { \"oustring\": \"val1\", " - "\"charptr\": \"val3\", \"int\": 12}}"), - std::string(result.get())); + CPPUNIT_ASSERT_EQUAL(OString("{ \"node\": { \"oustring\": \"val1\", " + "\"charptr\": \"val3\", \"int\": 12}}"), + result); } void JsonWriterTest::test2() @@ -69,12 +69,12 @@ void JsonWriterTest::test2() } } - std::unique_ptr<char, o3tl::free_delete> result(aJson.extractData()); + OString result(aJson.finishAndGetAsOString()); - CPPUNIT_ASSERT_EQUAL(std::string("{ \"node\": { \"field1\": \"val1\", \"field2\": \"val2\", " - "\"node\": { \"field3\": \"val3\", \"node\": { \"field4\": " - "\"val4\", \"field5\": \"val5\"}}}}"), - std::string(result.get())); + CPPUNIT_ASSERT_EQUAL(OString("{ \"node\": { \"field1\": \"val1\", \"field2\": \"val2\", " + "\"node\": { \"field3\": \"val3\", \"node\": { \"field4\": " + "\"val4\", \"field5\": \"val5\"}}}}"), + result); } void JsonWriterTest::testArray() @@ -86,10 +86,9 @@ void JsonWriterTest::testArray() aJson.putSimpleValue("bar"); } - std::unique_ptr<char, o3tl::free_delete> aResult(aJson.extractData()); + OString aResult(aJson.finishAndGetAsOString()); - CPPUNIT_ASSERT_EQUAL(std::string("{ \"items\": [ \"foo\", \"bar\"]}"), - std::string(aResult.get())); + CPPUNIT_ASSERT_EQUAL(OString("{ \"items\": [ \"foo\", \"bar\"]}"), aResult); } CPPUNIT_TEST_SUITE_REGISTRATION(JsonWriterTest); diff --git a/tools/source/misc/json_writer.cxx b/tools/source/misc/json_writer.cxx index c5e92385904b..e7a0f55fd6c2 100644 --- a/tools/source/misc/json_writer.cxx +++ b/tools/source/misc/json_writer.cxx @@ -24,6 +24,7 @@ JsonWriter::JsonWriter() , mSpaceAllocated(DEFAULT_BUFFER_SIZE) , mStartNodeCount(0) , mbFirstFieldInNode(true) + , mbClosed(false) { *mPos = '{'; ++mPos; @@ -35,7 +36,7 @@ JsonWriter::JsonWriter() JsonWriter::~JsonWriter() { - assert(!mpBuffer && "forgot to extract data?"); + assert(mbClosed && "forgot to extract data?"); free(mpBuffer); } @@ -314,7 +315,7 @@ void JsonWriter::addCommaBeforeField() void JsonWriter::ensureSpace(int noMoreBytesRequired) { - assert(mpBuffer && "already extracted data"); + assert(!mbClosed && "already extracted data"); int currentUsed = mPos - mpBuffer; if (currentUsed + noMoreBytesRequired >= mSpaceAllocated) { @@ -351,36 +352,19 @@ void JsonWriter::putLiteral(std::string_view propName, std::string_view propValu validate(); } -/** Hands ownership of the underlying storage buffer to the caller, - * after this no more document modifications may be written. */ -std::pair<char*, int> JsonWriter::extractDataImpl() +OString JsonWriter::finishAndGetAsOString() { assert(mStartNodeCount == 0 && "did not close all nodes"); - assert(mpBuffer && "data already extracted"); + assert(!mbClosed && "data already extracted"); ensureSpace(2); // add closing brace *mPos = '}'; ++mPos; // null-terminate *mPos = 0; - const int sz = mPos - mpBuffer; - mPos = nullptr; - return { std::exchange(mpBuffer, nullptr), sz }; -} - -OString JsonWriter::extractAsOString() -{ - auto[pChar, sz] = extractDataImpl(); - OString ret(pChar, sz); - free(pChar); - return ret; -} + mbClosed = true; -std::string JsonWriter::extractAsStdString() -{ - auto[pChar, sz] = extractDataImpl(); - std::string ret(pChar, sz); - free(pChar); + OString ret(mpBuffer, mPos - mpBuffer); return ret; } diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx b/vcl/inc/jsdialog/jsdialogbuilder.hxx index e8cc3451c6bd..27ac31784228 100644 --- a/vcl/inc/jsdialog/jsdialogbuilder.hxx +++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx @@ -111,7 +111,7 @@ class JSDialogNotifyIdle final : public Idle // used to generate JSON VclPtr<vcl::Window> m_aContentWindow; OUString m_sTypeOfJSON; - std::string m_LastNotificationMessage; + OString m_LastNotificationMessage; bool m_bForce; std::deque<JSDialogMessageInfo> m_aMessageQueue; diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx index 39da090326e9..a55242ffae58 100644 --- a/vcl/jsdialog/jsdialogbuilder.cxx +++ b/vcl/jsdialog/jsdialogbuilder.cxx @@ -71,7 +71,7 @@ void JSDialogNotifyIdle::send(tools::JsonWriter& aJsonWriter) { if (!m_aNotifierWindow) { - free(aJsonWriter.extractData()); + aJsonWriter.finishAndGetAsOString(); return; } @@ -81,18 +81,17 @@ void JSDialogNotifyIdle::send(tools::JsonWriter& aJsonWriter) if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage)) { m_bForce = false; - m_LastNotificationMessage = aJsonWriter.extractAsStdString(); - pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, - m_LastNotificationMessage.c_str()); + m_LastNotificationMessage = aJsonWriter.finishAndGetAsOString(); + pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, m_LastNotificationMessage); } else { - free(aJsonWriter.extractData()); + aJsonWriter.finishAndGetAsOString(); } } else { - free(aJsonWriter.extractData()); + aJsonWriter.finishAndGetAsOString(); } } @@ -1276,8 +1275,8 @@ JSInstanceBuilder::CreateMessageDialog(weld::Widget* pParent, VclMessageType eMe xMessageDialog->DumpAsPropertyTree(aJsonWriter); aJsonWriter.put("id", xMessageDialog->GetLOKWindowId()); aJsonWriter.put("jsontype", "dialog"); - std::unique_ptr<char[], o3tl::free_delete> message(aJsonWriter.extractData()); - pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.get()); + OString message(aJsonWriter.finishAndGetAsOString()); + pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message); OUString sWindowId = OUString::number(xMessageDialog->GetLOKWindowId()); InsertWindowToMap(sWindowId); diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 5359ac139532..6dfc3d7cc4d6 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -324,14 +324,14 @@ void Application::notifyWindow(vcl::LOKWindowId /*nLOKWindowId*/, SAL_WARN("vcl", "Invoked not implemented method: Application::notifyWindow"); } -void Application::libreOfficeKitViewCallback(int nType, const char* pPayload) const +void Application::libreOfficeKitViewCallback(int nType, const OString& pPayload) const { if (!comphelper::LibreOfficeKit::isActive()) return; if (m_pCallback) { - m_pCallback(nType, pPayload, m_pCallbackData); + m_pCallback(nType, pPayload.getStr(), m_pCallbackData); } } @@ -1868,7 +1868,7 @@ void dumpState(rtl::OStringBuffer &rState) pWin->DumpAsPropertyTree(props); rState.append("\n\tWindow: "); - rState.append(props.extractAsOString()); + rState.append(props.finishAndGetAsOString()); pWin = Application::GetNextTopLevelWindow( pWin ); }