From e4bc028711b22aef600aaf0727725e155f697709 Mon Sep 17 00:00:00 2001 From: Daniel Brondani Date: Fri, 1 Aug 2025 13:48:48 +0200 Subject: [PATCH] [projmgr] Improve performance of yml file content comparison --- tools/projmgr/include/ProjMgrUtils.h | 7 ++++ tools/projmgr/include/ProjMgrYamlEmitter.h | 3 +- tools/projmgr/src/ProjMgrUtils.cpp | 15 +++++++- tools/projmgr/src/ProjMgrYamlEmitter.cpp | 36 +++++++++---------- .../test/src/ProjMgrUtilsUnitTests.cpp | 10 +++++- 5 files changed, 50 insertions(+), 21 deletions(-) diff --git a/tools/projmgr/include/ProjMgrUtils.h b/tools/projmgr/include/ProjMgrUtils.h index 243211d1f..7aa729791 100644 --- a/tools/projmgr/include/ProjMgrUtils.h +++ b/tools/projmgr/include/ProjMgrUtils.h @@ -295,6 +295,13 @@ class ProjMgrUtils { */ static const std::string FileTypeFromExtension(const std::string& file); + /** + * @brief normalize line endings for consistent string comparison + * @param input string + * @return output normalized string + */ + static const std::string NormalizeLineEndings(const std::string& in); + protected: /** * @brief get filtered list of contexts diff --git a/tools/projmgr/include/ProjMgrYamlEmitter.h b/tools/projmgr/include/ProjMgrYamlEmitter.h index bb037dfbe..d07b3e238 100644 --- a/tools/projmgr/include/ProjMgrYamlEmitter.h +++ b/tools/projmgr/include/ProjMgrYamlEmitter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * Copyright (c) 2020-2025 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ @@ -114,6 +114,7 @@ class ProjMgrYamlEmitter { bool CompareFile(const std::string& filename, const YAML::Node& rootNode); bool CompareNodes(const YAML::Node& lhs, const YAML::Node& rhs); bool NeedRebuild(const std::string& filename, const YAML::Node& rootNode); + std::string EraseGeneratedByNode(const std::string& inStr); }; #endif // PROJMGRYAMLEMITTER_H diff --git a/tools/projmgr/src/ProjMgrUtils.cpp b/tools/projmgr/src/ProjMgrUtils.cpp index 57359eb8d..dfabd8f80 100644 --- a/tools/projmgr/src/ProjMgrUtils.cpp +++ b/tools/projmgr/src/ProjMgrUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 Arm Limited. All rights reserved. + * Copyright (c) 2020-2025 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ @@ -464,3 +464,16 @@ const string ProjMgrUtils::FileTypeFromExtension(const string& file) { } return RteUtils::EMPTY_STRING; } + +const std::string ProjMgrUtils::NormalizeLineEndings(const std::string& in) { + string out = in; + size_t pos = 0; + while ((pos = out.find("\r\n", pos)) != std::string::npos) { + out.replace(pos++, 2, "\n"); + } + pos = 0; + while ((pos = out.find("\r", pos)) != std::string::npos) { + out.replace(pos, 1, "\n"); + } + return out; +} diff --git a/tools/projmgr/src/ProjMgrYamlEmitter.cpp b/tools/projmgr/src/ProjMgrYamlEmitter.cpp index d90f96785..52baaac57 100644 --- a/tools/projmgr/src/ProjMgrYamlEmitter.cpp +++ b/tools/projmgr/src/ProjMgrYamlEmitter.cpp @@ -87,29 +87,29 @@ bool ProjMgrYamlEmitter::WriteFile(YAML::Node& rootNode, const std::string& file return true; } +string ProjMgrYamlEmitter::EraseGeneratedByNode(const string& inStr) { + size_t startIndex, endIndex; + string outStr = inStr; + startIndex = outStr.find(YAML_GENERATED_BY, 0); + endIndex = outStr.find('\n', startIndex); + if (startIndex != std::string::npos && endIndex != std::string::npos) { + outStr = outStr.erase(startIndex, endIndex - startIndex); + } + return outStr; +}; + bool ProjMgrYamlEmitter::CompareFile(const string& filename, const YAML::Node& rootNode) { - if (!RteFsUtils::Exists(filename)) { + string inBuffer; + if (!RteFsUtils::Exists(filename) || !RteFsUtils::ReadFile(filename, inBuffer)) { return false; } - const YAML::Node& yamlRoot = YAML::LoadFile(filename); - - // emit and load rootNode to ensure both comparison sides have the same formatting YAML::Emitter emitter; - return CompareNodes(yamlRoot, YAML::Load((emitter << rootNode).c_str())); + const auto& outBuffer = string((emitter << rootNode).c_str()) + '\n'; + return ProjMgrUtils::NormalizeLineEndings(EraseGeneratedByNode(inBuffer)) == + ProjMgrUtils::NormalizeLineEndings(EraseGeneratedByNode(outBuffer)); } bool ProjMgrYamlEmitter::CompareNodes(const YAML::Node& lhs, const YAML::Node& rhs) { - auto eraseGenNode = [](const string& inStr) { - size_t startIndex, endIndex; - string outStr = inStr; - startIndex = outStr.find(YAML_GENERATED_BY, 0); - endIndex = outStr.find('\n', startIndex); - if (startIndex != std::string::npos && endIndex != std::string::npos) { - outStr = outStr.erase(startIndex, endIndex - startIndex); - } - return outStr; - }; - YAML::Emitter lhsEmitter, rhsEmitter; string lhsData, rhsData; @@ -118,8 +118,8 @@ bool ProjMgrYamlEmitter::CompareNodes(const YAML::Node& lhs, const YAML::Node& r rhsEmitter << rhs; // remove generated-by node from the string - lhsData = eraseGenNode(lhsEmitter.c_str()); - rhsData = eraseGenNode(rhsEmitter.c_str()); + lhsData = EraseGeneratedByNode(lhsEmitter.c_str()); + rhsData = EraseGeneratedByNode(rhsEmitter.c_str()); return (lhsData == rhsData) ? true : false; } diff --git a/tools/projmgr/test/src/ProjMgrUtilsUnitTests.cpp b/tools/projmgr/test/src/ProjMgrUtilsUnitTests.cpp index eabbd9eaf..faa25b857 100644 --- a/tools/projmgr/test/src/ProjMgrUtilsUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrUtilsUnitTests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * Copyright (c) 2020-2025 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ @@ -531,3 +531,11 @@ TEST_F(ProjMgrUtilsUnitTests, ULLToHex) { EXPECT_EQ("0xDEADBEEF", ProjMgrUtils::ULLToHex(3735928559)); EXPECT_EQ("0xFFFFFFFF", ProjMgrUtils::ULLToHex(4294967295)); } + +TEST_F(ProjMgrUtilsUnitTests, NormalizeLineEndings) { + EXPECT_EQ("abc\ndef\n", ProjMgrUtils::NormalizeLineEndings("abc\r\ndef\r\n")); + EXPECT_EQ("abc\ndef\n", ProjMgrUtils::NormalizeLineEndings("abc\rdef\r")); + EXPECT_EQ("abc\ndef\n", ProjMgrUtils::NormalizeLineEndings("abc\rdef\n")); + EXPECT_EQ("abc\ndef\n", ProjMgrUtils::NormalizeLineEndings("abc\ndef\r")); + EXPECT_EQ("abc\ndef\n", ProjMgrUtils::NormalizeLineEndings("abc\ndef\n")); +}