diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 265a6a1..7b4d2d4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,11 +1,9 @@ name: CMake -on: [push] -#on: -# push: -# branches: [ master ] -# pull_request: -# branches: [ master ] +on: + pull_request: + branches: [ master ] + workflow_dispatch: env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) @@ -26,19 +24,20 @@ jobs: curl http://download.opensuse.org/repositories/science:/dlr/xUbuntu_18.04/Release.key | sudo apt-key add - echo "deb http://download.opensuse.org/repositories/science:/dlr/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list sudo apt-get update -qq - sudo apt-get install -y libboost-all-dev libtixi3-dev cmake cmake-data + sudo apt-get install -y libtixi3-dev cmake cmake-data - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -DBoost_USE_STATIC_LIBS=OFF -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - name: Build + working-directory: ${{github.workspace}}/build # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + run: make VERBOSE=1 - name: Test working-directory: ${{github.workspace}}/build # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ./tests \ No newline at end of file + run: ./tests diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fb3641a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -dist: trusty -language: cpp -sudo: required - -addons: - apt: - packages: libboost-all-dev - sources: - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - boost1.85 - -before_install: - - curl http://download.opensuse.org/repositories/science:/dlr/xUbuntu_14.04/Release.key | sudo apt-key add - - - echo "deb http://download.opensuse.org/repositories/science:/dlr/xUbuntu_14.04/ /" | sudo tee -a /etc/apt/sources.list - - sudo apt-get update -qq - - sudo apt-get install -y --force-yes libtixi3-dev - -script: - - mkdir build - - cd build - - cmake -DBoost_USE_STATIC_LIBS=OFF .. - - make -j4 - - ./tests - \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index fe0b232..d2ddcd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,14 @@ # CPACSGen cmake project # author: Bernhard Manfred Gruber -cmake_minimum_required(VERSION 3.2) +cmake_minimum_required(VERSION 3.11.0) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) project(CPACSGen) # cache variables -set(BOOST_ROOT "" CACHE PATH "Boost installation prefix") set(TIXI_PATH "" CACHE PATH "Tixi installation prefix") set(TIGL_PATH "" CACHE PATH "Tigl installation prefix") @@ -22,12 +21,6 @@ if (SYSTEM_RHEL7) endif() endif() -# find boost -set(Boost_USE_STATIC_LIBS ON CACHE BOOL "Find static or dynamic libs. Static libs require lib prefix.") -find_package (Boost REQUIRED COMPONENTS system filesystem date_time regex unit_test_framework) -mark_as_advanced(CLEAR BOOST_ROOT) # find module for boost marks these variables as advanced -mark_as_advanced(CLEAR Boost_USE_STATIC_LIBS) - # find tixi set(CMAKE_PREFIX_PATH "${TIXI_PATH};${CMAKE_PREFIX_PATH}") find_package(tixi3 3.0.3 REQUIRED) @@ -42,9 +35,6 @@ target_compile_definitions(lib${PROJECT_NAME} PUBLIC -DCPACS_GEN ) -target_include_directories(lib${PROJECT_NAME} PUBLIC - ${Boost_INCLUDE_DIRS} -) # driver file(GLOB DRIVER_INPUTS src/driver/*.cpp *src/driver/*.h *.md) @@ -53,32 +43,33 @@ source_group(" " FILES ${DRIVER_INPUTS}) target_link_libraries(${PROJECT_NAME} lib${PROJECT_NAME} - ${Boost_LIBRARIES} ) # tests +message(STATUS "Build gtest Testsuite") + +enable_testing() +option(gtest_force_shared_crt "" ON) +mark_as_advanced(gtest_force_shared_crt gtest_build_tests gtest_build_samples gtest_disable_pthreads) + +set(BUILD_GMOCK OFF) +set(INSTALL_GTEST OFF) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) +message(STATUS "Download and configure the TIGL gtest Testsuite") +include(AddGoogleTest) +message(STATUS "Download and configure the TIGL gtest Testsuite - Success") + set(DATA_DIR ${CMAKE_SOURCE_DIR}/test/data) configure_file(test/paths.h.in ${CMAKE_BINARY_DIR}/test/paths.h) file(GLOB TEST_INPUTS test/*.cpp test/*.h) list(APPEND TEST_INPUTS ${CMAKE_BINARY_DIR}/test/paths.h) add_executable(tests ${TEST_INPUTS}) -source_group(" " FILES ${TEST_INPUTS}) - -if(NOT Boost_USE_STATIC_LIBS) - target_compile_definitions(tests PUBLIC - -DBOOST_TEST_DYN_LINK - ) -endif() - +target_link_libraries(tests PRIVATE gtest gtest_main libCPACSGen) target_include_directories(tests PUBLIC ${CMAKE_BINARY_DIR}/test ) - -target_link_libraries(tests - lib${PROJECT_NAME} - ${Boost_LIBRARIES} -) +add_test(NAME tests COMMAND tests) # generate target if(TIGL_PATH) diff --git a/README.md b/README.md index c0e45eb..7e6a1ce 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,8 @@ https://github.com/RISCSoftware/cpacs_tigl_gen The following components are required to build and run CPACSGen * A working copy of CPACSGen * CMake -* C\++11/C++14 compliant compiler (VS2017 is currently used and tested) +* C\++17 compliant compiler (VS2017 is currently used and tested) * TIXI library (https://github.com/DLR-SC/tixi) -* Boost libraries (v1.55 or higher) * A working copy of TiGL with CPACSGen input files (https://github.com/DLR-SC/tigl) ## Input files @@ -42,9 +41,8 @@ For each subdirectory, CPACSGen runs an additional pass, putting the generated f 1. Clone the CPACSGen repository from Github 2. Clone the TiGL repository Github 3. Use CMake to configure CPACSGen - 1. Set BOOST_ROOT - 2. Set TIXI_PATH - 3. Set TIGL_PATH to the directory of your TiGL clone + 1. Set TIXI_PATH, if the TiXI package is not already installed in the current conda environment + 2. Set TIGL_PATH to the directory of your TiGL clone 4. Build CPACSGen 5. Build target generate executes CPACSGen.exe $\{TIGL_DIR}/cpacs_gen_input $\{CPACSGEN_DIR}/src $\{TIGL_DIR}/src/generated @@ -107,7 +105,3 @@ The classes generated by CPACSGen depend upon the following helper files, which Wrappers over TIXI functions providing a C++ friendly interface (references, std::string, exceptions, ...). Is used by the ReadCPACS and WriteCPACS implementation. -* UniquePtr.hpp - Contains tigl\::unique_ptr\ which defaults to std\::unique_ptr\ if C++11 is available, otherwise provides a custom type based on std\::auto_ptr\. - Furthermore, the generated classes may require boost::optional\, which is part of TiGL, and some internal TiGL files. - diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index c2c2ca5..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,17 +0,0 @@ -image: Visual Studio 2017 -environment: - VCPKG_DEFAULT_TRIPLET: x64-windows - -install: - - call C:\\Miniconda35-x64\\Scripts\\activate.bat - - conda install --yes -c dlr-sc tixi3 - -build_script: -- ps: | - mkdir build - pushd build - cmake -DBOOST_ROOT=C:\Libraries\boost_1_67_0 -G "Visual Studio 15 2017 Win64" .. - cmake --build . --config "Release" - -test_script: - - Release\tests diff --git a/cmake/AddGoogleTest.cmake b/cmake/AddGoogleTest.cmake new file mode 100644 index 0000000..9dfea91 --- /dev/null +++ b/cmake/AddGoogleTest.cmake @@ -0,0 +1,69 @@ +# +# +# Downloads GTest and provides a helper macro to add tests. Add make check, as well, which +# gives output on failed tests without having to set an environment variable. +# +# +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +include(FetchContent) +FetchContent_Declare(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.17.0) +FetchContent_GetProperties(googletest) +if(NOT googletest_POPULATED) + FetchContent_Populate(googletest) + set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE BOOL "") + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) + unset(CMAKE_SUPPRESS_DEVELOPER_WARNINGS) +endif() + + +if(CMAKE_CONFIGURATION_TYPES) + add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} + --force-new-ctest-process --output-on-failure + --build-config "$") +else() + add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} + --force-new-ctest-process --output-on-failure) +endif() +set_target_properties(check PROPERTIES FOLDER "Scripts") + +#include_directories(${gtest_SOURCE_DIR}/include) + +# More modern way to do the last line, less messy but needs newish CMake: +# target_include_directories(gtest INTERFACE ${gtest_SOURCE_DIR}/include) + + +if(GOOGLE_TEST_INDIVIDUAL) + include(GoogleTest) +endif() + +# Target must already exist +macro(add_gtest TESTNAME) + target_link_libraries(${TESTNAME} PUBLIC gtest gtest_main) + + if(GOOGLE_TEST_INDIVIDUAL) + gtest_discover_tests(${TESTNAME} + TEST_PREFIX "${TESTNAME}." + PROPERTIES FOLDER "Tests") + else() + add_test(${TESTNAME} ${TESTNAME}) + set_target_properties(${TESTNAME} PROPERTIES FOLDER "Tests") + endif() + +endmacro() + +mark_as_advanced( +gmock_build_tests +gtest_build_samples +gtest_build_tests +gtest_disable_pthreads +gtest_force_shared_crt +gtest_hide_internal_symbols +BUILD_GMOCK +BUILD_GTEST +) + +set_target_properties(gtest gtest_main + PROPERTIES FOLDER "Extern") diff --git a/src/driver/main.cpp b/src/driver/main.cpp index 0ada4d2..11ee56e 100644 --- a/src/driver/main.cpp +++ b/src/driver/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -9,12 +9,11 @@ #include "../lib/Filesystem.h" #include "../lib/NotImplementedException.h" -namespace fs = boost::filesystem; +namespace fs = std::filesystem; namespace tigl { const auto runtimeFiles = { "TixiHelper.h", - "UniquePtr.h", }; void processDirectory(const std::string& inputDirectory, const std::string& runtimeDirectory, const std::string& outputDirectory, const std::string& typeSystemGraphVisFile, Filesystem& fs, const std::string& ns = "") { diff --git a/src/lib/CodeGen.cpp b/src/lib/CodeGen.cpp index f2413ca..92b9de2 100644 --- a/src/lib/CodeGen.cpp +++ b/src/lib/CodeGen.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include @@ -8,6 +6,9 @@ #include #include #include +#include +#include +#include #include "SchemaParser.h" #include "Tables.h" @@ -32,9 +33,9 @@ namespace tigl { } namespace { + auto customReplacedType(const std::string& type, const Tables& tables) -> const std::string& { - const auto p = tables.m_customTypes.find(type); - return p ? *p : type; + return tables.m_customTypes.find(type).value_or(type); } auto capitalizeFirstLetter(std::string str) -> std::string { @@ -200,7 +201,7 @@ namespace tigl { return typeName; case Cardinality::Vector: { - if (vectorInnerTypeIsUniquePtr(field)) + if (vectorInnerTypeIsCPACSClass(field)) return "std::vector>"; else return "std::vector<" + typeName + ">"; @@ -220,16 +221,44 @@ namespace tigl { return customReplacedType(field); } - auto vectorInnerTypeIsUniquePtr(const Field& field) const -> bool { + auto vectorInnerClass(const Field& field) const -> Class const& + { + if (field.cardinality() != Cardinality::Vector){ + throw std::logic_error("Requested vector inner type for non-vector type"); + } + auto const it = m_types.classes.find(field.typeName); + if(vectorInnerTypeIsCPACSClass(field) && it != std::end(m_types.classes)) { + return it->second; + } else { + throw std::logic_error("VectorInnerType is not a CPACS class"); + } + } + + auto vectorInnerTypeIsCPACSClass(const Field& field) const -> bool { if (field.cardinality() != Cardinality::Vector) throw std::logic_error("Requested vector inner type for non-vector type"); return m_types.classes.find(field.typeName) != std::end(m_types.classes); } + std::string trimString(const std::string& s) const{ + auto start = std::find_if_not(s.begin(), s.end(), [](unsigned char c){ return std::isspace(c); }); + auto end = std::find_if_not(s.rbegin(), s.rend(), [](unsigned char c){ return std::isspace(c); }).base(); + + return (start < end ? std::string(start, end) : ""); + } + void writeDocumentation(IndentingStreamWrapper& hpp, const std::string& documentation) const { if (!documentation.empty()) { std::vector lines; - boost::algorithm::split(lines, documentation, boost::is_any_of("\n")); + std::istringstream stream(documentation); + std::string line; + + while (std::getline(stream, line, '\n')) { + lines.push_back(trimString(line)); + } + if (documentation.back() == '\n') { + lines.push_back(""); + } for (const auto& line : lines) hpp << "/// " << line; } @@ -264,9 +293,18 @@ namespace tigl { hpp << "TIGL_EXPORT virtual " << getterSetterType(f) << "& Get" << capitalizeFirstLetter(f.name()) << "();"; hpp << EmptyLine; hpp << "TIGL_EXPORT virtual size_t Get" << capitalizeFirstLetter(f.cpacsName) << "Count() const;"; + if(vectorInnerTypeIsCPACSClass(f) && hasUidField(vectorInnerClass(f))){ + hpp << "TIGL_EXPORT virtual size_t Get" << capitalizeFirstLetter(f.cpacsName) << "Index(const std::string& UID) const;"; + } + hpp << EmptyLine; hpp << "TIGL_EXPORT virtual const " << vectorInnerType(f) << "& Get" << capitalizeFirstLetter(f.cpacsName) << "(size_t index) const;"; hpp << "TIGL_EXPORT virtual " << vectorInnerType(f) << "& Get" << capitalizeFirstLetter(f.cpacsName) << "(size_t index);"; - } // generate special accessors for uid reference vectors + if(vectorInnerTypeIsCPACSClass(f) && hasUidField(vectorInnerClass(f))){ + hpp << EmptyLine; + hpp << "TIGL_EXPORT virtual const " << vectorInnerType(f) << "& Get" << capitalizeFirstLetter(f.cpacsName) << "(const std::string& UID) const;"; + hpp << "TIGL_EXPORT virtual " << vectorInnerType(f) << "& Get" << capitalizeFirstLetter(f.cpacsName) << "(const std::string& UID);"; + } + } // generate special accessors for uid reference vectors else if (f.cardinality() == Cardinality::Vector && f.xmlTypeName == c_uidRefType) { hpp << "TIGL_EXPORT virtual void AddTo" << capitalizeFirstLetter(f.name()) << "(const " << vectorInnerType(f) << "& value);"; hpp << "TIGL_EXPORT virtual bool RemoveFrom" << capitalizeFirstLetter(f.name()) << "(const " << vectorInnerType(f) << "& value);"; @@ -386,6 +424,40 @@ namespace tigl { cpp << "}"; cpp << EmptyLine; + // Getter for index by UID + if(vectorInnerTypeIsCPACSClass(f) && hasUidField(vectorInnerClass(f))){ + cpp << "size_t " << className << "::Get" << capitalizeFirstLetter(f.cpacsName) << "Index(const std::string& UID) const"; + cpp << "{"; + { + Scope s(cpp); + cpp << "for (size_t i=0; i < Get" << capitalizeFirstLetter(f.cpacsName) << "Count(); i++) {"; + { + Scope s(cpp); + if(vectorInnerTypeIsCPACSClass(f) && hasUidField(vectorInnerClass(f)) && !hasMandatoryUidField(vectorInnerClass(f))) { + cpp << "const boost::optional tmpUID(*" << f.fieldName() << "[i]->GetUID());"; + cpp << "if (tmpUID == UID) {"; + { + Scope s(cpp); + cpp << "return i+1;"; + } + cpp << "}"; + } else { + cpp << "const std::string tmpUID(" << f.fieldName() << "[i]->GetUID());"; + cpp << "if (tmpUID == UID) {"; + { + Scope s(cpp); + cpp << "return i+1;"; + } + cpp << "}"; + } + } + cpp << "}"; + cpp << "throw CTiglError(\"Invalid UID in " << className << "::Get" << capitalizeFirstLetter(f.cpacsName) << "Index\", TIGL_UID_ERROR);"; + } + cpp << "}"; + cpp << EmptyLine; + } + //Getters for elements in vector type by index; for (auto isConst : { false, true }) { if(isConst){ @@ -396,14 +468,15 @@ namespace tigl { cpp << "{"; { Scope s(cpp); - cpp << "index--;"; - cpp << "if (index < 0 || index >= Get" << capitalizeFirstLetter(f.cpacsName) << "Count()) {"; + cpp << "if (index < 1 || index > Get" << capitalizeFirstLetter(f.cpacsName) << "Count()) {"; { Scope s(cpp); cpp << "throw CTiglError(\"Invalid index in " << getterSetterType(f) << "::Get" << capitalizeFirstLetter(f.cpacsName) << "\", TIGL_INDEX_ERROR);"; } cpp << "}"; - if (vectorInnerTypeIsUniquePtr(f)) { + cpp << "index--;"; + // CPACS classes are stored in smart pointers and we need to derefence + if (vectorInnerTypeIsCPACSClass(f)) { cpp << "return *" << f.fieldName() << "[index];"; } else { cpp << "return " << f.fieldName() << "[index];"; @@ -413,6 +486,38 @@ namespace tigl { cpp << EmptyLine; } + //Getters for elements in vector type by uid; + if(vectorInnerTypeIsCPACSClass(f) && hasUidField(vectorInnerClass(f))){ + for (auto isConst : { false, true }) { + if(isConst){ + cpp << "const " << vectorInnerType(f) << "& " << className << "::Get" << capitalizeFirstLetter(f.cpacsName) << "(const std::string& UID) const"; + } else { + cpp << vectorInnerType(f) << "& " << className << "::Get" << capitalizeFirstLetter(f.cpacsName) << "(const std::string& UID)"; + } + cpp << "{"; + { + Scope s(cpp); + cpp << "for (auto& elem : " << f.fieldName() <<" ) {"; + { + Scope s(cpp); + cpp << "if (elem->GetUID() == UID)"; + { + Scope s(cpp); + if (vectorInnerTypeIsCPACSClass(f)) { + cpp << "return *elem;"; + } else { + cpp << "return elem;"; + } + + } + cpp << "}"; + cpp << "throw CTiglError(\"Invalid UID in " << className << "::Get" << capitalizeFirstLetter(f.cpacsName) << ". \\\"\"+ UID + \"\\\" not found in CPACS file!\" , TIGL_UID_ERROR);"; + } + } + cpp << "}"; + cpp << EmptyLine; + } + } }// generate special accessors for uid reference vectors else if (f.cardinality() == Cardinality::Vector && f.xmlTypeName == c_uidRefType) { @@ -706,7 +811,13 @@ namespace tigl { arguments.push_back(parentPointerThis(parentClass)); if (requiresUidManager(c)) arguments.push_back("m_uidMgr"); - return boost::join(arguments, ", "); + std::ostringstream oss; + for (size_t i = 0; i < arguments.size(); ++i) { + if (i != 0) + oss << ", "; + oss << arguments[i]; + } + return oss.str(); } void writeReadAttributeOrElementImplementation(IndentingStreamWrapper& cpp, const Class& c, const Field& f) const { @@ -1003,7 +1114,13 @@ namespace tigl { cpp << "if (" << tixiHelperNamespace << "::TixiCheckAttribute(tixiHandle, xpath, \"" << f.cpacsName << "\")) {"; else { const auto empty = f.xmlType == XMLConstruct::SimpleContent || f.xmlType == XMLConstruct::FundamentalTypeBase; - cpp << "if (" << tixiHelperNamespace << "::TixiCheckElement(tixiHandle, xpath" << (empty ? "" : " + \"/" + f.cpacsName + "\"") << ")) {"; + const auto fundamentalOrEnum = m_tables.m_fundamentalTypes.contains(f.typeName) || m_types.enums.count(f.typeName) > 0; + if (empty) + cpp << "if (" << tixiHelperNamespace << "::TixiCheckElementHasTextContent(tixiHandle, xpath)) {"; + else if (fundamentalOrEnum) + cpp << "if (" << tixiHelperNamespace << "::TixiCheckElementHasTextContent(tixiHandle, xpath + \"/" + f.cpacsName + "\")) {"; + else + cpp << "if (" << tixiHelperNamespace << "::TixiCheckElement(tixiHandle, xpath + \"/" + f.cpacsName + "\")) {"; } { Scope s(cpp); @@ -1087,6 +1204,12 @@ namespace tigl { throw std::logic_error("elements inside choice can only be optional or vector"); } + static auto unique (std::vector& v) { + std::sort(std::begin(v), std::end(v)); + const auto it = std::unique(std::begin(v), std::end(v)); + v.erase(it, std::end(v)); + } + void writeChoiceValidatorImplementation(IndentingStreamWrapper& cpp, const Class& c) const { if (!c.choices.empty()) { cpp << "bool " << c.name << "::ValidateChoices() const"; @@ -1096,7 +1219,7 @@ namespace tigl { - struct RecursiveColletor : public boost::static_visitor<> { + struct RecursiveColletor { void operator()(const ChoiceElement& ce) { indices.push_back(ce.index); } @@ -1108,13 +1231,21 @@ namespace tigl { void operator()(const ChoiceElements& ces) { for (const auto& ce : ces) - ce.apply_visitor(*this); + std::visit(*this, ce); + } + + void operator()(const std::shared_ptr& c) { + if (c) (*this)(*c); + } + + void operator()(const std::variant>& v) { + std::visit(*this, v); } std::vector indices; }; - struct ChoiceWriter : public boost::static_visitor<> { + struct ChoiceWriter { ChoiceWriter(IndentingStreamWrapper& cpp, const Class& c) : cpp(cpp), c(c) {} @@ -1126,11 +1257,17 @@ namespace tigl { cpp << "true // " << f.fieldName() << " is optional in choice"; } + void operator()(const std::shared_ptr& chPtr) { + if (chPtr) { + (*this)(*chPtr); + } + } + void operator()(const Choice& ch) { cpp << "("; { Scope s(cpp); - boost::optional additionalScope; + std::optional additionalScope; if (ch.minOccurs == 0) { cpp << "// all uninitialized is valid since choice is optional!"; @@ -1142,11 +1279,6 @@ namespace tigl { parentCollector(ch); auto& allIndices = parentCollector.indices; - auto unique = [](std::vector& v) { - std::sort(std::begin(v), std::end(v)); - const auto it = std::unique(std::begin(v), std::end(v)); - v.erase(it, std::end(v)); - }; unique(allIndices); for (const auto& i : allIndices) { @@ -1176,7 +1308,11 @@ namespace tigl { cpp << ")"; } - void operator()(const ChoiceElements& ces, boost::optional parentChoice = {}) { + void operator()(const std::variant>& variant) { + std::visit(*this, variant); + } + + void operator()(const ChoiceElements& ces, std::optional> parentChoice = std::nullopt) { cpp << "("; { Scope s(cpp); @@ -1184,7 +1320,7 @@ namespace tigl { if (parentChoice) cpp << "// mandatory elements of this choice must be there"; for (const auto& ce : ces) { - ce.apply_visitor(*this); + std::visit(*this, ce); if (&ce != &ces.back()) cpp << "&&"; } @@ -1204,11 +1340,6 @@ namespace tigl { childCollector(ces); auto& childIndices = childCollector.indices; - auto unique = [](std::vector& v) { - std::sort(std::begin(v), std::end(v)); - const auto it = std::unique(std::begin(v), std::end(v)); - v.erase(it, std::end(v)); - }; unique(allIndices); unique(childIndices); @@ -1308,7 +1439,7 @@ namespace tigl { cpp << "{"; { Scope s(cpp); - cpp << f.fieldName() << ".push_back(make_unique<" << customReplacedType(f) << ">(" << ctorArgumentList(itC->second, c) << "));"; + cpp << f.fieldName() << ".push_back(std::make_unique<" << customReplacedType(f) << ">(" << ctorArgumentList(itC->second, c) << "));"; cpp << "return *" << f.fieldName() << ".back();"; } cpp << "}"; @@ -1451,7 +1582,7 @@ namespace tigl { if (vectorHeader) { deps.hppIncludes.push_back(""); if (makeUnique) { - deps.hppIncludes.push_back("\"UniquePtr.h\""); + deps.hppIncludes.push_back(""); } } if (optionalHeader) { @@ -1509,11 +1640,11 @@ namespace tigl { switch (f.cardinality()) { case Cardinality::Optional: case Cardinality::Mandatory: - deps.hppIncludes.push_back("<" + *p + ".h>"); + deps.hppIncludes.push_back("<" + p->get() + ".h>"); break; case Cardinality::Vector: deps.hppCustomForwards.push_back(*p); - deps.cppIncludes.push_back("<" + *p + ".h>"); + deps.cppIncludes.push_back("<" + p->get() + ".h>"); break; } } @@ -1526,8 +1657,8 @@ namespace tigl { for (const auto& dep : c.deps.parents) { const auto p = m_tables.m_customTypes.find(dep->name); if (p) { - deps.hppCustomForwards.push_back(*p); - deps.cppIncludes.push_back("\"" + *p + ".h\""); + deps.hppCustomForwards.push_back(p->get()); + deps.cppIncludes.push_back("\"" + p->get() + ".h\""); } else { deps.hppForwards.push_back(dep->name); deps.cppIncludes.push_back("\"" + dep->name + ".h\""); @@ -1548,7 +1679,16 @@ namespace tigl { return s[0] == '<'; }); // sort these groups individually - auto icmp = [](const std::string& a, const std::string& b) { return boost::ilexicographical_compare(a, b); }; + // ignore the (potential) capitalization + auto icmp = [](const std::string& a, const std::string& b) { + return std::lexicographical_compare( + a.begin(), a.end(), + b.begin(), b.end(), + [](unsigned char ac, unsigned char bc) { + return std::tolower(ac) < std::tolower(bc); + } + ); + }; std::sort(std::begin(includes), mid, icmp); std::sort(mid, std::end(includes), icmp); const auto& newMid = includes.erase(std::unique(std::begin(includes), mid), mid); @@ -1603,7 +1743,7 @@ namespace tigl { auto parentPointerThis(const Class& c) const -> std::string { const auto cust = m_tables.m_customTypes.find(c.name); if (cust) - return "reinterpret_cast<" + *cust + "*>(this)"; + return "reinterpret_cast<" + cust->get() + "*>(this)"; else return "this"; } @@ -1766,11 +1906,11 @@ namespace tigl { { Scope s(hpp); - boost::optional ops; + std::optional ops; if (!m_namespace.empty()) { hpp << "namespace " << m_namespace; hpp << "{"; - ops = boost::in_place(std::ref(hpp)); + ops.emplace(std::ref(hpp)); } // forward declarations @@ -1860,7 +2000,7 @@ namespace tigl { hpp << "};"; if (!m_namespace.empty()) { - ops = boost::none; + ops = std::nullopt; hpp << "}"; } } @@ -1874,7 +2014,7 @@ namespace tigl { std::vector exportedTypes; const auto& customName = m_tables.m_customTypes.find(c.name); if (customName) { - hpp << "// " << c.name << " is customized, use type " << *customName << " directly"; + hpp << "// " << c.name << " is customized, use type " << customName->get() << " directly"; if (includes.hppForwards.size() > 0) hpp << EmptyLine; } else @@ -1886,18 +2026,18 @@ namespace tigl { if (!exportedTypes.empty()) { hpp << "// Aliases in tigl namespace"; - boost::optional ops; + std::optional ops; if (!m_namespace.empty()) { hpp << "namespace " << m_namespace; hpp << "{"; - ops = boost::in_place(std::ref(hpp)); + ops.emplace(std::ref(hpp)); } for (const auto& name : exportedTypes) hpp << "using C" << name << " = " << generatedNs << "::" << name << ";"; if (!m_namespace.empty()) { - ops = boost::none; + ops = std::nullopt; hpp << "}"; } } @@ -1939,11 +2079,11 @@ namespace tigl { { Scope s(cpp); - boost::optional ops; + std::optional ops; if (!m_namespace.empty()) { cpp << "namespace " << m_namespace; cpp << "{"; - ops = boost::in_place(std::ref(cpp)); + ops.emplace(std::ref(cpp)); } // ctor @@ -1975,7 +2115,7 @@ namespace tigl { writeUidRefObjectFunctionImplementations(cpp, c); if (!m_namespace.empty()) { - ops = boost::none; + ops = std::nullopt; cpp << "}"; } } @@ -2036,11 +2176,11 @@ namespace tigl { { Scope s(hpp); - boost::optional ops; + std::optional ops; if (!m_namespace.empty()) { hpp << "namespace " << m_namespace; hpp << "{"; - ops = boost::in_place(std::ref(hpp)); + ops.emplace(std::ref(hpp)); } // meta information from schema @@ -2102,7 +2242,7 @@ namespace tigl { hpp << "}"; if (!m_namespace.empty()) { - ops = boost::none; + ops = std::nullopt; hpp << "}"; } } @@ -2114,19 +2254,19 @@ namespace tigl { const auto& customName = m_tables.m_customTypes.find(e.name); if (customName) { - hpp << "// " << e.name << " is customized, use type " << *customName << " directly"; + hpp << "// " << e.name << " is customized, use type " << customName->get() << " directly"; } else { hpp << "// Aliases in tigl namespace"; - boost::optional ops; + std::optional ops; if (!m_namespace.empty()) { hpp << "namespace " << m_namespace; hpp << "{"; - ops = boost::in_place(std::ref(hpp)); + ops.emplace(std::ref(hpp)); } hpp << "using E" << e.name << " = " << generatedNs << "::" << e.name << ";"; if (!m_namespace.empty()) { - ops = boost::none; + ops = std::nullopt; hpp << "}"; } } diff --git a/src/lib/Filesystem.cpp b/src/lib/Filesystem.cpp index cae3933..4fca62a 100644 --- a/src/lib/Filesystem.cpp +++ b/src/lib/Filesystem.cpp @@ -5,7 +5,7 @@ #include namespace tigl { - auto readFile(const boost::filesystem::path& filename) -> std::string { + auto readFile(const std::filesystem::path& filename) -> std::string { std::ifstream existingFile(filename.string()); if (!existingFile) return{}; @@ -20,10 +20,10 @@ namespace tigl { return content; } - File::File(boost::filesystem::path filename) + File::File(std::filesystem::path filename) : m_stream(new std::ostringstream), m_filename(std::move(filename)) {} - auto File::path() const -> const boost::filesystem::path& + auto File::path() const -> const std::filesystem::path& { return m_filename; } @@ -37,7 +37,7 @@ namespace tigl { const auto& newContent = file.m_stream->str(); // check if a file already exists - if (boost::filesystem::exists(file.m_filename)) { + if (std::filesystem::exists(file.m_filename)) { // read existing file to string and compare const auto& content = readFile(file.m_filename); @@ -60,19 +60,19 @@ namespace tigl { } } - auto Filesystem::newFile(boost::filesystem::path filename) -> File& { + auto Filesystem::newFile(std::filesystem::path filename) -> File& { m_files.emplace_back(std::move(filename)); return m_files.back(); } - void Filesystem::removeIfExists(const boost::filesystem::path& path) { - if (boost::filesystem::exists(path)) { - boost::filesystem::remove(path); + void Filesystem::removeIfExists(const std::filesystem::path& path) { + if (std::filesystem::exists(path)) { + std::filesystem::remove(path); deleted++; } } - void Filesystem::mergeFilesInto(boost::filesystem::path filename) { + void Filesystem::mergeFilesInto(std::filesystem::path filename) { File f(std::move(filename)); sortFiles(); for (auto& file : m_files) { diff --git a/src/lib/Filesystem.h b/src/lib/Filesystem.h index 26f8723..90cbd92 100644 --- a/src/lib/Filesystem.h +++ b/src/lib/Filesystem.h @@ -1,43 +1,42 @@ #pragma once -#include -#include +#include #include #include #include #include namespace tigl { - auto readFile(const boost::filesystem::path& filename) -> std::string; + auto readFile(const std::filesystem::path& filename) -> std::string; class Filesystem; class File { public: - File(boost::filesystem::path filename); + File(std::filesystem::path filename); File(const File&) = delete; File& operator=(const File&) = delete; File(File&&) = default; File& operator=(File&&) = default; - auto path() const -> const boost::filesystem::path&; + auto path() const -> const std::filesystem::path&; auto stream() -> std::ostream&; private: friend class Filesystem; std::unique_ptr m_stream; // workaround for GCC < 5.0, where stringstream is not moveable .. - boost::filesystem::path m_filename; + std::filesystem::path m_filename; }; class Filesystem { public: Filesystem() = default; - auto newFile(boost::filesystem::path filename) -> File&; - void removeIfExists(const boost::filesystem::path& path); + auto newFile(std::filesystem::path filename) -> File&; + void removeIfExists(const std::filesystem::path& path); - void mergeFilesInto(boost::filesystem::path filename); + void mergeFilesInto(std::filesystem::path filename); void flushToDisk(); diff --git a/src/lib/SchemaParser.cpp b/src/lib/SchemaParser.cpp index 31737ca..33b045d 100644 --- a/src/lib/SchemaParser.cpp +++ b/src/lib/SchemaParser.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include @@ -256,9 +256,11 @@ namespace tigl { const auto childXPath = (name == "#text") ? xpath + "/text()[" + std::to_string(++childIndex[name]) + "]" : xpath; auto text = document.textElement(childXPath); - static boost::regex r("^\\s*"); - text = boost::regex_replace(text, r, ""); // clear leading whitespace on each line - boost::trim_right(text); // clear trailing whitespace after last line + static std::regex r("^\\s*"); + text = std::regex_replace(text, r, ""); // clear leading whitespace on each line + // clear trailing whitespace after last line + text.erase(std::find_if_not(text.rbegin(), text.rend(), [](unsigned char ch) { return std::isspace(ch); }).base(), + text.end()); if (!result.empty() && result.back() != '\n') result += ' '; result += text; diff --git a/src/lib/Tables.cpp b/src/lib/Tables.cpp index eac0212..e82e6a3 100644 --- a/src/lib/Tables.cpp +++ b/src/lib/Tables.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "Tables.h" @@ -75,15 +76,15 @@ namespace tigl { } bool MappingTable::contains(const std::string& key) const { - return find(key).is_initialized(); + return find(key).has_value(); } - boost::optional MappingTable::find(const std::string& key) const { + std::optional> MappingTable::find(const std::string& key) const { const auto it = m_map.find(key); if (it != std::end(m_map)) return it->second; else - return {}; + return std::nullopt; } void MappingTable::substituteIfExists(const std::string& key, std::string& value) const { diff --git a/src/lib/Tables.h b/src/lib/Tables.h index beb766b..be91025 100644 --- a/src/lib/Tables.h +++ b/src/lib/Tables.h @@ -1,9 +1,9 @@ #pragma once -#include #include #include #include +#include namespace tigl { class Table { @@ -25,7 +25,7 @@ namespace tigl { MappingTable(const std::string& filename); bool contains(const std::string& key) const; - boost::optional find(const std::string& key) const; + std::optional> find(const std::string& key) const; void substituteIfExists(const std::string& key, std::string& value) const; private: diff --git a/src/lib/TypeSystem.cpp b/src/lib/TypeSystem.cpp index fb9c160..9f678e5 100644 --- a/src/lib/TypeSystem.cpp +++ b/src/lib/TypeSystem.cpp @@ -1,11 +1,14 @@ #include "TypeSystem.h" -#include -#include #include #include #include +#include +#include +#include +#include +#include #include "NotImplementedException.h" #include "Tables.h" @@ -76,9 +79,9 @@ namespace tigl { } // elements - struct ContentVisitor : public boost::static_visitor<> { + struct ContentVisitor { ContentVisitor(const xsd::SchemaTypes& types, std::vector& members, ChoiceElements& choiceItems, std::size_t attributeCount, const Tables& tables, std::vector choiceIndices = {}) - : types(types), members(members), choiceItems(choiceItems), attributeCount(attributeCount), tables(tables), choiceIndices(choiceIndices) {} + : types(types), members(members), choiceItems(choiceItems), attributeCount(attributeCount), tables(tables), choiceIndices(std::move(choiceIndices)) {} void emitField(Field f) const { if (!choiceIndices.empty()) { @@ -87,7 +90,14 @@ namespace tigl { f.minOccurs = 0; // give custom name - f.namePostfix = "_choice" + boost::join(choiceIndices | boost::adaptors::transformed([](std::size_t i) { return std::to_string(i); }), "_"); + std::ostringstream oss; + oss << "_choice"; + for (std::size_t i = 0; i < choiceIndices.size(); ++i) { + oss << choiceIndices[i]; + if (i + 1 < choiceIndices.size()) + oss << "_"; + } + f.namePostfix = oss.str(); choiceItems.push_back(ChoiceElement{ members.size(), minBefore == 0 }); } @@ -118,15 +128,14 @@ namespace tigl { Choice choice; choice.minOccurs = c.minOccurs; - for (const auto& v : c.elements | boost::adaptors::indexed(1)) { - // collect members of one choice + for (std::size_t idx = 0; idx < c.elements.size(); ++idx) { auto indices = choiceIndices; - indices.push_back(v.index()); + indices.push_back(idx + 1); // Index starting at 1 ChoiceElements subChoiceItems; - v.value().visit(ContentVisitor(types, members, subChoiceItems, attributeCount, tables, indices)); + c.elements[idx].visit(ContentVisitor(types, members, subChoiceItems, attributeCount, tables, indices)); choice.options.push_back(std::move(subChoiceItems)); } - choiceItems.push_back(std::move(choice)); + choiceItems.push_back(std::make_shared(std::move(choice))); // consistency check, two types with the same name but different types or cardinality are problematic for (std::size_t i = countBefore; i < members.size(); i++) { diff --git a/src/lib/TypeSystem.h b/src/lib/TypeSystem.h index d578fa2..1fa91ed 100644 --- a/src/lib/TypeSystem.h +++ b/src/lib/TypeSystem.h @@ -1,13 +1,14 @@ #pragma once -#include - #include #include #include #include #include #include +#include +#include +#include #include "Variant.hpp" #include "SchemaParser.h" @@ -100,7 +101,7 @@ namespace tigl { }; struct Choice; - using ChoiceElements = std::vector>>; + using ChoiceElements = std::vector>>; struct Choice { unsigned int minOccurs; diff --git a/src/lib/Variant.hpp b/src/lib/Variant.hpp index 24c12a0..5803220 100644 --- a/src/lib/Variant.hpp +++ b/src/lib/Variant.hpp @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include +#include namespace tigl { template @@ -42,7 +42,7 @@ namespace tigl { void visit(Visitor func) { if (m_data) { VisitorWrapper visitor(func); - m_data->apply_visitor(visitor); + std::visit(visitor, *m_data); } } @@ -50,33 +50,33 @@ namespace tigl { void visit(Visitor func) const { if (m_data) { VisitorWrapper visitor(func); - m_data->apply_visitor(visitor); + std::visit(visitor, *m_data); } } template bool is() const { if (m_data) - return m_data->type() == typeid(T); + return std::holds_alternative(*m_data); return false; } template T& as() { - return boost::get(*m_data); + return std::get(*m_data); } template const T& as() const { - return boost::get(*m_data); + return std::get(*m_data); } private: // adapts a visitor for boost template - struct VisitorWrapper : public boost::static_visitor<> { - VisitorWrapper(Func func) - : m_func(func) {} + struct VisitorWrapper { + explicit VisitorWrapper(Func func) + : m_func(std::move(func)) {} template void operator()(T&& arg) { @@ -87,6 +87,6 @@ namespace tigl { Func m_func; }; - boost::optional> m_data; + std::optional> m_data; }; } diff --git a/src/lib/runtime/TixiHelper.h b/src/lib/runtime/TixiHelper.h index 49c1567..327909e 100644 --- a/src/lib/runtime/TixiHelper.h +++ b/src/lib/runtime/TixiHelper.h @@ -19,16 +19,18 @@ #include -#ifndef BOOST_DATE_TIME_NO_LIB - #define BOOST_DATE_TIME_NO_LIB -#endif -#include +#include #include #include #include +#include +#include +#include +#include +#include -#include "UniquePtr.h" +#include #ifndef CPACS_GEN #include "CTiglLogging.h" #endif @@ -38,7 +40,13 @@ namespace tixi { inline std::time_t TixiGetTimeTElement(const TixiDocumentHandle& tixiHandle, const std::string& xpath) { - return boost::posix_time::to_time_t(boost::posix_time::from_iso_extended_string(TixiGetTextElement(tixiHandle, xpath))); + std::string datetimeStr = TixiGetTextElement(tixiHandle, xpath); + + std::tm tm = {}; + std::istringstream ss(datetimeStr); + ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S"); + + return std::mktime(&tm); } template<> @@ -47,9 +55,16 @@ namespace tixi return TixiGetTimeTElement(tixiHandle, xpath); } + inline std::string to_iso_extended_string(std::time_t value) + { + std::ostringstream oss; + oss << std::put_time(std::gmtime(&value), "%Y-%m-%dT%H:%M:%S"); + return oss.str(); + } + inline void TixiSaveElement(const TixiDocumentHandle& tixiHandle, const std::string& xpath, std::time_t value) { - TixiSaveElement(tixiHandle, xpath, boost::posix_time::to_iso_extended_string(boost::posix_time::from_time_t(value))); + TixiSaveElement(tixiHandle, xpath, to_iso_extended_string(value)); } constexpr auto xsdUnbounded = std::numeric_limits::max(); @@ -108,23 +123,11 @@ namespace tixi template void TixiReadElements(const TixiDocumentHandle& tixiHandle, const std::string& xpath, std::vector>& children, unsigned int minOccurs, unsigned int maxOccurs, ChildCtorArgs&&... args) { - // TODO(bgruber): enable when support for g++ < 4.9.0 is dropped - //TixiReadElementsInternal(tixiHandle, xpath, children, minOccurs, maxOccurs, [&](const std::string& childXPath) { - // auto child = tigl::make_unique(std::forward(args)...); - // child->ReadCPACS(tixiHandle, childXPath); - // return child; - //}); - struct Reader { - std::unique_ptr operator()(const std::string& childXPath, ChildCtorArgs&&... args) const - { - auto child = tigl::make_unique(std::forward(args)...); - child->ReadCPACS(tixiHandle, childXPath); - return child; - } - - const TixiDocumentHandle& tixiHandle; - }; - TixiReadElementsInternal(tixiHandle, xpath, children, minOccurs, maxOccurs, Reader{tixiHandle}, std::forward(args)...); + TixiReadElementsInternal(tixiHandle, xpath, children, minOccurs, maxOccurs, [&](const std::string& childXPath) { + auto child = std::make_unique(std::forward(args)...); + child->ReadCPACS(tixiHandle, childXPath); + return child; + }); } template @@ -172,6 +175,20 @@ namespace tixi TixiSaveElementsInternal(tixiHandle, xpath, children, writer); } + inline bool TixiCheckElementHasTextContent(const TixiDocumentHandle& tixiHandle, const std::string& xpath) + { + if (!TixiCheckElement(tixiHandle, xpath)) { + return false; + } + try { + std::string text = TixiGetTextElement(tixiHandle, xpath); + return !text.empty(); + } + catch (const TixiError&) { + return false; + } + } + inline void TixiCreateSequenceElementIfNotExists(const TixiDocumentHandle& tixiHandle, const std::string& xpath, const std::vector& childElemOrder) { // in case element already exists, nothing left to do diff --git a/src/lib/runtime/UniquePtr.h b/src/lib/runtime/UniquePtr.h deleted file mode 100644 index d0f5ccd..0000000 --- a/src/lib/runtime/UniquePtr.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2016 RISC Software GmbH -// -// This file is part of the CPACSGen runtime. -// Do not edit, all changes are lost when files are re-deployed. -// -// Licensed under the Apache License, Version 2.0 (the "License") -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#include - -namespace tigl -{ - template - using unique_ptr [[deprecated]] = std::unique_ptr; - - template - auto make_unique(Args&&... args) -> std::unique_ptr - { - return std::unique_ptr(new T(std::forward(args)...)); - } -} diff --git a/test/data/all/CustomTypes.txt b/test/data/all/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/all/ParentPointer.txt b/test/data/all/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/all/PruneList.txt b/test/data/all/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/all/TypeSubstitution.txt b/test/data/all/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/all/ref.cpp b/test/data/all/ref.cpp index 6f59bea..66662c2 100644 --- a/test/data/all/ref.cpp +++ b/test/data/all/ref.cpp @@ -132,7 +132,7 @@ namespace generated void CPACSRoot::ReadCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) { // read element a - if (tixi::TixiCheckElement(tixiHandle, xpath + "/a")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/a")) { m_a = tixi::TixiGetElement(tixiHandle, xpath + "/a"); } else { @@ -140,12 +140,12 @@ namespace generated } // read element b - if (tixi::TixiCheckElement(tixiHandle, xpath + "/b")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/b")) { m_b = tixi::TixiGetElement(tixiHandle, xpath + "/b"); } // read element c - if (tixi::TixiCheckElement(tixiHandle, xpath + "/c")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/c")) { m_c = tixi::TixiGetElement(tixiHandle, xpath + "/c"); } else { @@ -153,7 +153,7 @@ namespace generated } // read element d - if (tixi::TixiCheckElement(tixiHandle, xpath + "/d")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/d")) { m_d = tixi::TixiGetElement(tixiHandle, xpath + "/d"); } else { @@ -161,12 +161,12 @@ namespace generated } // read element e - if (tixi::TixiCheckElement(tixiHandle, xpath + "/e")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/e")) { m_e = tixi::TixiGetElement(tixiHandle, xpath + "/e"); } // read element f - if (tixi::TixiCheckElement(tixiHandle, xpath + "/f")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/f")) { m_f = tixi::TixiGetElement(tixiHandle, xpath + "/f"); } else { diff --git a/test/data/basetypewithparent/CustomTypes.txt b/test/data/basetypewithparent/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/basetypewithparent/PruneList.txt b/test/data/basetypewithparent/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/basetypewithparent/TypeSubstitution.txt b/test/data/basetypewithparent/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/basetypewithparent/ref.cpp b/test/data/basetypewithparent/ref.cpp index c21a790..bcf8746 100644 --- a/test/data/basetypewithparent/ref.cpp +++ b/test/data/basetypewithparent/ref.cpp @@ -613,7 +613,7 @@ namespace generated } // read element name - if (tixi::TixiCheckElement(tixiHandle, xpath + "/name")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/name")) { m_name = tixi::TixiGetElement(tixiHandle, xpath + "/name"); if (m_name->empty()) { LOG(WARNING) << "Optional element name is present but empty at xpath " << xpath; diff --git a/test/data/cdata/CustomTypes.txt b/test/data/cdata/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/cdata/ParentPointer.txt b/test/data/cdata/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/cdata/PruneList.txt b/test/data/cdata/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/cdata/TypeSubstitution.txt b/test/data/cdata/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/cdata/ref.cpp b/test/data/cdata/ref.cpp index 52a7ecb..4d215f9 100644 --- a/test/data/cdata/ref.cpp +++ b/test/data/cdata/ref.cpp @@ -34,6 +34,7 @@ namespace generated /// This XML-Schema document ( XSD ) serves two purposes: (1) it defines the CPACS data structure used in the XML file (e.g., aircraft.xml) and /// (2) it provides the corresponding documentation (see picture below). An XML processor (e.g., TiXI https://github.com/DLR-SC/tixi or /// XML tools in Eclipse) parses the XSD and XML files and validates whether the data set defined by the user (or tool) conforms to the given structure defined by the schema. + /// @see basicPrinciple /// This documentation explains the elements defined in CPACS and its corresponding data types . /// Data types can either be simple types (string, double, boolean, etc.) or complex types (definition of attributes and sub-elements to build a hierarchical /// structure). In addition, the sequence of the elements and their occurrence is documented. @@ -145,7 +146,7 @@ namespace generated } // read element a - if (tixi::TixiCheckElement(tixiHandle, xpath + "/a")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/a")) { m_a = tixi::TixiGetElement(tixiHandle, xpath + "/a"); } else { @@ -153,7 +154,7 @@ namespace generated } // read element b - if (tixi::TixiCheckElement(tixiHandle, xpath + "/b")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/b")) { m_b = tixi::TixiGetElement(tixiHandle, xpath + "/b"); } else { diff --git a/test/data/cdata/schema.xsd b/test/data/cdata/schema.xsd index 1a8699e..a87c989 100644 --- a/test/data/cdata/schema.xsd +++ b/test/data/cdata/schema.xsd @@ -16,7 +16,7 @@ (2) it provides the corresponding documentation (see picture below). An XML processor (e.g., TiXIhttps://github.com/DLR-SC/tixi or XML tools in Eclipse) parses the XSD and XML files and validates whether the data set defined by the user (or tool) conforms to the given structure defined by the schema. - + This documentation explains the elements defined in CPACS and its corresponding data types. Data types can either be simple types (string, double, boolean, etc.) or diff --git a/test/data/choice/CustomTypes.txt b/test/data/choice/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/choice/ParentPointer.txt b/test/data/choice/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/choice/PruneList.txt b/test/data/choice/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/choice/TypeSubstitution.txt b/test/data/choice/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/choice/ref.cpp b/test/data/choice/ref.cpp index d7971dc..edaddb5 100644 --- a/test/data/choice/ref.cpp +++ b/test/data/choice/ref.cpp @@ -114,12 +114,12 @@ namespace generated void CPACSRoot::ReadCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) { // read element a - if (tixi::TixiCheckElement(tixiHandle, xpath + "/a")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/a")) { m_a_choice1 = tixi::TixiGetElement(tixiHandle, xpath + "/a"); } // read element b - if (tixi::TixiCheckElement(tixiHandle, xpath + "/b")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/b")) { m_b_choice2 = tixi::TixiGetElement(tixiHandle, xpath + "/b"); } diff --git a/test/data/collapsedifferentenums/CustomTypes.txt b/test/data/collapsedifferentenums/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/collapsedifferentenums/ParentPointer.txt b/test/data/collapsedifferentenums/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/collapsedifferentenums/PruneList.txt b/test/data/collapsedifferentenums/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/collapsedifferentenums/TypeSubstitution.txt b/test/data/collapsedifferentenums/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/complextypewithsimplecontent/CustomTypes.txt b/test/data/complextypewithsimplecontent/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/complextypewithsimplecontent/ParentPointer.txt b/test/data/complextypewithsimplecontent/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/complextypewithsimplecontent/PruneList.txt b/test/data/complextypewithsimplecontent/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/complextypewithsimplecontent/ref.cpp b/test/data/complextypewithsimplecontent/ref.cpp index ad299b5..a279e4f 100644 --- a/test/data/complextypewithsimplecontent/ref.cpp +++ b/test/data/complextypewithsimplecontent/ref.cpp @@ -417,7 +417,7 @@ namespace generated } // read simpleContent - if (tixi::TixiCheckElement(tixiHandle, xpath)) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath)) { m_value = tixi::TixiGetElement(tixiHandle, xpath); if (m_value.empty()) { LOG(WARNING) << "Required element is empty at xpath " << xpath; @@ -885,7 +885,7 @@ namespace generated } // read simpleContent - if (tixi::TixiCheckElement(tixiHandle, xpath)) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath)) { m_value = tixi::TixiGetElement(tixiHandle, xpath); if (m_value.empty()) { LOG(WARNING) << "Required element is empty at xpath " << xpath; diff --git a/test/data/custombasetype/ParentPointer.txt b/test/data/custombasetype/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/custombasetype/PruneList.txt b/test/data/custombasetype/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/custombasetype/TypeSubstitution.txt b/test/data/custombasetype/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/custombasetype/ref.cpp b/test/data/custombasetype/ref.cpp index cf8ade7..92a45e6 100644 --- a/test/data/custombasetype/ref.cpp +++ b/test/data/custombasetype/ref.cpp @@ -247,7 +247,7 @@ namespace generated } // read element name - if (tixi::TixiCheckElement(tixiHandle, xpath + "/name")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/name")) { m_name = tixi::TixiGetElement(tixiHandle, xpath + "/name"); if (m_name->empty()) { LOG(WARNING) << "Optional element name is present but empty at xpath " << xpath; diff --git a/test/data/documentation/CustomTypes.txt b/test/data/documentation/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/documentation/ParentPointer.txt b/test/data/documentation/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/documentation/PruneList.txt b/test/data/documentation/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/documentation/TypeSubstitution.txt b/test/data/documentation/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/documentation/ref.cpp b/test/data/documentation/ref.cpp index 70bef0d..9539ab2 100644 --- a/test/data/documentation/ref.cpp +++ b/test/data/documentation/ref.cpp @@ -136,7 +136,7 @@ namespace generated } // read element a - if (tixi::TixiCheckElement(tixiHandle, xpath + "/a")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/a")) { m_a = tixi::TixiGetElement(tixiHandle, xpath + "/a"); } else { @@ -144,7 +144,7 @@ namespace generated } // read element b - if (tixi::TixiCheckElement(tixiHandle, xpath + "/b")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/b")) { m_b = tixi::TixiGetElement(tixiHandle, xpath + "/b"); } else { diff --git a/test/data/elementtextcontent/CPACSRoot.cpp b/test/data/elementtextcontent/CPACSRoot.cpp new file mode 100644 index 0000000..147a4cd --- /dev/null +++ b/test/data/elementtextcontent/CPACSRoot.cpp @@ -0,0 +1,155 @@ +// Copyright (c) 2020 RISC Software GmbH +// +// This file was generated by CPACSGen from CPACS XML Schema (c) German Aerospace Center (DLR/SC). +// Do not edit, all changes are lost when files are re-generated. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "CPACSRoot.h" +#include "CTiglError.h" +#include "CTiglLogging.h" +#include "CTiglUIDObject.h" +#include "TixiHelper.h" + +namespace tigl +{ +namespace generated +{ + CPACSRoot::CPACSRoot() + : m_mandatoryDouble(0) + , m_mandatoryInt(0) + { + } + + CPACSRoot::~CPACSRoot() + { + } + + const CTiglUIDObject* CPACSRoot::GetNextUIDParent() const + { + return nullptr; + } + + CTiglUIDObject* CPACSRoot::GetNextUIDParent() + { + return nullptr; + } + + void CPACSRoot::ReadCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) + { + // read element optionalDouble + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/optionalDouble")) { + m_optionalDouble = tixi::TixiGetElement(tixiHandle, xpath + "/optionalDouble"); + } + + // read element mandatoryDouble + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/mandatoryDouble")) { + m_mandatoryDouble = tixi::TixiGetElement(tixiHandle, xpath + "/mandatoryDouble"); + } + else { + LOG(ERROR) << "Required element mandatoryDouble is missing at xpath " << xpath; + } + + // read element optionalInt + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/optionalInt")) { + m_optionalInt = tixi::TixiGetElement(tixiHandle, xpath + "/optionalInt"); + } + + // read element mandatoryInt + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/mandatoryInt")) { + m_mandatoryInt = tixi::TixiGetElement(tixiHandle, xpath + "/mandatoryInt"); + } + else { + LOG(ERROR) << "Required element mandatoryInt is missing at xpath " << xpath; + } + + } + + void CPACSRoot::WriteCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) const + { + const std::vector childElemOrder = { "optionalDouble", "mandatoryDouble", "optionalInt", "mandatoryInt" }; + + // write element optionalDouble + if (m_optionalDouble) { + tixi::TixiCreateSequenceElementIfNotExists(tixiHandle, xpath + "/optionalDouble", childElemOrder); + tixi::TixiSaveElement(tixiHandle, xpath + "/optionalDouble", *m_optionalDouble); + } + else { + if (tixi::TixiCheckElement(tixiHandle, xpath + "/optionalDouble")) { + tixi::TixiRemoveElement(tixiHandle, xpath + "/optionalDouble"); + } + } + + // write element mandatoryDouble + tixi::TixiCreateSequenceElementIfNotExists(tixiHandle, xpath + "/mandatoryDouble", childElemOrder); + tixi::TixiSaveElement(tixiHandle, xpath + "/mandatoryDouble", m_mandatoryDouble); + + // write element optionalInt + if (m_optionalInt) { + tixi::TixiCreateSequenceElementIfNotExists(tixiHandle, xpath + "/optionalInt", childElemOrder); + tixi::TixiSaveElement(tixiHandle, xpath + "/optionalInt", *m_optionalInt); + } + else { + if (tixi::TixiCheckElement(tixiHandle, xpath + "/optionalInt")) { + tixi::TixiRemoveElement(tixiHandle, xpath + "/optionalInt"); + } + } + + // write element mandatoryInt + tixi::TixiCreateSequenceElementIfNotExists(tixiHandle, xpath + "/mandatoryInt", childElemOrder); + tixi::TixiSaveElement(tixiHandle, xpath + "/mandatoryInt", m_mandatoryInt); + + } + + const boost::optional& CPACSRoot::GetOptionalDouble() const + { + return m_optionalDouble; + } + + void CPACSRoot::SetOptionalDouble(const boost::optional& value) + { + m_optionalDouble = value; + } + + const double& CPACSRoot::GetMandatoryDouble() const + { + return m_mandatoryDouble; + } + + void CPACSRoot::SetMandatoryDouble(const double& value) + { + m_mandatoryDouble = value; + } + + const boost::optional& CPACSRoot::GetOptionalInt() const + { + return m_optionalInt; + } + + void CPACSRoot::SetOptionalInt(const boost::optional& value) + { + m_optionalInt = value; + } + + const int& CPACSRoot::GetMandatoryInt() const + { + return m_mandatoryInt; + } + + void CPACSRoot::SetMandatoryInt(const int& value) + { + m_mandatoryInt = value; + } + +} // namespace generated +} // namespace tigl diff --git a/test/data/elementtextcontent/CPACSRoot.h b/test/data/elementtextcontent/CPACSRoot.h new file mode 100644 index 0000000..f3a5c6e --- /dev/null +++ b/test/data/elementtextcontent/CPACSRoot.h @@ -0,0 +1,74 @@ +// Copyright (c) 2020 RISC Software GmbH +// +// This file was generated by CPACSGen from CPACS XML Schema (c) German Aerospace Center (DLR/SC). +// Do not edit, all changes are lost when files are re-generated. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include +#include "tigl_internal.h" + +namespace tigl +{ +class CTiglUIDObject; + +namespace generated +{ + // This class is used in: + class CPACSRoot + { + public: + TIGL_EXPORT CPACSRoot(); + TIGL_EXPORT virtual ~CPACSRoot(); + + TIGL_EXPORT virtual CTiglUIDObject* GetNextUIDParent(); + TIGL_EXPORT virtual const CTiglUIDObject* GetNextUIDParent() const; + + TIGL_EXPORT virtual void ReadCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath); + TIGL_EXPORT virtual void WriteCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) const; + + TIGL_EXPORT virtual const boost::optional& GetOptionalDouble() const; + TIGL_EXPORT virtual void SetOptionalDouble(const boost::optional& value); + + TIGL_EXPORT virtual const double& GetMandatoryDouble() const; + TIGL_EXPORT virtual void SetMandatoryDouble(const double& value); + + TIGL_EXPORT virtual const boost::optional& GetOptionalInt() const; + TIGL_EXPORT virtual void SetOptionalInt(const boost::optional& value); + + TIGL_EXPORT virtual const int& GetMandatoryInt() const; + TIGL_EXPORT virtual void SetMandatoryInt(const int& value); + + protected: + boost::optional m_optionalDouble; + double m_mandatoryDouble; + boost::optional m_optionalInt; + int m_mandatoryInt; + + private: + CPACSRoot(const CPACSRoot&) = delete; + CPACSRoot& operator=(const CPACSRoot&) = delete; + + CPACSRoot(CPACSRoot&&) = delete; + CPACSRoot& operator=(CPACSRoot&&) = delete; + }; +} // namespace generated + +// Aliases in tigl namespace +using CCPACSRoot = generated::CPACSRoot; +} // namespace tigl diff --git a/test/data/elementtextcontent/TixiHelper.h b/test/data/elementtextcontent/TixiHelper.h new file mode 100644 index 0000000..327909e --- /dev/null +++ b/test/data/elementtextcontent/TixiHelper.h @@ -0,0 +1,217 @@ +// Copyright (c) 2017 RISC Software GmbH +// +// This file is part of the CPACSGen runtime. +// Do not edit, all changes are lost when files are re-generated. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef CPACS_GEN +#include "CTiglLogging.h" +#endif + +// some extensions to tixi +namespace tixi +{ + inline std::time_t TixiGetTimeTElement(const TixiDocumentHandle& tixiHandle, const std::string& xpath) + { + std::string datetimeStr = TixiGetTextElement(tixiHandle, xpath); + + std::tm tm = {}; + std::istringstream ss(datetimeStr); + ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S"); + + return std::mktime(&tm); + } + + template<> + inline std::time_t TixiGetElement(const TixiDocumentHandle& tixiHandle, const std::string& xpath) + { + return TixiGetTimeTElement(tixiHandle, xpath); + } + + inline std::string to_iso_extended_string(std::time_t value) + { + std::ostringstream oss; + oss << std::put_time(std::gmtime(&value), "%Y-%m-%dT%H:%M:%S"); + return oss.str(); + } + + inline void TixiSaveElement(const TixiDocumentHandle& tixiHandle, const std::string& xpath, std::time_t value) + { + TixiSaveElement(tixiHandle, xpath, to_iso_extended_string(value)); + } + + constexpr auto xsdUnbounded = std::numeric_limits::max(); + + template + void TixiReadElementsInternal(const TixiDocumentHandle& tixiHandle, const std::string& xpath, std::vector& children, unsigned int minOccurs, unsigned int maxOccurs, ReadChildFunc readChild, ChildCtorArgs&&... args) + { + // read number of child nodes + const auto childCount = static_cast(TixiGetNamedChildrenCount(tixiHandle, xpath)); + + // validate number of child nodes + if (childCount < minOccurs) { +#ifndef CPACS_GEN + LOG(ERROR) + << "Not enough child nodes for element\n" + << "xpath: " << xpath << "\n" + << "minimum: " << minOccurs << "\n" + << "actual: " << childCount; +#endif + } + + if (childCount > maxOccurs) { + // TODO: replace by exception/warning +#ifndef CPACS_GEN + LOG(ERROR) + << "Too many child nodes for element\n" + << "xpath: " << xpath << "\n" + << "maximum: " << maxOccurs << "\n" + << "actual: " << childCount; +#endif + } + + // read child nodes + for (unsigned int i = 0; i < childCount; i++) { + const std::string childXPath = xpath + "[" + std::to_string(i + 1) + "]"; + try { + children.push_back(readChild(childXPath, std::forward(args)...)); + } catch (const std::exception& e) { +#ifdef CPACS_GEN + throw; +#else + LOG(ERROR) << "Failed to read element at xpath " << childXPath << ": " << e.what(); +#endif + } + } + } + + template + void TixiReadElements(const TixiDocumentHandle& tixiHandle, const std::string& xpath, std::vector& children, unsigned int minOccurs, unsigned int maxOccurs) + { + TixiReadElementsInternal(tixiHandle, xpath, children, minOccurs, maxOccurs, [&](const std::string& childXPath) { + return TixiGetElement(tixiHandle, childXPath); + }); + } + + template + void TixiReadElements(const TixiDocumentHandle& tixiHandle, const std::string& xpath, std::vector>& children, unsigned int minOccurs, unsigned int maxOccurs, ChildCtorArgs&&... args) + { + TixiReadElementsInternal(tixiHandle, xpath, children, minOccurs, maxOccurs, [&](const std::string& childXPath) { + auto child = std::make_unique(std::forward(args)...); + child->ReadCPACS(tixiHandle, childXPath); + return child; + }); + } + + template + void TixiSaveElementsInternal(const TixiDocumentHandle& tixiHandle, const std::string& xpath, const std::vector& children, WriteChildFunc writeChild) + { + // get number of children + const int childCount = TixiGetNamedChildrenCount(tixiHandle, xpath); + + // test if we have children to write + if (children.size() > 0) { + // iteratore over all child nodes + for (std::size_t i = 0; i < children.size(); i++) { + // if child node does not exist, create it + const std::string& childPath = xpath + "[" + std::to_string(i + 1) + "]"; + if (!TixiCheckElement(tixiHandle, childPath)) { + TixiCreateElement(tixiHandle, xpath); + } + + // write child node + writeChild(childPath, children[i]); + } + } + + // delete old children which where not overwritten + for (std::size_t i = children.size() + 1; i <= static_cast(childCount); i++) { + TixiRemoveElement(tixiHandle, xpath + "[" + std::to_string(children.size() + 1) + "]"); + } + } + + template + void TixiSaveElements(const TixiDocumentHandle& tixiHandle, const std::string& xpath, const std::vector& children) + { + auto writer = [&](const std::string& childXPath, const T& child) { + TixiSaveElement(tixiHandle, childXPath, child); + }; + TixiSaveElementsInternal(tixiHandle, xpath, children, writer); + } + + template + void TixiSaveElements(const TixiDocumentHandle& tixiHandle, const std::string& xpath, const std::vector>& children) + { + auto writer = [&](const std::string& childXPath, const std::unique_ptr& child) { + child->WriteCPACS(tixiHandle, childXPath); + }; + TixiSaveElementsInternal(tixiHandle, xpath, children, writer); + } + + inline bool TixiCheckElementHasTextContent(const TixiDocumentHandle& tixiHandle, const std::string& xpath) + { + if (!TixiCheckElement(tixiHandle, xpath)) { + return false; + } + try { + std::string text = TixiGetTextElement(tixiHandle, xpath); + return !text.empty(); + } + catch (const TixiError&) { + return false; + } + } + + inline void TixiCreateSequenceElementIfNotExists(const TixiDocumentHandle& tixiHandle, const std::string& xpath, const std::vector& childElemOrder) + { + // in case element already exists, nothing left to do + if (TixiCheckElement(tixiHandle, xpath)) { + return; + } + const auto sp = internal::splitXPath(xpath); + const auto numChildren = tixi::TixiGetNumberOfChilds(tixiHandle, sp.parentXPath); + // find place of new element in sequence + auto it = std::find(childElemOrder.begin(), childElemOrder.end(), sp.element); + if (numChildren > 0 && it != childElemOrder.end()) { + // search for the first existing element which has to be after the new element + while (++it != childElemOrder.end()) { + for (int i = 1; i <= numChildren; i++) { + if (TixiGetChildNodeName(tixiHandle, sp.parentXPath, i) == *it) { + tixiCreateElementAtIndex(tixiHandle, sp.parentXPath.c_str(), sp.element.c_str(), i); + return; + } + } + } + } + // in case no place for insertion was found append the new element + TixiCreateElement(tixiHandle, xpath); + } + +} diff --git a/test/data/elementtextcontent/ref.cpp b/test/data/elementtextcontent/ref.cpp new file mode 100644 index 0000000..bf7dc9e --- /dev/null +++ b/test/data/elementtextcontent/ref.cpp @@ -0,0 +1,229 @@ +// Copyright (c) 2020 RISC Software GmbH +// +// This file was generated by CPACSGen from CPACS XML Schema (c) German Aerospace Center (DLR/SC). +// Do not edit, all changes are lost when files are re-generated. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include +#include "tigl_internal.h" + +namespace tigl +{ +class CTiglUIDObject; + +namespace generated +{ + // This class is used in: + class CPACSRoot + { + public: + TIGL_EXPORT CPACSRoot(); + TIGL_EXPORT virtual ~CPACSRoot(); + + TIGL_EXPORT virtual CTiglUIDObject* GetNextUIDParent(); + TIGL_EXPORT virtual const CTiglUIDObject* GetNextUIDParent() const; + + TIGL_EXPORT virtual void ReadCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath); + TIGL_EXPORT virtual void WriteCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) const; + + TIGL_EXPORT virtual const boost::optional& GetOptionalDouble() const; + TIGL_EXPORT virtual void SetOptionalDouble(const boost::optional& value); + + TIGL_EXPORT virtual const double& GetMandatoryDouble() const; + TIGL_EXPORT virtual void SetMandatoryDouble(const double& value); + + TIGL_EXPORT virtual const boost::optional& GetOptionalInt() const; + TIGL_EXPORT virtual void SetOptionalInt(const boost::optional& value); + + TIGL_EXPORT virtual const int& GetMandatoryInt() const; + TIGL_EXPORT virtual void SetMandatoryInt(const int& value); + + protected: + boost::optional m_optionalDouble; + double m_mandatoryDouble; + boost::optional m_optionalInt; + int m_mandatoryInt; + + private: + CPACSRoot(const CPACSRoot&) = delete; + CPACSRoot& operator=(const CPACSRoot&) = delete; + + CPACSRoot(CPACSRoot&&) = delete; + CPACSRoot& operator=(CPACSRoot&&) = delete; + }; +} // namespace generated + +// Aliases in tigl namespace +using CCPACSRoot = generated::CPACSRoot; +} // namespace tigl +// Copyright (c) 2020 RISC Software GmbH +// +// This file was generated by CPACSGen from CPACS XML Schema (c) German Aerospace Center (DLR/SC). +// Do not edit, all changes are lost when files are re-generated. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "CPACSRoot.h" +#include "CTiglError.h" +#include "CTiglLogging.h" +#include "CTiglUIDObject.h" +#include "TixiHelper.h" + +namespace tigl +{ +namespace generated +{ + CPACSRoot::CPACSRoot() + : m_mandatoryDouble(0) + , m_mandatoryInt(0) + { + } + + CPACSRoot::~CPACSRoot() + { + } + + const CTiglUIDObject* CPACSRoot::GetNextUIDParent() const + { + return nullptr; + } + + CTiglUIDObject* CPACSRoot::GetNextUIDParent() + { + return nullptr; + } + + void CPACSRoot::ReadCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) + { + // read element optionalDouble + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/optionalDouble")) { + m_optionalDouble = tixi::TixiGetElement(tixiHandle, xpath + "/optionalDouble"); + } + + // read element mandatoryDouble + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/mandatoryDouble")) { + m_mandatoryDouble = tixi::TixiGetElement(tixiHandle, xpath + "/mandatoryDouble"); + } + else { + LOG(ERROR) << "Required element mandatoryDouble is missing at xpath " << xpath; + } + + // read element optionalInt + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/optionalInt")) { + m_optionalInt = tixi::TixiGetElement(tixiHandle, xpath + "/optionalInt"); + } + + // read element mandatoryInt + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/mandatoryInt")) { + m_mandatoryInt = tixi::TixiGetElement(tixiHandle, xpath + "/mandatoryInt"); + } + else { + LOG(ERROR) << "Required element mandatoryInt is missing at xpath " << xpath; + } + + } + + void CPACSRoot::WriteCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) const + { + const std::vector childElemOrder = { "optionalDouble", "mandatoryDouble", "optionalInt", "mandatoryInt" }; + + // write element optionalDouble + if (m_optionalDouble) { + tixi::TixiCreateSequenceElementIfNotExists(tixiHandle, xpath + "/optionalDouble", childElemOrder); + tixi::TixiSaveElement(tixiHandle, xpath + "/optionalDouble", *m_optionalDouble); + } + else { + if (tixi::TixiCheckElement(tixiHandle, xpath + "/optionalDouble")) { + tixi::TixiRemoveElement(tixiHandle, xpath + "/optionalDouble"); + } + } + + // write element mandatoryDouble + tixi::TixiCreateSequenceElementIfNotExists(tixiHandle, xpath + "/mandatoryDouble", childElemOrder); + tixi::TixiSaveElement(tixiHandle, xpath + "/mandatoryDouble", m_mandatoryDouble); + + // write element optionalInt + if (m_optionalInt) { + tixi::TixiCreateSequenceElementIfNotExists(tixiHandle, xpath + "/optionalInt", childElemOrder); + tixi::TixiSaveElement(tixiHandle, xpath + "/optionalInt", *m_optionalInt); + } + else { + if (tixi::TixiCheckElement(tixiHandle, xpath + "/optionalInt")) { + tixi::TixiRemoveElement(tixiHandle, xpath + "/optionalInt"); + } + } + + // write element mandatoryInt + tixi::TixiCreateSequenceElementIfNotExists(tixiHandle, xpath + "/mandatoryInt", childElemOrder); + tixi::TixiSaveElement(tixiHandle, xpath + "/mandatoryInt", m_mandatoryInt); + + } + + const boost::optional& CPACSRoot::GetOptionalDouble() const + { + return m_optionalDouble; + } + + void CPACSRoot::SetOptionalDouble(const boost::optional& value) + { + m_optionalDouble = value; + } + + const double& CPACSRoot::GetMandatoryDouble() const + { + return m_mandatoryDouble; + } + + void CPACSRoot::SetMandatoryDouble(const double& value) + { + m_mandatoryDouble = value; + } + + const boost::optional& CPACSRoot::GetOptionalInt() const + { + return m_optionalInt; + } + + void CPACSRoot::SetOptionalInt(const boost::optional& value) + { + m_optionalInt = value; + } + + const int& CPACSRoot::GetMandatoryInt() const + { + return m_mandatoryInt; + } + + void CPACSRoot::SetMandatoryInt(const int& value) + { + m_mandatoryInt = value; + } + +} // namespace generated +} // namespace tigl diff --git a/test/data/elementtextcontent/schema.xsd b/test/data/elementtextcontent/schema.xsd new file mode 100644 index 0000000..a06de3f --- /dev/null +++ b/test/data/elementtextcontent/schema.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/test/data/optionalchoice/CustomTypes.txt b/test/data/optionalchoice/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/optionalchoice/ParentPointer.txt b/test/data/optionalchoice/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/optionalchoice/PruneList.txt b/test/data/optionalchoice/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/optionalchoice/TypeSubstitution.txt b/test/data/optionalchoice/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/optionalchoice/ref.cpp b/test/data/optionalchoice/ref.cpp index aefd1b3..8baa246 100644 --- a/test/data/optionalchoice/ref.cpp +++ b/test/data/optionalchoice/ref.cpp @@ -114,12 +114,12 @@ namespace generated void CPACSRoot::ReadCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) { // read element a - if (tixi::TixiCheckElement(tixiHandle, xpath + "/a")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/a")) { m_a_choice1 = tixi::TixiGetElement(tixiHandle, xpath + "/a"); } // read element b - if (tixi::TixiCheckElement(tixiHandle, xpath + "/b")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/b")) { m_b_choice2 = tixi::TixiGetElement(tixiHandle, xpath + "/b"); } diff --git a/test/data/sequence/CustomTypes.txt b/test/data/sequence/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/sequence/ParentPointer.txt b/test/data/sequence/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/sequence/PruneList.txt b/test/data/sequence/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/sequence/TypeSubstitution.txt b/test/data/sequence/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/sequence/ref.cpp b/test/data/sequence/ref.cpp index 4efcaba..c50c708 100644 --- a/test/data/sequence/ref.cpp +++ b/test/data/sequence/ref.cpp @@ -59,6 +59,7 @@ namespace generated TIGL_EXPORT virtual std::vector& GetEs(); TIGL_EXPORT virtual size_t GetECount() const; + TIGL_EXPORT virtual const int& GetE(size_t index) const; TIGL_EXPORT virtual int& GetE(size_t index); @@ -69,6 +70,7 @@ namespace generated TIGL_EXPORT virtual std::vector& GetGs(); TIGL_EXPORT virtual size_t GetGCount() const; + TIGL_EXPORT virtual const int& GetG(size_t index) const; TIGL_EXPORT virtual int& GetG(size_t index); @@ -79,6 +81,7 @@ namespace generated TIGL_EXPORT virtual std::vector& GetIs(); TIGL_EXPORT virtual size_t GetICount() const; + TIGL_EXPORT virtual const int& GetI(size_t index) const; TIGL_EXPORT virtual int& GetI(size_t index); @@ -157,7 +160,7 @@ namespace generated void CPACSRoot::ReadCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) { // read element a - if (tixi::TixiCheckElement(tixiHandle, xpath + "/a")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/a")) { m_a = tixi::TixiGetElement(tixiHandle, xpath + "/a"); } else { @@ -165,12 +168,12 @@ namespace generated } // read element b - if (tixi::TixiCheckElement(tixiHandle, xpath + "/b")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/b")) { m_b = tixi::TixiGetElement(tixiHandle, xpath + "/b"); } // read element c - if (tixi::TixiCheckElement(tixiHandle, xpath + "/c")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/c")) { m_c = tixi::TixiGetElement(tixiHandle, xpath + "/c"); } else { @@ -178,7 +181,7 @@ namespace generated } // read element d - if (tixi::TixiCheckElement(tixiHandle, xpath + "/d")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/d")) { m_d = tixi::TixiGetElement(tixiHandle, xpath + "/d"); } else { @@ -186,22 +189,22 @@ namespace generated } // read element e - if (tixi::TixiCheckElement(tixiHandle, xpath + "/e")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/e")) { tixi::TixiReadElements(tixiHandle, xpath + "/e", m_es, 1, tixi::xsdUnbounded); } // read element f - if (tixi::TixiCheckElement(tixiHandle, xpath + "/f")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/f")) { m_f = tixi::TixiGetElement(tixiHandle, xpath + "/f"); } // read element g - if (tixi::TixiCheckElement(tixiHandle, xpath + "/g")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/g")) { tixi::TixiReadElements(tixiHandle, xpath + "/g", m_gs, 0, tixi::xsdUnbounded); } // read element h - if (tixi::TixiCheckElement(tixiHandle, xpath + "/h")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/h")) { m_h = tixi::TixiGetElement(tixiHandle, xpath + "/h"); } else { @@ -209,7 +212,7 @@ namespace generated } // read element i - if (tixi::TixiCheckElement(tixiHandle, xpath + "/i")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/i")) { tixi::TixiReadElements(tixiHandle, xpath + "/i", m_is, 1, tixi::xsdUnbounded); } @@ -325,19 +328,19 @@ namespace generated int& CPACSRoot::GetE(size_t index) { - index--; - if (index < 0 || index >= GetECount()) { + if (index < 1 || index > GetECount()) { throw CTiglError("Invalid index in std::vector::GetE", TIGL_INDEX_ERROR); } + index--; return m_es[index]; } const int& CPACSRoot::GetE(size_t index) const { - index--; - if (index < 0 || index >= GetECount()) { + if (index < 1 || index > GetECount()) { throw CTiglError("Invalid index in std::vector::GetE", TIGL_INDEX_ERROR); } + index--; return m_es[index]; } @@ -369,19 +372,19 @@ namespace generated int& CPACSRoot::GetG(size_t index) { - index--; - if (index < 0 || index >= GetGCount()) { + if (index < 1 || index > GetGCount()) { throw CTiglError("Invalid index in std::vector::GetG", TIGL_INDEX_ERROR); } + index--; return m_gs[index]; } const int& CPACSRoot::GetG(size_t index) const { - index--; - if (index < 0 || index >= GetGCount()) { + if (index < 1 || index > GetGCount()) { throw CTiglError("Invalid index in std::vector::GetG", TIGL_INDEX_ERROR); } + index--; return m_gs[index]; } @@ -413,19 +416,19 @@ namespace generated int& CPACSRoot::GetI(size_t index) { - index--; - if (index < 0 || index >= GetICount()) { + if (index < 1 || index > GetICount()) { throw CTiglError("Invalid index in std::vector::GetI", TIGL_INDEX_ERROR); } + index--; return m_is[index]; } const int& CPACSRoot::GetI(size_t index) const { - index--; - if (index < 0 || index >= GetICount()) { + if (index < 1 || index > GetICount()) { throw CTiglError("Invalid index in std::vector::GetI", TIGL_INDEX_ERROR); } + index--; return m_is[index]; } diff --git a/test/data/simplebasetypewithparent/CustomTypes.txt b/test/data/simplebasetypewithparent/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/simplebasetypewithparent/PruneList.txt b/test/data/simplebasetypewithparent/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/simplebasetypewithparent/TypeSubstitution.txt b/test/data/simplebasetypewithparent/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/simplebasetypewithparent/ref.cpp b/test/data/simplebasetypewithparent/ref.cpp index 7d274d6..49772e0 100644 --- a/test/data/simplebasetypewithparent/ref.cpp +++ b/test/data/simplebasetypewithparent/ref.cpp @@ -331,7 +331,7 @@ namespace generated } // read simpleContent - if (tixi::TixiCheckElement(tixiHandle, xpath)) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath)) { m_value = tixi::TixiGetElement(tixiHandle, xpath); if (m_value.empty()) { LOG(WARNING) << "Required element is empty at xpath " << xpath; @@ -481,7 +481,7 @@ namespace generated } // read simpleContent - if (tixi::TixiCheckElement(tixiHandle, xpath)) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath)) { m_value = tixi::TixiGetElement(tixiHandle, xpath); if (m_value.empty()) { LOG(WARNING) << "Required element is empty at xpath " << xpath; diff --git a/test/data/uidinbasetype/CustomTypes.txt b/test/data/uidinbasetype/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/uidinbasetype/ParentPointer.txt b/test/data/uidinbasetype/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/uidinbasetype/PruneList.txt b/test/data/uidinbasetype/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/uidinbasetype/TypeSubstitution.txt b/test/data/uidinbasetype/TypeSubstitution.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/uidinbasetype/ref.cpp b/test/data/uidinbasetype/ref.cpp index 328ed15..ed1dbc9 100644 --- a/test/data/uidinbasetype/ref.cpp +++ b/test/data/uidinbasetype/ref.cpp @@ -246,7 +246,7 @@ namespace generated } // read element name - if (tixi::TixiCheckElement(tixiHandle, xpath + "/name")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/name")) { m_name = tixi::TixiGetElement(tixiHandle, xpath + "/name"); if (m_name->empty()) { LOG(WARNING) << "Optional element name is present but empty at xpath " << xpath; diff --git a/test/data/uidreferencevector/CustomTypes.txt b/test/data/uidreferencevector/CustomTypes.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/uidreferencevector/ParentPointer.txt b/test/data/uidreferencevector/ParentPointer.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/uidreferencevector/PruneList.txt b/test/data/uidreferencevector/PruneList.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/data/uidreferencevector/ref.cpp b/test/data/uidreferencevector/ref.cpp index 34050f9..c3b39ac 100644 --- a/test/data/uidreferencevector/ref.cpp +++ b/test/data/uidreferencevector/ref.cpp @@ -148,7 +148,7 @@ namespace generated void CPACSRoot::ReadCPACS(const TixiDocumentHandle& tixiHandle, const std::string& xpath) { // read element singleUidRef - if (tixi::TixiCheckElement(tixiHandle, xpath + "/singleUidRef")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/singleUidRef")) { m_singleUidRef = tixi::TixiGetElement(tixiHandle, xpath + "/singleUidRef"); if (m_singleUidRef->empty()) { LOG(WARNING) << "Optional element singleUidRef is present but empty at xpath " << xpath; @@ -157,7 +157,7 @@ namespace generated } // read element multiUidRefs - if (tixi::TixiCheckElement(tixiHandle, xpath + "/multiUidRefs")) { + if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/multiUidRefs")) { tixi::TixiReadElements(tixiHandle, xpath + "/multiUidRefs", m_multiUidRefs, 0, tixi::xsdUnbounded); if (m_uidMgr) { for (std::vector::iterator it = m_multiUidRefs.begin(); it != m_multiUidRefs.end(); ++it) { diff --git a/test/main.cpp b/test/main.cpp index eae08d4..3629ebc 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,5 +1,4 @@ -#define BOOST_TEST_MODULE CPACSGenTests -#include +#include #include "../src/lib/SchemaParser.h" #include "../src/lib/TypeSystem.h" @@ -8,6 +7,9 @@ #include "../src/lib/Filesystem.h" #include "utils.h" +#include +#include +#include void runTest() { const auto testDir = ::testDir(); @@ -27,60 +29,65 @@ void runTest() { const auto ref = readTextFile(refFile); const auto result = readTextFile(resultFile); + if (ref != result) - BOOST_TEST_ERROR("ref and result mismatch. please diff files in filesystem"); + ADD_FAILURE() << "ref and result mismatch. please diff files in filesystem"; else - boost::filesystem::remove(resultFile); + std::filesystem::remove(resultFile); } -BOOST_AUTO_TEST_CASE(sequence) { +TEST(CPACSGenTests, sequence) { runTest(); } -BOOST_AUTO_TEST_CASE(all) { +TEST(CPACSGenTests, all) { runTest(); } -BOOST_AUTO_TEST_CASE(choice) { +TEST(CPACSGenTests, choice) { runTest(); } -BOOST_AUTO_TEST_CASE(documentation) { +TEST(CPACSGenTests, documentation) { runTest(); } -BOOST_AUTO_TEST_CASE(uidinbasetype) { +TEST(CPACSGenTests, uidinbasetype) { runTest(); } -BOOST_AUTO_TEST_CASE(custombasetype) { +TEST(CPACSGenTests, custombasetype) { runTest(); } -BOOST_AUTO_TEST_CASE(basetypewithparent) { +TEST(CPACSGenTests, basetypewithparent) { runTest(); } -BOOST_AUTO_TEST_CASE(uidreferencevector) { +TEST(CPACSGenTests, uidreferencevector) { runTest(); } -BOOST_AUTO_TEST_CASE(cdata) { +TEST(CPACSGenTests, cdata) { runTest(); } -BOOST_AUTO_TEST_CASE(simplebasetypewithparent) { +TEST(CPACSGenTests, simplebasetypewithparent) { runTest(); } -BOOST_AUTO_TEST_CASE(complextypewithsimplecontent) { +TEST(CPACSGenTests, complextypewithsimplecontent) { runTest(); } -BOOST_AUTO_TEST_CASE(collapsedifferentenums) { +TEST(CPACSGenTests, collapsedifferentenums) { runTest(); } -BOOST_AUTO_TEST_CASE(optionalchoice) { +TEST(CPACSGenTests, optionalchoice) { runTest(); } + +TEST(CPACSGenTests, elementtextcontent) { + runTest(); +} \ No newline at end of file diff --git a/test/utils.cpp b/test/utils.cpp index 5699d74..fb11f0c 100644 --- a/test/utils.cpp +++ b/test/utils.cpp @@ -1,7 +1,8 @@ #include "utils.h" #include +#include -auto readTextFile(const boost::filesystem::path& path) -> std::string { +auto readTextFile(const std::filesystem::path& path) -> std::string { std::ifstream f(path.string()); if (!f) throw std::ios::failure("Failed to open file " + path.string() + " for reading"); @@ -17,9 +18,9 @@ auto readTextFile(const boost::filesystem::path& path) -> std::string { } auto testName() -> std::string { - return boost::unit_test::framework::current_test_case().p_name.get(); + return ::testing::UnitTest::GetInstance()->current_test_info()->name(); } -auto testDir() -> boost::filesystem::path { - return boost::filesystem::path{ c_dataDir } / testName(); +auto testDir() -> std::filesystem::path { + return std::filesystem::path{ c_dataDir } / testName(); } diff --git a/test/utils.h b/test/utils.h index 3436941..bd6d981 100644 --- a/test/utils.h +++ b/test/utils.h @@ -1,12 +1,11 @@ #pragma once -#include -#include +#include #include "paths.h" -auto readTextFile(const boost::filesystem::path& path) -> std::string; +auto readTextFile(const std::filesystem::path& path) -> std::string; auto testName() -> std::string; -auto testDir() -> boost::filesystem::path; +auto testDir() -> std::filesystem::path;