diff --git a/.clang-format b/.clang-format index 67a4a8f..830ab06 100644 --- a/.clang-format +++ b/.clang-format @@ -1,26 +1,33 @@ ---- +# SPDX-FileCopyrightText: 2024 SeisSol Group +# +# SPDX-License-Identifier: MIT + Language: Cpp -# BasedOnStyle: LLVM -AccessModifierOffset: -2 +AccessModifierOffset: -4 AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlines: Right AlignOperands: true AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: false +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: false -BinPackArguments: true -BinPackParameters: true -BraceWrapping: +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false AfterClass: false AfterControlStatement: false AfterEnum: false @@ -39,6 +46,7 @@ BraceWrapping: BreakBeforeBinaryOperators: None BreakBeforeBraces: Attach BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon @@ -55,12 +63,12 @@ DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true -ForEachMacros: +ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH IncludeBlocks: Preserve -IncludeCategories: +IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 - Regex: '^(<|"(gtest|gmock|isl|json)/)' @@ -71,7 +79,7 @@ IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: false IndentPPDirectives: None IndentWidth: 2 -IndentWrappedFunctionNames: false +IndentWrappedFunctionNames: true JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: true @@ -79,6 +87,7 @@ MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None +ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 2 ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true @@ -87,20 +96,23 @@ PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right -RawStringFormats: - - Delimiter: pb - Language: TextProto - BasedOnStyle: google +PointerAlignment: Left +QualifierAlignment: Left ReflowComments: true SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false @@ -109,7 +121,8 @@ SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION TabWidth: 8 UseTab: Never -... - diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..b96c2b6 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,334 @@ +# SPDX-FileCopyrightText: 2024 SeisSol Group +# +# SPDX-License-Identifier: MIT + +Checks: | + -*, + clang-diagnostic-*, + cppcoreguidelines-*, + -cppcoreguidelines-avoid-const-or-ref-data-members, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-avoid-do-while, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-no-malloc, + -cppcoreguidelines-non-private-member-variables-in-classes, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-reinterpret-cast, + llvm-*, + -llvm-else-after-return, + -llvm-header-guard, + -llvm-qualified-auto, + misc-*, + -misc-non-private-member-variables-in-classes, + -misc-unused-parameters, + -misc-no-recursion, + modernize-*, + performance-*, + readability-*, + -readability-else-after-return, + -readability-identifier-length, + -readability-magic-numbers, + -readability-function-cognitive-complexity, +WarningsAsErrors: '*' +CheckOptions: +# - key: readability-identifier-naming.AbstractClassCase +# value: CamelCase +# - key: readability-identifier-naming.AbstractClassPrefix +# value: CamelCase +# - key: readability-identifier-naming.AbstractClassSuffix +# value: CamelCase + - key: readability-identifier-naming.ClassCase + value: CamelCase +# - key: readability-identifier-naming.ClassPrefix +# value: CamelCase +# - key: readability-identifier-naming.ClassSuffix +# value: CamelCase +# - key: readability-identifier-naming.ClassConstantCase +# value: CamelCase +# - key: readability-identifier-naming.ClassConstantPrefix +# value: CamelCase +# - key: readability-identifier-naming.ClassConstantSuffix +# value: CamelCase +# - key: readability-identifier-naming.ClassMemberCase +# value: CamelCase +# - key: readability-identifier-naming.ClassMemberPrefix +# value: CamelCase +# - key: readability-identifier-naming.ClassMemberSuffix +# value: CamelCase + - key: readability-identifier-naming.ClassMethodCase + value: camelBack +# - key: readability-identifier-naming.ClassMethodPrefix +# value: CamelCase +# - key: readability-identifier-naming.ClassMethodSuffix +# value: CamelCase + - key: readability-identifier-naming.ConstantCase + value: CamelCase +# - key: readability-identifier-naming.ConstantPrefix +# value: CamelCase +# - key: readability-identifier-naming.ConstantSuffix +# value: CamelCase +# - key: readability-identifier-naming.ConstantMemberCase +# value: CamelCase +# - key: readability-identifier-naming.ConstantMemberPrefix +# value: CamelCase +# - key: readability-identifier-naming.ConstantMemberSuffix +# value: CamelCase +# - key: readability-identifier-naming.ConstantParameterCase +# value: CamelCase +# - key: readability-identifier-naming.ConstantParameterPrefix +# value: CamelCase +# - key: readability-identifier-naming.ConstantParameterSuffix +# value: CamelCase +# - key: readability-identifier-naming.ConstantPointerParameterCase +# value: CamelCase +# - key: readability-identifier-naming.ConstantPointerParameterPrefix +# value: CamelCase +# - key: readability-identifier-naming.ConstantPointerParameterSuffix +# value: CamelCase + - key: readability-identifier-naming.ConstexprFunctionCase + value: camelBack +# - key: readability-identifier-naming.ConstexprFunctionPrefix +# value: CamelCase +# - key: readability-identifier-naming.ConstexprFunctionSuffix +# value: CamelCase +# - key: readability-identifier-naming.ConstexprMethodCase +# value: CamelCase +# - key: readability-identifier-naming.ConstexprMethodPrefix +# value: CamelCase +# - key: readability-identifier-naming.ConstexprMethodSuffix +# value: CamelCase + - key: readability-identifier-naming.ConstexprVariableCase + value: CamelCase +# - key: readability-identifier-naming.ConstexprVariablePrefix +# value: CamelCase +# - key: readability-identifier-naming.ConstexprVariableSuffix +# value: CamelCase + - key: readability-identifier-naming.EnumCase + value: CamelCase +# - key: readability-identifier-naming.EnumPrefix +# value: CamelCase +# - key: readability-identifier-naming.EnumSuffix +# value: CamelCase + - key: readability-identifier-naming.EnumConstantCase + value: CamelCase +# - key: readability-identifier-naming.EnumConstantPrefix +# value: CamelCase +# - key: readability-identifier-naming.EnumConstantSuffix +# value: CamelCase +# - key: readability-identifier-naming.FunctionCase +# value: CamelCase +# - key: readability-identifier-naming.FunctionPrefix +# value: CamelCase +# - key: readability-identifier-naming.FunctionSuffix +# value: CamelCase +# - key: readability-identifier-naming.GlobalConstantCase +# value: CamelCase +# - key: readability-identifier-naming.GlobalConstantPrefix +# value: CamelCase +# - key: readability-identifier-naming.GlobalConstantSuffix +# value: CamelCase +# - key: readability-identifier-naming.GlobalConstantPointerCase +# value: CamelCase +# - key: readability-identifier-naming.GlobalConstantPointerPrefix +# value: CamelCase +# - key: readability-identifier-naming.GlobalConstantPointerSuffix +# value: CamelCase +# - key: readability-identifier-naming.GlobalFunctionCase +# value: CamelCase +# - key: readability-identifier-naming.GlobalFunctionPrefix +# value: CamelCase +# - key: readability-identifier-naming.GlobalFunctionSuffix +# value: CamelCase +# - key: readability-identifier-naming.GlobalPointerCase +# value: CamelCase +# - key: readability-identifier-naming.GlobalPointerPrefix +# value: CamelCase +# - key: readability-identifier-naming.GlobalPointerSuffix +# value: CamelCase +# - key: readability-identifier-naming.GlobalVariableCase +# value: CamelCase +# - key: readability-identifier-naming.GlobalVariablePrefix +# value: CamelCase +# - key: readability-identifier-naming.GlobalVariableSuffix +# value: CamelCase +# - key: readability-identifier-naming.IgnoreMainLikeFunctions +# value: CamelCase +# - key: readability-identifier-naming.InlineNamespaceCase +# value: CamelCase +# - key: readability-identifier-naming.InlineNamespacePrefix +# value: CamelCase +# - key: readability-identifier-naming.InlineNamespaceSuffix +# value: CamelCase + - key: readability-identifier-naming.LocalConstantCase + value: CamelCase +# - key: readability-identifier-naming.LocalConstantPrefix +# value: CamelCase +# - key: readability-identifier-naming.LocalConstantSuffix +# value: CamelCase +# - key: readability-identifier-naming.LocalConstantPointerCase +# value: CamelCase +# - key: readability-identifier-naming.LocalConstantPointerPrefix +# value: CamelCase +# - key: readability-identifier-naming.LocalConstantPointerSuffix +# value: CamelCase +# - key: readability-identifier-naming.LocalPointerCase +# value: CamelCase +# - key: readability-identifier-naming.LocalPointerPrefix +# value: CamelCase +# - key: readability-identifier-naming.LocalPointerSuffix +# value: CamelCase + - key: readability-identifier-naming.LocalVariableCase + value: CamelCase +# - key: readability-identifier-naming.LocalVariablePrefix +# value: CamelCase +# - key: readability-identifier-naming.LocalVariableSuffix +# value: CamelCase + - key: readability-identifier-naming.MemberCase + value: CamelCase + - key: readability-identifier-naming.MemberPrefix + value: "m_" +# - key: readability-identifier-naming.MemberSuffix +# value: CamelCase +# - key: readability-identifier-naming.MethodCase +# value: CamelCase +# - key: readability-identifier-naming.MethodPrefix +# value: CamelCase +# - key: readability-identifier-naming.MethodSuffix +# value: CamelCase +# - key: readability-identifier-naming.NamespaceCase +# value: CamelCase +# - key: readability-identifier-naming.NamespacePrefix +# value: CamelCase +# - key: readability-identifier-naming.NamespaceSuffix +# value: CamelCase + - key: readability-identifier-naming.ParameterCase + value: CamelCase +# - key: readability-identifier-naming.ParameterPrefix +# value: CamelCase +# - key: readability-identifier-naming.ParameterSuffix +# value: CamelCase +# - key: readability-identifier-naming.ParameterPackCase +# value: CamelCase +# - key: readability-identifier-naming.ParameterPackPrefix +# value: CamelCase +# - key: readability-identifier-naming.ParameterPackSuffix +# value: CamelCase +# - key: readability-identifier-naming.PointerParameterCase +# value: CamelCase +# - key: readability-identifier-naming.PointerParameterPrefix +# value: CamelCase +# - key: readability-identifier-naming.PointerParameterSuffix +# value: CamelCase +# - key: readability-identifier-naming.PrivateMemberCase +# value: CamelCase +# - key: readability-identifier-naming.PrivateMemberPrefix +# value: CamelCase +# - key: readability-identifier-naming.PrivateMemberSuffix +# value: CamelCase +# - key: readability-identifier-naming.PrivateMethodCase +# value: CamelCase +# - key: readability-identifier-naming.PrivateMethodPrefix +# value: CamelCase +# - key: readability-identifier-naming.PrivateMethodSuffix +# value: CamelCase +# - key: readability-identifier-naming.ProtectedMemberCase +# value: CamelCase +# - key: readability-identifier-naming.ProtectedMemberPrefix +# value: CamelCase +# - key: readability-identifier-naming.ProtectedMemberSuffix +# value: CamelCase +# - key: readability-identifier-naming.ProtectedMethodCase +# value: CamelCase +# - key: readability-identifier-naming.ProtectedMethodPrefix +# value: CamelCase +# - key: readability-identifier-naming.ProtectedMethodSuffix +# value: CamelCase +# - key: readability-identifier-naming.PublicMemberCase +# value: CamelCase +# - key: readability-identifier-naming.PublicMemberPrefix +# value: CamelCase +# - key: readability-identifier-naming.PublicMemberSuffix +# value: CamelCase +# - key: readability-identifier-naming.PublicMethodCase +# value: CamelCase +# - key: readability-identifier-naming.PublicMethodPrefix +# value: CamelCase +# - key: readability-identifier-naming.PublicMethodSuffix +# value: CamelCase +# - key: readability-identifier-naming.StaticConstantCase +# value: CamelCase +# - key: readability-identifier-naming.StaticConstantPrefix +# value: CamelCase +# - key: readability-identifier-naming.StaticConstantSuffix +# value: CamelCase +# - key: readability-identifier-naming.StaticVariableCase +# value: CamelCase +# - key: readability-identifier-naming.StaticVariablePrefix +# value: CamelCase +# - key: readability-identifier-naming.StaticVariableSuffix +# value: CamelCase + - key: readability-identifier-naming.StructCase + value: CamelCase +# - key: readability-identifier-naming.StructPrefix +# value: CamelCase +# - key: readability-identifier-naming.StructSuffix +# value: CamelCase +# - key: readability-identifier-naming.TemplateParameterCase +# value: CamelCase +# - key: readability-identifier-naming.TemplateParameterPrefix +# value: CamelCase +# - key: readability-identifier-naming.TemplateParameterSuffix +# value: CamelCase +# - key: readability-identifier-naming.TemplateTemplateParameterCase +# value: CamelCase +# - key: readability-identifier-naming.TemplateTemplateParameterPrefix +# value: CamelCase +# - key: readability-identifier-naming.TemplateTemplateParameterSuffix +# value: CamelCase +# - key: readability-identifier-naming.TypeAliasCase +# value: CamelCase +# - key: readability-identifier-naming.TypeAliasPrefix +# value: CamelCase +# - key: readability-identifier-naming.TypeAliasSuffix +# value: CamelCase +# - key: readability-identifier-naming.TypedefCase +# value: CamelCase +# - key: readability-identifier-naming.TypedefPrefix +# value: CamelCase +# - key: readability-identifier-naming.TypedefSuffix +# value: CamelCase +# - key: readability-identifier-naming.TypeTemplateParameterCase +# value: CamelCase +# - key: readability-identifier-naming.TypeTemplateParameterPrefix +# value: CamelCase +# - key: readability-identifier-naming.TypeTemplateParameterSuffix +# value: CamelCase + - key: readability-identifier-naming.UnionCase + value: camelBack +# - key: readability-identifier-naming.UnionPrefix +# value: CamelCase +# - key: readability-identifier-naming.UnionSuffix +# value: CamelCase +# - key: readability-identifier-naming.ValueTemplateParameterCase +# value: CamelCase +# - key: readability-identifier-naming.ValueTemplateParameterPrefix +# value: CamelCase +# - key: readability-identifier-naming.ValueTemplateParameterSuffix +# value: CamelCase + - key: readability-identifier-naming.VariableCase + value: CamelCase +# - key: readability-identifier-naming.VariablePrefix +# value: CamelCase +# - key: readability-identifier-naming.VariableSuffix +# value: CamelCase + - key: readability-identifier-naming.VirtualMethodCase + value: camelBack +# - key: readability-identifier-naming.VirtualMethodPrefix +# value: CamelCase +# - key: readability-identifier-naming.VirtualMethodSuffix +# value: CamelCase + + # ignore Eigen, fty manually, until added to IWYU + - key: misc-include-cleaner.IgnoreHeaders + value: 'yaml-cpp/.*' diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..218ebc8 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2024 SeisSol Group +# +# SPDX-License-Identifier: MIT + +name: clang-format +on: + - push + +jobs: + clang-format: + name: clang-format + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + + - name: apt-get + run: | + sudo apt-get update + sudo apt-get -y install python3 python3-pip + + # fix version here for now + pip3 install clang-format==18.1.5 + + - name: run-clang-format + run: | + set -euo pipefail + clang-format --version + which clang-format + + # cf. https://stackoverflow.com/a/36046965 + find ./include -iname '*.hpp' | xargs clang-format -i + find ./tests -iname '*.cpp' | xargs clang-format -i + + git diff > formatting.patch + cat formatting.patch + if [ -s ./formatting.patch ]; then (exit 1); fi diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml new file mode 100644 index 0000000..0f38f6d --- /dev/null +++ b/.github/workflows/reuse.yml @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2024 SeisSol Group +# +# SPDX-License-Identifier: MIT + +name: reuse +on: + - push + +jobs: + reuse: + name: reuse + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + + - name: apt-get + run: | + sudo apt-get update + sudo apt-get -y install python3 python3-pip + + # fix version here for now + pip3 install reuse==4.0.3 + + - name: run-reuse-lint + run: | + set -euo pipefail + + reuse lint + \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..06bf9d3 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2024 SeisSol Group +# +# SPDX-License-Identifier: MIT + +name: unittest +on: + - push + +jobs: + unittest: + name: unittest + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: 'true' + + - name: install-packages + run: | + sudo apt-get update -y + sudo apt-get install -y libyaml-cpp-dev libgtest-dev ninja-build + + - name: configure-googletest + run: | + cd /usr/src/googletest/googletest + sudo cmake ./CMakeLists.txt -Dgtest_disable_pthreads=ON -GNinja + sudo ninja + + # ninja install was not found + sudo cp lib/*.a /usr/lib + + - name: build + run: | + cd tests + mkdir build + cd build + cmake .. -GNinja + ninja + ./tests + cd .. diff --git a/.github/workflows/tidy.yml b/.github/workflows/tidy.yml new file mode 100644 index 0000000..75b4c2c --- /dev/null +++ b/.github/workflows/tidy.yml @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2024 SeisSol Group +# +# SPDX-License-Identifier: MIT + +name: clang-tidy +on: + - push + +jobs: + clang-tidy: + name: clang-tidy + runs-on: ubuntu-22.04 + steps: + - name: apt-get + run: | + sudo apt-get update -y + sudo apt-get install -y libyaml-cpp-dev libgtest-dev ninja-build + + # keep, for once clang-19 or higher is needed + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + sudo add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" + sudo add-apt-repository "deb-src http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" + sudo apt-get update -y + + sudo apt-get -y install clang-18 clang-tidy-18 libomp-18-dev + + sudo pip3 install numpy + sudo mkdir -p /opt/dependencies + + - name: configure-googletest + run: | + cd /usr/src/googletest/googletest + sudo cmake ./CMakeLists.txt -Dgtest_disable_pthreads=ON -GNinja + sudo ninja + + # ninja install was not found + sudo cp lib/*.a /usr/lib + + - uses: actions/checkout@v4 + with: + submodules: 'true' + + - name: clang-tidy + run: | + set -euo pipefail + clang-tidy-18 --version + which clang-tidy-18 + git submodule update --init + cd tests + mkdir -p build && cd build + cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -GNinja + ninja + sed -i 's/-fprofile-abs-path //g' compile_commands.json + run-clang-tidy ../ ./ -clang-tidy-binary=$(which clang-tidy-18) -quiet -j $(nproc) diff --git a/.gitignore b/.gitignore index 380ce87..7eea5ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,10 @@ +# SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +# SPDX-FileCopyrightText: 2024 SeisSol Group +# +# SPDX-License-Identifier: MIT + .idea -build +build* cmake-build-* *.sw* +.cache diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8451d9b..0000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -dist: bionic -language: cpp -comiler: - - gcc - -before_install: - - sudo apt-get update -qq - -install: - - sudo apt-get install cmake libyaml-cpp-dev libgtest-dev - -before_script: - - cd /usr/src/googletest/googletest - - sudo cmake ./CMakeLists.txt -Dgtest_disable_pthreads=ON && sudo make && sudo make install - - cd $TRAVIS_BUILD_DIR - -script: - - cd tests/ && mkdir build && cd build - - cmake .. && make - - ./tests \ No newline at end of file diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000..dffaeca --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1,9 @@ +SPDX-FileCopyrightText: 2024 SeisSol Group + +SPDX-License-Identifier: MIT + +--- + +Programmed by Ravil Dorozhinskii. + +Currently maintained by the SeisSol Group (cf. the members of https://github.com/SeisSol ). diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e5f4cd..329446e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,16 @@ +# SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +# +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.5) project(fty-converter) +target_compile_features(${CMAKE_PROJECT_NAME} PRIVATE cxx_std_17) + find_package(YAML-CPP REQUIRED) add_executable(${CMAKE_PROJECT_NAME} converter.cpp) target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${YAML_CPP_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}) target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC ${YAML_CPP_LIBRARIES}) -target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE -std=c++11 -Wall -Wextra -pedantic -Werror) +target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE -std=c++14 -Wall -Wextra -pedantic -Werror) diff --git a/LICENSE b/LICENSE index 45b59fd..a43a6c7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ MIT License -Copyright (c) 2023 Ravil Dorozhinskii +Copyright (c) 2020-2023 Ravil Dorozhinskii +Copyright (c) 2024 SeisSol Group Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 0000000..2071b23 --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 2c49eaa..5b6143a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ + + # fty - Fortran To Yaml It is a small header-only C++ library which is supposed to help people to start converting their legacy Fortran code to C++. The library reads a text file or lists of strings formatted according to Fortran *NAMELIST I/O* style, and generates a YAML::Node (a hash table) containing retrieved information. diff --git a/converter.cpp b/converter.cpp index bfa161e..580a0bb 100644 --- a/converter.cpp +++ b/converter.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2020-2022 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #include "fty.hpp" #include #include diff --git a/example/parameters.par b/example/parameters.par index e40a1e5..0e6dd2e 100644 --- a/example/parameters.par +++ b/example/parameters.par @@ -1,3 +1,7 @@ +! SPDX-FileCopyrightText: 2020 Ravil Dorozhinskii +! +! SPDX-License-Identifier: MIT + &equations MaterialFileName = 'material.yaml' / diff --git a/fty.hpp b/fty.hpp index 0e0d6c7..7bc5a96 100644 --- a/fty.hpp +++ b/fty.hpp @@ -1,3 +1,8 @@ +// SPDX-FileCopyrightText: 2022 Ravil Dorozhinskii +// SPDX-FileCopyrightText: 2024 SeisSol Group +// +// SPDX-License-Identifier: MIT + #ifndef FTY_CONVERTER_FTY_HPP #define FTY_CONVERTER_FTY_HPP @@ -6,7 +11,7 @@ #include "include/BlockProcessor.hpp" #include "include/FtyInternals.hpp" #include "include/FtyPolicies.hpp" -#include "include/StringProcessor.h" +#include "include/StringProcessor.hpp" // IWYU pragma: end_exports #include diff --git a/include/BlockParser.hpp b/include/BlockParser.hpp index eed1251..c2b4bc4 100644 --- a/include/BlockParser.hpp +++ b/include/BlockParser.hpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #ifndef FTY_CONVERTER_BLOCKPARSER_HPP #define FTY_CONVERTER_BLOCKPARSER_HPP @@ -7,11 +11,12 @@ namespace fty { -template class BlockParser { -public: - std::string getHeader(const BlockT &Block) { +template +class BlockParser { + public: + auto getHeader(const BlockT& Block) -> std::string { std::smatch Match; - const std::string &Header = *Block.first; + const std::string& Header = *Block.first; if (std::regex_match(Header, Match, m_HeaderExpr)) { return m_KeyModifier.apply(Match[1]); } else { @@ -19,7 +24,7 @@ template class BlockParser { } } - YAML::Node getFields(const BlockT &Block) { + auto getFields(const BlockT& Block) -> YAML::Node { YAML::Node Fields; auto Itr = next(Block.first); // the header @@ -32,8 +37,8 @@ template class BlockParser { for (; Itr != End; ++Itr) { std::smatch Match; if (std::regex_match(*Itr, Match, m_FieldExpr)) { - std::string Identifier = m_KeyModifier.apply(Match[1]); - std::string ValueStr = Match[2]; + const std::string Identifier = m_KeyModifier.apply(Match[1]); + const std::string ValueStr = Match[2]; if (!Fields[Identifier]) { @@ -41,11 +46,9 @@ template class BlockParser { std::smatch SubMatch; if (std::regex_match(ValueStr, SubMatch, m_QuotedValueExpr)) { Fields[Identifier] = std::string(SubMatch[2]); - } - else if (std::regex_match(ValueStr, SubMatch, m_LegacyFortranFloatExpr)) { - Fields[Identifier] = std::regex_replace(ValueStr, m_LegacyFortranFloatExpr, "$1e$3"); - } - else { + } else if (std::regex_match(ValueStr, SubMatch, m_LegacyFortranFloatExpr)) { + Fields[Identifier] = std::regex_replace(ValueStr, m_LegacyFortranFloatExpr, "$1e$2"); + } else { Fields[Identifier] = ValueStr; } } else { @@ -67,12 +70,13 @@ template class BlockParser { return Fields; } -private: - std::regex m_HeaderExpr{"^\\s*&\\s*(\\w*)\\s*.*\\s?"}; - std::regex m_FieldExpr{"\\s*(\\w*)\\s*=\\s*((?:\\w|[[:punct:]])(?:(?:\\w|[[:punct:]]|\\s)*(?:\\w|" - "[[:punct:]]))?)\\s*"}; - std::regex m_QuotedValueExpr{"^(\'|\")+(.*)(\'|\")+$"}; - std::regex m_LegacyFortranFloatExpr{"^(\\d*\\.?\\d*)(D|d)([\\+-]\\d+)$"}; // 'D' or 'd' instead of 'E' or 'e' + private: + std::regex m_HeaderExpr{R"(^\s*&\s*(\w*)\s*.*\s?)"}; + std::regex m_FieldExpr{ + R"(\s*(\w*)\s*=\s*((?:\w|[[:punct:]])(?:(?:\w|[[:punct:]]|\s)*(?:\w|[[:punct:]]))?)\s*)"}; + std::regex m_QuotedValueExpr{R"(^('|")+(.*)('|")+$)"}; + std::regex m_LegacyFortranFloatExpr{ + R"(^(\d*\.?\d*)(?:D|d)([\+-]?\d+)$)"}; // 'D' or 'd' instead of 'E' or 'e' Policy m_KeyModifier; }; } // namespace fty diff --git a/include/BlockProcessor.hpp b/include/BlockProcessor.hpp index f9516ed..972efdf 100644 --- a/include/BlockProcessor.hpp +++ b/include/BlockProcessor.hpp @@ -1,14 +1,18 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #ifndef FTY_CONVERTER_BLOCKPROCESSOR_HPP #define FTY_CONVERTER_BLOCKPROCESSOR_HPP #include "FtyInternals.hpp" -#include "StringProcessor.h" +#include "StringProcessor.hpp" #include namespace fty { class BlockProcessor { -public: + public: /** * Finds a block given the beginning, end, comment symbols of a block. 'Bigin' iterator will be * modified which will point to the next line after the end block symbol @@ -19,7 +23,7 @@ class BlockProcessor { * a block * @return a list of string which contains a block */ - BlockT getNextBlock(StringsT::iterator &CurrentItr, const StringsT::iterator End) { + static auto getNextBlock(StringsT::iterator& CurrentItr, const StringsT::iterator End) -> BlockT { BlockT Block; const char BlockBeginChar = '&'; const char BlockEndChar = '/'; @@ -29,7 +33,8 @@ class BlockProcessor { } // skip everything above which is not a block - while ((CurrentItr != End) && (!m_StringProcessor.startsWith(*CurrentItr, BlockBeginChar))) { + while ((CurrentItr != End) && + (!fty::StringProcessor::startsWith(*CurrentItr, BlockBeginChar))) { ++CurrentItr; } if (CurrentItr == End) { @@ -43,11 +48,12 @@ class BlockProcessor { bool IsBlockEndFound = false; bool IsNextBlockFound = false; for (; CurrentItr != End; ++CurrentItr) { - IsBlockEndFound = m_StringProcessor.startsWith(*CurrentItr, BlockEndChar); - IsNextBlockFound = m_StringProcessor.startsWith(*CurrentItr, BlockBeginChar); + IsBlockEndFound = fty::StringProcessor::startsWith(*CurrentItr, BlockEndChar); + IsNextBlockFound = fty::StringProcessor::startsWith(*CurrentItr, BlockBeginChar); - if (IsBlockEndFound or IsNextBlockFound) + if (IsBlockEndFound or IsNextBlockFound) { break; + } } if (IsNextBlockFound) { @@ -62,31 +68,29 @@ class BlockProcessor { Block.second = CurrentItr; // Advance to the next if it is not the end - if (CurrentItr != End) + if (CurrentItr != End) { ++CurrentItr; + } return Block; } - void removeEmptyBlocks(std::list &Blocks) { + static void removeEmptyBlocks(std::list& Blocks) { // NOTE: header + tail + at least one field - const std::list::iterator::difference_type MIN_NUM_STRINGS = 2; + const std::list::iterator::difference_type MinNumStrings = 2; std::vector::iterator> Deletees; for (auto Itr = Blocks.begin(); Itr != Blocks.end(); ++Itr) { - if (std::distance(Itr->first, Itr->second) < MIN_NUM_STRINGS) { + if (std::distance(Itr->first, Itr->second) < MinNumStrings) { Deletees.push_back(Itr); } } - for (auto &Deletee : Deletees) { + for (auto& Deletee : Deletees) { Blocks.erase(Deletee); } } - -private: - StringProcessor m_StringProcessor; }; } // namespace fty diff --git a/include/FtyDataTypes.hpp b/include/FtyDataTypes.hpp index e8c61ea..25790e6 100644 --- a/include/FtyDataTypes.hpp +++ b/include/FtyDataTypes.hpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #ifndef PARSER_FTYDATATYPES_HPP #define PARSER_FTYDATATYPES_HPP diff --git a/include/FtyExceptions.hpp b/include/FtyExceptions.hpp index 7f9bed7..5f301e7 100644 --- a/include/FtyExceptions.hpp +++ b/include/FtyExceptions.hpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #ifndef PARSER_FTYEXCEPTIONS_HPP #define PARSER_FTYEXCEPTIONS_HPP @@ -8,28 +12,28 @@ namespace fty { namespace exception { class BaseException : public std::runtime_error { -public: - BaseException(const std::string &Message) : std::runtime_error("ParsingError: " + Message) {} + public: + BaseException(const std::string& Message) : std::runtime_error("ParsingError: " + Message) {} }; class FileException : public BaseException { -public: - FileException(const std::string &Message) : BaseException(Message) {} + public: + FileException(const std::string& Message) : BaseException(Message) {} }; class TextBlockException : public BaseException { -public: - TextBlockException(const std::string &Message) : BaseException(Message) {} + public: + TextBlockException(const std::string& Message) : BaseException(Message) {} }; class CriticalTextBlockException : public BaseException { -public: - CriticalTextBlockException(const std::string &Message) : BaseException(Message) {} + public: + CriticalTextBlockException(const std::string& Message) : BaseException(Message) {} }; class CriticalKeyValueError : public BaseException { -public: - CriticalKeyValueError(const std::string &Message) : BaseException(Message) {} + public: + CriticalKeyValueError(const std::string& Message) : BaseException(Message) {} }; } // namespace exception diff --git a/include/FtyInternals.hpp b/include/FtyInternals.hpp index 91474b2..2b545b6 100644 --- a/include/FtyInternals.hpp +++ b/include/FtyInternals.hpp @@ -1,5 +1,10 @@ -#ifndef PARSER_FTY_H -#define PARSER_FTY_H +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// SPDX-FileCopyrightText: 2024 SeisSol Group +// +// SPDX-License-Identifier: MIT + +#ifndef PARSER_FTY_HPP +#define PARSER_FTY_HPP // IWYU pragma: begin_exports #include "FtyDataTypes.hpp" @@ -8,4 +13,4 @@ #include -#endif // PARSER_FTY_H \ No newline at end of file +#endif // PARSER_FTY_HPP diff --git a/include/FtyPolicies.hpp b/include/FtyPolicies.hpp index dee358f..7c49555 100644 --- a/include/FtyPolicies.hpp +++ b/include/FtyPolicies.hpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #ifndef FTY_CONVERTER_POLICIES_HPP #define FTY_CONVERTER_POLICIES_HPP @@ -6,26 +10,28 @@ namespace fty { struct AsLowercase { - std::string apply(const std::string &String) { + static auto apply(const std::string& String) -> std::string { std::string ConvertedString(String.size(), '\0'); - std::transform(String.begin(), String.end(), ConvertedString.begin(), - [](unsigned char Char) { return std::tolower(Char); }); + std::transform(String.begin(), String.end(), ConvertedString.begin(), [](unsigned char Char) { + return std::tolower(Char); + }); return ConvertedString; } }; struct AsUppercase { - std::string apply(const std::string &String) { + static auto apply(const std::string& String) -> std::string { std::string ConvertedString(String.size(), '\0'); - std::transform(String.begin(), String.end(), ConvertedString.begin(), - [](unsigned char Char) { return std::toupper(Char); }); + std::transform(String.begin(), String.end(), ConvertedString.begin(), [](unsigned char Char) { + return std::toupper(Char); + }); return ConvertedString; } }; struct AsOriginal { - std::string apply(const std::string &String) { return String; } + static auto apply(const std::string& String) -> std::string { return String; } }; } // namespace fty -#endif // FTY_CONVERTER_POLICIES_HPP \ No newline at end of file +#endif // FTY_CONVERTER_POLICIES_HPP diff --git a/include/StringProcessor.h b/include/StringProcessor.hpp similarity index 50% rename from include/StringProcessor.h rename to include/StringProcessor.hpp index ab63099..4a673bc 100644 --- a/include/StringProcessor.h +++ b/include/StringProcessor.hpp @@ -1,61 +1,65 @@ -#ifndef FTY_CONVERTER_STRINGPROCESSOR_H -#define FTY_CONVERTER_STRINGPROCESSOR_H +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + +#ifndef FTY_CONVERTER_STRINGPROCESSOR_HPP +#define FTY_CONVERTER_STRINGPROCESSOR_HPP #include "FtyInternals.hpp" #include namespace fty { class StringProcessor { -public: + public: /** * Checks whether the given line starts with 'Character' * @param String tests string * @param Character tests character * @return true if the string starts with 'Character'. Otherwise, false */ - bool startsWith(const std::string &String, const char Character) { + static auto startsWith(const std::string& String, const char Character) -> bool { auto CurrentChar = String.begin(); // find the first non-white-space character - while ((CurrentChar != String.end()) && (isspace(*(CurrentChar)))) { + while ((CurrentChar != String.end()) && ((isspace(*(CurrentChar))) != 0)) { ++CurrentChar; }; return ((*CurrentChar) == Character) && (CurrentChar != String.end()); } - void removeComments(StringsT &Content) { - - for (auto &Item : Content) { + static void removeComments(StringsT& Content) { + for (auto& Item : Content) { std::smatch Match; - if (std::regex_match(Item, Match, m_Comment_Expr)) { + if (std::regex_match(Item, Match, CommentExpr)) { Item = Match[1]; } } } - void removeEmptyLines(StringsT &Content) { + static void removeEmptyLines(StringsT& Content) { const std::string WHITESPACE = " \n\r\t\f\v"; - auto isEmptyString = [&WHITESPACE](const std::string &String) -> bool { - size_t Start = String.find_first_not_of(WHITESPACE); + auto IsEmptyString = [&WHITESPACE](const std::string& String) -> bool { + const size_t Start = String.find_first_not_of(WHITESPACE); return Start == std::string::npos; }; std::vector Deletees; for (auto Itr = Content.begin(); Itr != Content.end(); ++Itr) { - if (isEmptyString(*Itr)) + if (IsEmptyString(*Itr)) { Deletees.push_back(Itr); + } } - for (auto &Itr : Deletees) { + for (auto& Itr : Deletees) { Content.erase(Itr); } } -private: - std::regex m_Comment_Expr{"^([^!]*)!.*\\s?$"}; + private: + const static inline std::regex CommentExpr{"^([^!]*)!.*\\s?$"}; }; } // namespace fty -#endif // FTY_CONVERTER_STRINGPROCESSOR_H +#endif // FTY_CONVERTER_STRINGPROCESSOR_HPP diff --git a/tests/BlockParserTest.cpp b/tests/BlockParserTest.cpp index 8bce10f..7f85176 100644 --- a/tests/BlockParserTest.cpp +++ b/tests/BlockParserTest.cpp @@ -1,4 +1,10 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #include "BlockParser.hpp" +#include "FtyDataTypes.hpp" +#include "FtyExceptions.hpp" #include "FtyPolicies.hpp" #include "helper.hpp" #include "gtest/gtest.h" @@ -10,16 +16,16 @@ using namespace fty; TEST(HeaderTest, HeaderWithWhitespaces) { BlockParser Processor; StringsT Content{{" & Discretization "}, {"Order = 1"}}; - BlockT Block = make_block(Content); - std::string Header = Processor.getHeader(Block); + const BlockT Block = make_block(Content); + const std::string Header = Processor.getHeader(Block); ASSERT_STREQ(Header.c_str(), "Discretization"); } TEST(HeaderTest, HeaderWithComment) { BlockParser Processor; StringsT Content{{"&Discretization ! Comment \n"}, {"Order = 1"}}; - BlockT Block = make_block(Content); - std::string Header = Processor.getHeader(Block); + const BlockT Block = make_block(Content); + const std::string Header = Processor.getHeader(Block); ASSERT_STREQ(Header.c_str(), "Discretization"); } @@ -27,7 +33,7 @@ TEST(InvalidHeaderTest, InvalidHeader) { BlockParser Processor; // forgotten '&' symbol StringsT Content{{"Discretization"}, {"Order = 1"}}; - BlockT Block = make_block(Content); + const BlockT Block = make_block(Content); ASSERT_THROW(Processor.getHeader(Block), exception::CriticalTextBlockException); } @@ -36,7 +42,7 @@ TEST(InvalidBlockFieldTest, EmptyBlock) { BlockParser Processor; // forgotten '&' symbol StringsT Content{{"&Discretization"}, {"/"}}; - BlockT Block = make_block(Content); + const BlockT Block = make_block(Content); ASSERT_THROW(Processor.getFields(Block), exception::CriticalTextBlockException); } @@ -45,7 +51,7 @@ TEST(InvalidBlockFieldTest, RepeatedFields) { BlockParser Processor; // forgotten '&' symbol StringsT Content{{"&Discretization"}, {"Order = 1"}, {"Order = 1"}, {"/"}}; - BlockT Block = make_block(Content); + const BlockT Block = make_block(Content); ASSERT_THROW(Processor.getFields(Block), exception::CriticalKeyValueError); } @@ -54,7 +60,7 @@ TEST(InvalidBlockFieldTest, InvalidField) { BlockParser Processor; // forgotten '=' symbol StringsT Content{{"&Discretization"}, {"Order 1"}, {"/"}}; - BlockT Block = make_block(Content); + const BlockT Block = make_block(Content); ASSERT_THROW(Processor.getFields(Block), exception::CriticalTextBlockException); } @@ -70,7 +76,7 @@ TEST(CorrectBlockTest, CorrectBlock) { {"MASK1 = 0 1 0 1 0 1 "}, {"MASK2 =1 0 1 0 0 1"}, {"/"}}; - BlockT Block = make_block(Content); + const BlockT Block = make_block(Content); YAML::Node Node = Processor.getFields(Block); ASSERT_STREQ(Node["order"].as().c_str(), "1"); @@ -89,28 +95,38 @@ TEST(FloatingPointField, StandardNotaion) { {"Epsilon3 = 1.01E-10"}, {"Epsilon4 = 1.01E+10"}, {"/"}}; - BlockT Block = make_block(Content); + const BlockT Block = make_block(Content); YAML::Node Node = Processor.getFields(Block); ASSERT_DOUBLE_EQ(Node["Epsilon1"].as(), 1.01e-10); - ASSERT_FLOAT_EQ(Node["Epsilon2"].as(), 1.01e+10f); + ASSERT_FLOAT_EQ(Node["Epsilon2"].as(), 1.01e+10F); ASSERT_DOUBLE_EQ(Node["Epsilon3"].as(), 1.01E-10); - ASSERT_FLOAT_EQ(Node["Epsilon4"].as(), 1.01E+10f); + ASSERT_FLOAT_EQ(Node["Epsilon4"].as(), 1.01E+10F); } -TEST(FloatingPointField, FortranNotaion) { +TEST(FloatingPointField, FortranNotation) { BlockParser Processor; StringsT Content{{"&Block1"}, {"Epsilon1=1.01d-10"}, {"Epsilon2=1.01d+10"}, {"Epsilon3=1.01D-10"}, {"Epsilon4=1.01D+10"}, + {"Epsilon5=1.01d10"}, + {"Epsilon6=1.01D10"}, + {"Epsilon7=1d10"}, + {"Epsilon8=1D10"}, {"/"}}; - BlockT Block = make_block(Content); + const BlockT Block = make_block(Content); YAML::Node Node = Processor.getFields(Block); + + // (note that the assignment to float/double here is more or less randomly-chosen) ASSERT_DOUBLE_EQ(Node["Epsilon1"].as(), 1.01e-10); - ASSERT_FLOAT_EQ(Node["Epsilon2"].as(), 1.01e+10f); + ASSERT_FLOAT_EQ(Node["Epsilon2"].as(), 1.01e+10F); ASSERT_DOUBLE_EQ(Node["Epsilon3"].as(), 1.01e-10); - ASSERT_FLOAT_EQ(Node["Epsilon4"].as(), 1.01e+10f); + ASSERT_FLOAT_EQ(Node["Epsilon4"].as(), 1.01e+10F); + ASSERT_DOUBLE_EQ(Node["Epsilon5"].as(), 1.01e10); + ASSERT_FLOAT_EQ(Node["Epsilon6"].as(), 1.01e10F); + ASSERT_DOUBLE_EQ(Node["Epsilon7"].as(), 1e10); + ASSERT_FLOAT_EQ(Node["Epsilon8"].as(), 1e10F); } diff --git a/tests/BlockProcessorTest.cpp b/tests/BlockProcessorTest.cpp index 35501cb..dd512d2 100644 --- a/tests/BlockProcessorTest.cpp +++ b/tests/BlockProcessorTest.cpp @@ -1,25 +1,32 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #include "BlockProcessor.hpp" -#include "FtyPolicies.hpp" +#include "FtyDataTypes.hpp" +#include "FtyExceptions.hpp" #include "helper.hpp" #include "gtest/gtest.h" -#include +#include +#include +#include #include using namespace fty; -bool isEqualBlocks(const BlockT &Left, const BlockT &Right) { +auto isEqualBlocks(const BlockT& Left, const BlockT& Right) -> bool { auto LeftSize = std::distance(Left.first, std::next(Left.second)); auto RightSize = std::distance(Right.first, std::next(Right.second)); if (LeftSize != RightSize) { - std::cout << "LeftSize: " << LeftSize << "; RightSize: " << RightSize << std::endl; + std::cout << "LeftSize: " << LeftSize << "; RightSize: " << RightSize << '\n'; return false; } auto LeftItr = Left.first; auto RightItr = Right.first; - for (int i = 0; i < LeftSize; ++i, ++LeftItr, ++RightItr) { + for (int I = 0; I < LeftSize; ++I, ++LeftItr, ++RightItr) { if ((*LeftItr) != (*RightItr)) { - std::cout << "Left: " << *LeftItr << "; Right: " << *RightItr << ";" << std::endl; + std::cout << "Left: " << *LeftItr << "; Right: " << *RightItr << ";" << '\n'; return false; } } @@ -27,7 +34,6 @@ bool isEqualBlocks(const BlockT &Left, const BlockT &Right) { } TEST(BlockProcessorTest, RemoveEmptyBlocks) { - BlockProcessor Processor; BlockFactory Factory; Factory.add({{"&Empty"}, {"/"}}); @@ -38,21 +44,20 @@ TEST(BlockProcessorTest, RemoveEmptyBlocks) { Factory.add({{"&Boundaries"}, {"Order=1 "}, {"BC_fs = 1.5"}, {"BC_of = 1"}, {"/"}}); Factory.add({{"&Empty"}, {"/"}}); - StringsT Content = Factory.getContent(); - std::list Blocks = Factory.getBlocks(); + const StringsT Content = Factory.getContent(); + const std::list Blocks = Factory.getBlocks(); BlockFactory TestFactory = Factory; - StringsT TestContent = TestFactory.getContent(); + const StringsT TestContent = TestFactory.getContent(); std::list TestBlocks = TestFactory.getBlocks(); - Processor.removeEmptyBlocks(TestBlocks); + fty::BlockProcessor::removeEmptyBlocks(TestBlocks); ASSERT_EQ(TestBlocks.size(), 2); ASSERT_TRUE(isEqualBlocks(BlockScroll(TestBlocks)[0], BlockScroll(Blocks)[1])); ASSERT_TRUE(isEqualBlocks(BlockScroll(TestBlocks)[1], BlockScroll(Blocks)[3])); } TEST(BlockProcessorTest, StartsWithCorruptedNextBlock) { - BlockProcessor Processor; BlockFactory Factory; Factory.add({{"&Empty"}, {"Dummy = 1"}}); @@ -61,11 +66,11 @@ TEST(BlockProcessorTest, StartsWithCorruptedNextBlock) { StringsT Content = Factory.getContent(); auto Begin = Content.begin(); auto End = Content.end(); - ASSERT_THROW(Processor.getNextBlock(Begin, End), exception::CriticalTextBlockException); + ASSERT_THROW(fty::BlockProcessor::getNextBlock(Begin, End), + exception::CriticalTextBlockException); } TEST(BlockProcessorTest, EndsWithCorruptedNextBlock) { - BlockProcessor Processor; BlockFactory Factory; Factory.add({{"&Discretization"}, {"Order=1 "}, {"Cfl = 0.5 \n"}, {"MASK2 =1 0 1 0 0 1"}}); @@ -75,11 +80,11 @@ TEST(BlockProcessorTest, EndsWithCorruptedNextBlock) { StringsT Content = Factory.getContent(); auto Begin = Content.begin(); auto End = Content.end(); - ASSERT_THROW(Processor.getNextBlock(Begin, End), exception::CriticalTextBlockException); + ASSERT_THROW(fty::BlockProcessor::getNextBlock(Begin, End), + exception::CriticalTextBlockException); } TEST(BlockProcessorTest, EndsWithoutTerminator) { - BlockProcessor Processor; BlockFactory Factory; Factory.add( @@ -88,17 +93,17 @@ TEST(BlockProcessorTest, EndsWithoutTerminator) { Factory.add({{"&Empty"}, {"Dummy = 1"}}); StringsT Content = Factory.getContent(); - std::list Blocks = Factory.getBlocks(); + const std::list Blocks = Factory.getBlocks(); auto Begin = Content.begin(); auto End = Content.end(); - BlockT ValidBlock = Processor.getNextBlock(Begin, End); + const BlockT ValidBlock = fty::BlockProcessor::getNextBlock(Begin, End); ASSERT_TRUE(isEqualBlocks(ValidBlock, BlockScroll(Blocks)[0])); - ASSERT_THROW(Processor.getNextBlock(Begin, End), exception::CriticalTextBlockException); + ASSERT_THROW(fty::BlockProcessor::getNextBlock(Begin, End), + exception::CriticalTextBlockException); } TEST(BlockProcessorTest, EmptyLinesAfterLastBlock) { - BlockProcessor Processor; BlockFactory Factory; Factory.add({{""}, {"\n"}}); @@ -108,11 +113,11 @@ TEST(BlockProcessorTest, EmptyLinesAfterLastBlock) { Factory.add({{""}, {"\n"}}); StringsT Content = Factory.getContent(); - std::list Blocks = Factory.getBlocks(); + const std::list Blocks = Factory.getBlocks(); auto Begin = Content.begin(); auto End = Content.end(); - BlockT ValidBlock = Processor.getNextBlock(Begin, End); + const BlockT ValidBlock = fty::BlockProcessor::getNextBlock(Begin, End); ASSERT_TRUE(isEqualBlocks(ValidBlock, BlockScroll(Blocks)[1])); - ASSERT_THROW(Processor.getNextBlock(Begin, End), exception::TextBlockException); + ASSERT_THROW(fty::BlockProcessor::getNextBlock(Begin, End), exception::TextBlockException); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index eed682e..2912c82 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +# +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.5) project(testing) @@ -11,11 +15,12 @@ add_executable(tests ./main.cpp ./BlockParserTest.cpp ./BlockProcessorTest.cpp) +target_compile_features(tests PRIVATE cxx_std_17) -target_compile_options(tests PRIVATE "-std=c++11") +target_compile_options(tests PRIVATE "-std=c++17") target_include_directories(tests PRIVATE ${YAML_CPP_INCLUDE_DIR} ${GTEST_INCLUDE_DIRS} ../include) target_link_libraries(tests PRIVATE ${YAML_CPP_LIBRARIES} ${GTEST_LIBRARIES}) target_compile_options(tests PRIVATE -Wall -Wextra -pedantic -Werror) enable_testing() -add_test(NAME tests COMMAND tests) \ No newline at end of file +add_test(NAME tests COMMAND tests) diff --git a/tests/PolicyTest.cpp b/tests/PolicyTest.cpp index c089c66..d1dfab4 100644 --- a/tests/PolicyTest.cpp +++ b/tests/PolicyTest.cpp @@ -1,4 +1,9 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #include "BlockParser.hpp" +#include "FtyDataTypes.hpp" #include "FtyPolicies.hpp" #include "helper.hpp" #include "gtest/gtest.h" @@ -8,13 +13,13 @@ using namespace fty; class PolicyTests : public ::testing::Test { -protected: + protected: void SetUp() override { - m_Content.push_back("&Discretization\n"); - m_Content.push_back("Order = 4\n"); - m_Content.push_back(" Material = 1 \n"); - m_Content.push_back(" Cfl = 0.5 "); - m_Content.push_back("/"); + m_Content.emplace_back("&Discretization\n"); + m_Content.emplace_back("Order = 4\n"); + m_Content.emplace_back(" Material = 1 \n"); + m_Content.emplace_back(" Cfl = 0.5 "); + m_Content.emplace_back("/"); m_TestContent = m_Content; } @@ -23,10 +28,10 @@ class PolicyTests : public ::testing::Test { }; TEST_F(PolicyTests, LowercaseTest) { - BlockT Block = make_block(m_TestContent); + const BlockT Block = make_block(m_TestContent); BlockParser Processor; - std::string Header = Processor.getHeader(Block); + const std::string Header = Processor.getHeader(Block); ASSERT_STREQ(Header.c_str(), "discretization"); YAML::Node Node = Processor.getFields(Block); @@ -36,10 +41,10 @@ TEST_F(PolicyTests, LowercaseTest) { } TEST_F(PolicyTests, UppercaseTest) { - BlockT Block = make_block(m_TestContent); + const BlockT Block = make_block(m_TestContent); BlockParser Processor; - std::string Header = Processor.getHeader(Block); + const std::string Header = Processor.getHeader(Block); ASSERT_STREQ(Header.c_str(), "DISCRETIZATION"); YAML::Node Node = Processor.getFields(Block); @@ -49,14 +54,14 @@ TEST_F(PolicyTests, UppercaseTest) { } TEST_F(PolicyTests, OriginalPolicyTest) { - BlockT Block = make_block(m_TestContent); + const BlockT Block = make_block(m_TestContent); BlockParser Processor; - std::string Header = Processor.getHeader(Block); + const std::string Header = Processor.getHeader(Block); ASSERT_STREQ(Header.c_str(), "Discretization"); YAML::Node Node = Processor.getFields(Block); ASSERT_STREQ(Node["Order"].as().c_str(), "4"); ASSERT_STREQ(Node["Material"].as().c_str(), "1"); ASSERT_STREQ(Node["Cfl"].as().c_str(), "0.5"); -} \ No newline at end of file +} diff --git a/tests/StringProcessorTest.cpp b/tests/StringProcessorTest.cpp index e74e091..66a2c3a 100644 --- a/tests/StringProcessorTest.cpp +++ b/tests/StringProcessorTest.cpp @@ -1,4 +1,8 @@ -#include "StringProcessor.h" +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + +#include "StringProcessor.hpp" #include "helper.hpp" #include "gtest/gtest.h" #include @@ -6,55 +10,52 @@ using namespace fty; TEST(StartWithString, Found) { - StringProcessor Processor; std::string TestString; TestString = "&DataInFortranStyle \n"; - ASSERT_TRUE(Processor.startsWith(TestString, '&')); + ASSERT_TRUE(fty::StringProcessor::startsWith(TestString, '&')); TestString = " \t &DataInFortranStyle"; - ASSERT_TRUE(Processor.startsWith(TestString, '&')); + ASSERT_TRUE(fty::StringProcessor::startsWith(TestString, '&')); } TEST(StartWithString, NotFound) { - StringProcessor Processor; std::string TestString; TestString = " DataInFortranStyle& \n"; - ASSERT_FALSE(Processor.startsWith(TestString, '&')); + ASSERT_FALSE(fty::StringProcessor::startsWith(TestString, '&')); TestString = " \t DataInFortranStyle"; - ASSERT_FALSE(Processor.startsWith(TestString, '&')); + ASSERT_FALSE(fty::StringProcessor::startsWith(TestString, '&')); TestString = "! &DataInFortranStyle"; - ASSERT_FALSE(Processor.startsWith(TestString, '&')); + ASSERT_FALSE(fty::StringProcessor::startsWith(TestString, '&')); } TEST(StartWithString, EmptyStrings) { - StringProcessor Processor; std::string TestString{"\n"}; - ASSERT_FALSE(Processor.startsWith(TestString, '&')); + ASSERT_FALSE(fty::StringProcessor::startsWith(TestString, '&')); TestString = "\n\n\n"; - ASSERT_FALSE(Processor.startsWith(TestString, '&')); + ASSERT_FALSE(fty::StringProcessor::startsWith(TestString, '&')); TestString = ""; - ASSERT_FALSE(Processor.startsWith(TestString, '&')); + ASSERT_FALSE(fty::StringProcessor::startsWith(TestString, '&')); } class CommentsAndEmptyLinesTest : public ::testing::Test { -protected: + protected: void SetUp() override { - m_Content.push_back("\n"); - m_Content.push_back(" "); - m_Content.push_back(" \n"); - m_Content.push_back("\n "); - m_Content.push_back(" ! Comments "); - m_Content.push_back(" \r\n"); - m_Content.push_back("value1 = 3.14 ! Comments "); - m_Content.push_back(" value2 = 2.71 ! Comments ! Comment\n"); - m_Content.push_back("value3 = 9.81! Comments ! Comment\n"); - m_Content.push_back(""); + m_Content.emplace_back("\n"); + m_Content.emplace_back(" "); + m_Content.emplace_back(" \n"); + m_Content.emplace_back("\n "); + m_Content.emplace_back(" ! Comments "); + m_Content.emplace_back(" \r\n"); + m_Content.emplace_back("value1 = 3.14 ! Comments "); + m_Content.emplace_back(" value2 = 2.71 ! Comments ! Comment\n"); + m_Content.emplace_back("value3 = 9.81! Comments ! Comment\n"); + m_Content.emplace_back(""); m_TestContent = m_Content; } @@ -65,8 +66,7 @@ class CommentsAndEmptyLinesTest : public ::testing::Test { TEST_F(CommentsAndEmptyLinesTest, removeEmptyLines) { - StringProcessor Processor; - Processor.removeEmptyLines(m_TestContent); + fty::StringProcessor::removeEmptyLines(m_TestContent); ASSERT_EQ(m_TestContent.size(), 4); ASSERT_STREQ(StringsScroll(m_TestContent)[0].c_str(), StringsScroll(m_Content)[4].c_str()); @@ -77,8 +77,7 @@ TEST_F(CommentsAndEmptyLinesTest, removeEmptyLines) { TEST_F(CommentsAndEmptyLinesTest, removeComments) { - StringProcessor Processor; - Processor.removeComments(m_TestContent); + fty::StringProcessor::removeComments(m_TestContent); // removeComments just trims comments ASSERT_EQ(m_TestContent.size(), m_Content.size()); @@ -90,9 +89,8 @@ TEST_F(CommentsAndEmptyLinesTest, removeComments) { TEST_F(CommentsAndEmptyLinesTest, CombinedTest) { - StringProcessor Processor; - Processor.removeComments(m_TestContent); - Processor.removeEmptyLines(m_TestContent); + fty::StringProcessor::removeComments(m_TestContent); + fty::StringProcessor::removeEmptyLines(m_TestContent); // removeComments just trims comments ASSERT_EQ(m_TestContent.size(), 3); @@ -100,4 +98,4 @@ TEST_F(CommentsAndEmptyLinesTest, CombinedTest) { ASSERT_STREQ((*Itr).c_str(), "value1 = 3.14 "); ASSERT_STREQ((*(++Itr)).c_str(), " value2 = 2.71 "); ASSERT_STREQ((*(++Itr)).c_str(), "value3 = 9.81"); -} \ No newline at end of file +} diff --git a/tests/helper.cpp b/tests/helper.cpp index 730dd37..38d5da7 100644 --- a/tests/helper.cpp +++ b/tests/helper.cpp @@ -1,3 +1,11 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #include "helper.hpp" +#include "FtyDataTypes.hpp" +#include -BlockT make_block(StringsT &Content) { return std::make_pair(Content.begin(), --Content.end()); } \ No newline at end of file +auto make_block(StringsT& Content) -> BlockT { + return std::make_pair(Content.begin(), --Content.end()); +} diff --git a/tests/helper.hpp b/tests/helper.hpp index 8717e55..ea60da9 100644 --- a/tests/helper.hpp +++ b/tests/helper.hpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #ifndef FTY_CONVERTER_HELPER_HPP #define FTY_CONVERTER_HELPER_HPP @@ -6,12 +10,12 @@ #include using namespace fty; -BlockT make_block(StringsT &Content); +auto make_block(StringsT &Content) -> BlockT; template class Scroll { public: Scroll(const ListT &Content) : m_Content(Content){}; - typename ListT::value_type operator[](size_t Index) { + auto operator[](size_t Index) -> typename ListT::value_type { assert(Index < m_Content.size() && "Index is out of the range"); return *(std::next(m_Content.begin(), Index)); } @@ -31,20 +35,25 @@ class BlockFactory { m_Content.insert(m_Content.end(), Block.first, std::next(Block.second)); auto Head = std::prev(m_Content.end(), std::distance(Block.first, std::next(Block.second))); auto Tail = std::prev(m_Content.end()); - m_Blocks.push_back(std::make_pair(Head, Tail)); + m_Blocks.emplace_back(Head, Tail); } } + auto operator=(const BlockFactory&) -> BlockFactory& = delete; // TODO + BlockFactory(BlockFactory&&) = delete; // TODO + auto operator=(BlockFactory&&) -> BlockFactory& = delete; // TODO + ~BlockFactory() = default; + void add(StringsT LocalContent) { m_Content.insert(m_Content.end(), LocalContent.begin(), LocalContent.end()); - auto Head = std::prev(m_Content.end(), LocalContent.size()); + auto Head = std::prev(m_Content.end(), static_cast(LocalContent.size())); auto Tail = std::prev(m_Content.end()); - m_Blocks.push_back(std::make_pair(Head, Tail)); + m_Blocks.emplace_back(Head, Tail); } - StringsT getContent() { return m_Content; } + auto getContent() -> StringsT { return m_Content; } - std::list getBlocks() { return m_Blocks; } + auto getBlocks() -> std::list { return m_Blocks; } private: StringsT m_Content; diff --git a/tests/main.cpp b/tests/main.cpp index 1659be8..3f654c0 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,6 +1,10 @@ +// SPDX-FileCopyrightText: 2020-2023 Ravil Dorozhinskii +// +// SPDX-License-Identifier: MIT + #include "gtest/gtest.h" -int main(int argc, char **argv) { +auto main(int argc, char** argv) -> int { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} \ No newline at end of file +}