Commit 1a096c4f authored by GILLES Sebastien's avatar GILLES Sebastien

#1540 Add a Split() utility function for strings.

#1539 Add tests for functions defined in Utilities::String - and modify slightly ConvertCharArray() to make it pass the test (one line was undue...)
parent 9886f465
......@@ -3017,6 +3017,8 @@
BE0513F31CC7C3D000A8F20D /* Alias.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Alias.hpp; sourceTree = "<group>"; };
BE05B4DD16D23573000E248D /* libGeometry.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libGeometry.a; sourceTree = BUILT_PRODUCTS_DIR; };
BE05B52916D238FE000E248D /* libCore.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCore.a; sourceTree = BUILT_PRODUCTS_DIR; };
BE08AB9D24A62BD000F36CEA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = CMakeLists.txt; path = Sources/Test/Utilities/String/CMakeLists.txt; sourceTree = SOURCE_ROOT; };
BE08AB9E24A62BEC00F36CEA /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = Sources/Test/Utilities/String/main.cpp; sourceTree = SOURCE_ROOT; };
BE08BAB222A7F8B700242810 /* Libmeshb.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Libmeshb.hpp; sourceTree = "<group>"; };
BE09762F1A723F93000C46A1 /* ___FILEBASENAME___.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "___FILEBASENAME___.cpp"; sourceTree = "<group>"; };
BE0976301A723F93000C46A1 /* ___FILEBASENAME___.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "___FILEBASENAME___.hpp"; sourceTree = "<group>"; };
......@@ -6047,6 +6049,15 @@
path = LocalInterface;
sourceTree = "<group>";
};
BE08AB9C24A62B9C00F36CEA /* String */ = {
isa = PBXGroup;
children = (
BE08AB9D24A62BD000F36CEA /* CMakeLists.txt */,
BE08AB9E24A62BEC00F36CEA /* main.cpp */,
);
path = String;
sourceTree = "<group>";
};
BE08BAB122A7F88900242810 /* Libmeshb */ = {
isa = PBXGroup;
children = (
......@@ -6432,8 +6443,8 @@
BE2457AA1E005B0B00677AEF /* Utilities */ = {
isa = PBXGroup;
children = (
02E68F9E242CC54D003CF312 /* StrongType */,
BE8B5FA72077D67400DC005E /* CMakeLists.txt */,
02E68F9E242CC54D003CF312 /* StrongType */,
BE7B9DCD235CF29100F52F7B /* HasMember */,
BE35030D22F30E2000D09A4D /* Filesystem */,
BE8B5F962077B21E00DC005E /* Environment */,
......@@ -6444,6 +6455,7 @@
BECEF93222DF63CA00D0DDE7 /* Now */,
BE2457AB1E005B0B00677AEF /* InputData */,
BE353BA922E77F0700A06A8F /* PrintContainer */,
BE08AB9C24A62B9C00F36CEA /* String */,
);
path = Utilities;
sourceTree = "<group>";
......@@ -9,6 +9,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/PrintContainer/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/Filesystem/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/StrongType/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/InputData/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/String/CMakeLists.txt)
......
add_executable(MoReFEMTestString
${CMAKE_CURRENT_LIST_DIR}/main.cpp
)
target_link_libraries(MoReFEMTestString
${MOREFEM_TEST_TOOLS})
add_test(String MoReFEMTestString)
set_tests_properties(String PROPERTIES TIMEOUT 20)
/*!
// \file
//
//
// Created by Jérôme Diaz <jerome.diaz@inria.fr> on the Thu, 27 Feb 2020 18:22:06 +0100
// Copyright (c) Inria. All rights reserved.
//
*/
#include <algorithm>
#define BOOST_TEST_MODULE string
#include "ThirdParty/IncludeWithoutWarning/Boost/Test.hpp"
#include "Utilities/String/String.hpp"
using namespace MoReFEM::Utilities::String;
PRAGMA_DIAGNOSTIC(push)
#include "Utilities/Warnings/Internal/IgnoreWarning/disabled-macro-expansion.hpp"
BOOST_AUTO_TEST_CASE(strip)
{
const std::string string = " \t ABCDEF \n\n ";
{
auto copy = string;
StripLeft(copy);
BOOST_CHECK_EQUAL(copy, "ABCDEF \n\n ");
}
{
auto copy = string;
StripRight(copy);
BOOST_CHECK_EQUAL(copy, " \t ABCDEF");
}
{
auto copy = string;
Strip(copy);
BOOST_CHECK_EQUAL(copy, "ABCDEF");
}
{
auto copy = string;
Strip(copy, " ");
BOOST_CHECK_EQUAL(copy, "\t ABCDEF \n\n");
}
}
BOOST_AUTO_TEST_CASE(start_end)
{
const std::string string = "Hello world!";
BOOST_CHECK(StartsWith(string, "Hello") == true);
BOOST_CHECK(StartsWith(string, "Bye") == false);
BOOST_CHECK(EndsWith(string, "!") == true);
BOOST_CHECK(EndsWith(string, "Bye") == false);
}
BOOST_AUTO_TEST_CASE(replace)
{
std::string string = "Hello world!";
BOOST_CHECK_EQUAL(Replace("Bonjour", "Hello", string), 0u);
BOOST_CHECK_EQUAL(Replace("Hello", "Bonjour", string), 1u);
BOOST_CHECK_EQUAL(Replace("world", "le monde", string), 1u);
BOOST_CHECK_EQUAL(string, "Bonjour le monde!");
}
BOOST_AUTO_TEST_CASE(repeat)
{
const std::string string = "parrot";
BOOST_CHECK_EQUAL(Repeat(string, 5u), "parrotparrotparrotparrotparrot");
BOOST_CHECK_EQUAL(Repeat("parrot", 5u), "parrotparrotparrotparrotparrot");
}
BOOST_AUTO_TEST_CASE(convert_char_array)
{
std::vector<char> char_hello { 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!' };
const std::string hello = "Hello world!";
BOOST_CHECK(ConvertCharArray(char_hello) == hello);
char_hello.push_back('\0');
BOOST_CHECK(ConvertCharArray(char_hello) == hello);
}
BOOST_AUTO_TEST_CASE(random_string)
{
const std::string charset = "+-0123456789";
const auto string = GenerateRandomString(10, charset);
BOOST_CHECK_EQUAL(string.size(), 10ul);
BOOST_CHECK(std::all_of(string.cbegin(),
string.cend(),
[&charset](char character)
{
return std::find(charset.cbegin(),
charset.cend(),
character) != charset.cend();
}));
}
BOOST_AUTO_TEST_CASE(split)
{
const std::string string = "Triangle 3; 0; 5; P1; 0.16 5.14 3.2";
BOOST_CHECK(Split(string, ";") == (std::vector<std::string_view>{"Triangle 3", " 0", " 5", " P1", " 0.16 5.14 3.2"}));
BOOST_CHECK(Split(string, "!") == (std::vector<std::string_view>{string}));
}
PRAGMA_DIAGNOSTIC(pop)
......@@ -285,7 +285,6 @@ namespace MoReFEM
}
);
ret.push_back('\0');
ret.shrink_to_fit();
return ret;
......@@ -293,7 +292,7 @@ namespace MoReFEM
std::string GenerateRandomString(std::size_t length,
const std::string& charset)
std::string_view charset)
{
assert(charset.size() >= 2ul);
......@@ -313,6 +312,31 @@ namespace MoReFEM
}
std::vector<std::string_view> Split(std::string_view string, std::string_view delimiter)
{
auto next = string.find(delimiter);
// Case delimiter simply not there...
if (next == std::string::npos)
return { string };
auto current = 0ul;
std::vector<std::string_view> ret;
while (next != std::string::npos)
{
assert(next >= current);
ret.push_back(string.substr(current, next - current));
current = next + 1;
next = string.find(delimiter, current);
}
ret.push_back(string.substr(current, next - current));
return ret;
}
} // namespace String
......
......@@ -89,6 +89,8 @@ namespace MoReFEM
* \param[in] sequence Sequence that is searched at the beginning of \a string.
*
* \return True if \a string starts with \a sequence.
*
* \attention C++ 20 will finally introduce that feature (see https://en.cppreference.com/w/cpp/string/basic_string_view)
*/
bool StartsWith(std::string_view string, std::string_view sequence);
......@@ -100,6 +102,8 @@ namespace MoReFEM
* \param[in] sequence Sequence that is searched at the end of \a string.
*
* \return True if \a string ends with \a sequence.
*
* \attention C++ 20 will finally introduce that feature (see https://en.cppreference.com/w/cpp/string/basic_string_view)
*/
bool EndsWith(std::string_view string, std::string_view sequence);
......@@ -190,10 +194,27 @@ namespace MoReFEM
* \return The random string.
*/
std::string GenerateRandomString(std::size_t length,
const std::string& charset =
std::string_view charset =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
/*!
* \brief Split a string into several parts given a separator.
*
* This is really a facilitator and does not aim to provide the best performance possible.
*
* \param[in] string The string to be splitted in several parts.
* \param[in] delimiter The delimiter to separate the parts.
*
* \return A view over the different parts.
*
* Example: Split("Triangle3; Domain1; 5", ";")
*
* will return { "Triangle3", " Domain1" and " 5" } (the space is not stripped).
*/
std::vector<std::string_view> Split(std::string_view string, std::string_view delimiter);
} // namespace String
......
......@@ -35,7 +35,7 @@ namespace MoReFEM
}
inline bool StartsWith(std::string_view string, std::string_view sequence )
inline bool StartsWith(std::string_view string, std::string_view sequence)
{
return 0 == string.compare(0, sequence.size(), sequence);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment