logic: add storage transformation to merge anonymous types and the respective typedef

* moved storage related classes to data/storage folder
* implemented recording c++ unions as NODE_UNION instead of just using NODE_TYPE
* added transformation to merge anonymous classes/structs/enums/unions and typedef nodes
* added tests for this transformation
* added setting for enabling/disabling this transformation
This commit is contained in:
malte_langkabel
2017-07-18 15:14:43 +02:00
parent e536f20e36
commit cad595a32c
76 changed files with 524 additions and 96 deletions
+1 -1
View File
@@ -19,7 +19,7 @@
#include "component/controller/IDECommunicationController.h"
#include "component/view/MainView.h"
#include "component/view/ViewFactory.h"
#include "data/StorageCache.h"
#include "data/storage/StorageCache.h"
#include "LicenseChecker.h"
#include "settings/ApplicationSettings.h"
#include "settings/ProjectSettings.h"
+28 -25
View File
@@ -211,6 +211,34 @@ add_files(
data/search/SearchIndex.h
data/search/SearchMatch.cpp
data/search/SearchMatch.h
data/storage/migration/SqliteStorageMigration.cpp
data/storage/migration/SqliteStorageMigration.h
data/storage/migration/SqliteStorageMigrationLambda.cpp
data/storage/migration/SqliteStorageMigrationLambda.h
data/storage/migration/SqliteStorageMigrator.h
data/storage/sqlite/SqliteBookmarkStorage.cpp
data/storage/sqlite/SqliteBookmarkStorage.h
data/storage/sqlite/SqliteDatabaseIndex.cpp
data/storage/sqlite/SqliteDatabaseIndex.h
data/storage/sqlite/SqliteIndexStorage.cpp
data/storage/sqlite/SqliteIndexStorage.h
data/storage/sqlite/SqliteStorage.cpp
data/storage/sqlite/SqliteStorage.h
data/storage/IntermediateStorage.cpp
data/storage/IntermediateStorage.h
data/storage/PersistentStorage.cpp
data/storage/PersistentStorage.h
data/storage/Storage.cpp
data/storage/Storage.h
data/storage/StorageCache.cpp
data/storage/StorageCache.h
data/storage/StorageProvider.cpp
data/storage/StorageProvider.h
data/storage/StorageTypes.h
data/storage/StorageStats.h
data/DefinitionKind.cpp
data/DefinitionKind.h
@@ -219,31 +247,6 @@ add_files(
data/ErrorInfo.h
data/HierarchyCache.cpp
data/HierarchyCache.h
data/IntermediateStorage.cpp
data/IntermediateStorage.h
data/PersistentStorage.cpp
data/PersistentStorage.h
data/SqliteBookmarkStorage.cpp
data/SqliteBookmarkStorage.h
data/SqliteDatabaseIndex.cpp
data/SqliteDatabaseIndex.h
data/SqliteIndexStorage.cpp
data/SqliteIndexStorage.h
data/SqliteStorage.cpp
data/SqliteStorage.h
data/SqliteStorageMigration.cpp
data/SqliteStorageMigration.h
data/SqliteStorageMigrationLambda.cpp
data/SqliteStorageMigrationLambda.h
data/SqliteStorageMigrator.h
data/Storage.cpp
data/Storage.h
data/StorageCache.cpp
data/StorageCache.h
data/StorageProvider.cpp
data/StorageProvider.h
data/StorageTypes.h
data/StorageStats.h
data/TaskCleanStorage.cpp
data/TaskCleanStorage.h
data/TaskFinishParsing.cpp
@@ -1169,6 +1169,7 @@ void GraphController::bundleNodesByType()
bundleByType(nodes, Node::NODE_TYPE, "Types");
bundleByType(nodes, Node::NODE_TYPEDEF, "Typedefs");
bundleByType(nodes, Node::NODE_ENUM, "Enums");
bundleByType(nodes, Node::NODE_UNION, "Unions");
// // should never be visible
@@ -1334,7 +1335,7 @@ void GraphController::layoutNestingRecursive(DummyNode* node) const
Node::NodeTypeMask mask =
Node::NODE_NON_INDEXED | Node::NODE_TYPE | Node::NODE_BUILTIN_TYPE |
Node::NODE_CLASS | Node::NODE_STRUCT | Node::NODE_ENUM;
Node::NODE_CLASS | Node::NODE_STRUCT | Node::NODE_ENUM | Node::NODE_UNION;
if (node->data->isType(mask) && node->data->getChildCount() > 0)
{
addExpandToggleNode(node);
@@ -1609,7 +1610,7 @@ void GraphController::forEachDummyEdge(std::function<void(DummyEdge*)> func)
void GraphController::handleMessage(MessageColorSchemeTest* message)
{
// todo: add nodes: package, interface, type_parameter, builtin_type
// todo: add nodes: package, interface, type_parameter, builtin_type, union
// todo: add edges: EDGE_TYPE_ARGUMENT, EDGE_IMPORT
// todo: add access: TYPE_PARAMETER
clear();
@@ -188,6 +188,7 @@ size_t GraphViewStyle::getFontSizeForNodeType(Node::NodeType type)
case Node::NODE_BUILTIN_TYPE:
case Node::NODE_STRUCT:
case Node::NODE_CLASS:
case Node::NODE_UNION:
case Node::NODE_INTERFACE:
case Node::NODE_ENUM:
case Node::NODE_TYPEDEF:
@@ -276,6 +277,7 @@ GraphViewStyle::NodeMargins GraphViewStyle::getMarginsForNodeType(Node::NodeType
case Node::NODE_BUILTIN_TYPE:
case Node::NODE_STRUCT:
case Node::NODE_CLASS:
case Node::NODE_UNION:
case Node::NODE_INTERFACE:
case Node::NODE_TEMPLATE_PARAMETER_TYPE:
case Node::NODE_TYPE_PARAMETER:
@@ -418,6 +420,7 @@ GraphViewStyle::NodeStyle GraphViewStyle::getStyleForNodeType(
case Node::NODE_BUILTIN_TYPE:
case Node::NODE_STRUCT:
case Node::NODE_CLASS:
case Node::NODE_UNION:
case Node::NODE_INTERFACE:
case Node::NODE_ENUM:
case Node::NODE_TYPEDEF:
+1 -1
View File
@@ -2,7 +2,7 @@
#define ERROR_FILTER_H
#include "data/ErrorInfo.h"
#include "data/StorageTypes.h"
#include "data/storage/StorageTypes.h"
struct ErrorFilter
{
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef ERROR_INFO_H
#define ERROR_INFO_H
#include "data/StorageTypes.h"
#include "data/storage/StorageTypes.h"
typedef StorageError ErrorInfo;
+1 -1
View File
@@ -1,7 +1,7 @@
#include "data/TaskCleanStorage.h"
#include "component/view/DialogView.h"
#include "data/PersistentStorage.h"
#include "data/storage/PersistentStorage.h"
#include "utility/file/FilePath.h"
#include "utility/scheduling/Blackboard.h"
#include "utility/utility.h"
+1 -1
View File
@@ -1,7 +1,7 @@
#include "data/TaskFinishParsing.h"
#include "component/view/DialogView.h"
#include "data/PersistentStorage.h"
#include "data/storage/PersistentStorage.h"
#include "utility/messaging/type/MessageFinishedParsing.h"
#include "utility/messaging/type/MessageStatus.h"
#include "utility/scheduling/Blackboard.h"
+2 -2
View File
@@ -3,8 +3,8 @@
#include <chrono>
#include <thread>
#include "data/Storage.h"
#include "data/StorageProvider.h"
#include "data/storage/Storage.h"
#include "data/storage/StorageProvider.h"
TaskInjectStorage::TaskInjectStorage(
std::shared_ptr<StorageProvider> storageProvider,
+1 -1
View File
@@ -3,7 +3,7 @@
#include <chrono>
#include <thread>
#include "data/StorageProvider.h"
#include "data/storage/StorageProvider.h"
TaskMergeStorages::TaskMergeStorages(
std::shared_ptr<StorageProvider> storageProvider
+1 -1
View File
@@ -15,7 +15,7 @@
#include "data/ErrorCountInfo.h"
#include "data/ErrorFilter.h"
#include "data/ErrorInfo.h"
#include "data/StorageStats.h"
#include "data/storage/StorageStats.h"
class FilePath;
struct FileInfo;
+4
View File
@@ -65,6 +65,8 @@ std::string Node::getReadableTypeString(NodeType type)
return "file";
case NODE_MACRO:
return "macro";
case NODE_UNION:
return "union";
}
return "";
@@ -115,6 +117,8 @@ Node::NodeType Node::intToType(int value)
return NODE_FILE;
case NODE_MACRO:
return NODE_MACRO;
case NODE_UNION:
return NODE_UNION;
}
return NODE_NON_INDEXED;
+2 -1
View File
@@ -45,7 +45,8 @@ public:
NODE_TYPE_PARAMETER = 0x10000,
NODE_FILE = 0x20000,
NODE_MACRO = 0x40000
NODE_MACRO = 0x40000,
NODE_UNION = 0x80000
};
static std::string getUnderscoredTypeString(NodeType type);
+1 -1
View File
@@ -2,7 +2,7 @@
#include "data/indexer/IndexerCommand.h"
#include "utility/logging/logging.h"
#include "data/IntermediateStorage.h"
#include "data/storage/IntermediateStorage.h"
IndexerComposite::~IndexerComposite()
{
+1 -1
View File
@@ -10,7 +10,7 @@
#include "component/view/DialogView.h"
#include "data/indexer/IndexerCommandList.h"
#include "data/indexer/interprocess/InterprocessIndexer.h"
#include "data/StorageProvider.h"
#include "data/storage/StorageProvider.h"
#if _WIN32
const std::string TaskBuildIndex::s_processName("sourcetrail_indexer.exe");
@@ -1,7 +1,7 @@
#include "InterprocessIntermediateStorageManager.h"
#include "data/indexer/interprocess/shared_types/SharedIntermediateStorage.h"
#include "data/IntermediateStorage.h"
#include "data/storage/IntermediateStorage.h"
#include "utility/logging/logging.h"
const char* InterprocessIntermediateStorageManager::s_sharedMemoryNamePrefix = "iist_";
@@ -22,6 +22,7 @@ void SharedIndexerCommand::fromLocal(IndexerCommand* indexerCommand)
setSystemHeaderSearchPaths(cmd->getSystemHeaderSearchPaths());
setFrameworkSearchhPaths(cmd->getFrameworkSearchPaths());
setPreprocessorOnly(cmd->preprocessorOnly());
setShouldApplyAnonymousTypedefTransformation(cmd->shouldApplyAnonymousTypedefTransformation());
}
else if (dynamic_cast<IndexerCommandCxxManual*>(indexerCommand) != NULL)
{
@@ -33,6 +34,7 @@ void SharedIndexerCommand::fromLocal(IndexerCommand* indexerCommand)
setSystemHeaderSearchPaths(cmd->getSystemHeaderSearchPaths());
setFrameworkSearchhPaths(cmd->getFrameworkSearchPaths());
setPreprocessorOnly(cmd->preprocessorOnly());
setShouldApplyAnonymousTypedefTransformation(cmd->shouldApplyAnonymousTypedefTransformation());
}
else if (dynamic_cast<IndexerCommandJava*>(indexerCommand) != NULL)
{
@@ -60,8 +62,9 @@ std::shared_ptr<IndexerCommand> SharedIndexerCommand::fromShared(const SharedInd
indexerCommand.getWorkingDirectory(),
indexerCommand.getCompilerFlags(),
indexerCommand.getSystemHeaderSearchPaths(),
indexerCommand.getFrameworkSearchhPaths()
);
indexerCommand.getFrameworkSearchhPaths(),
indexerCommand.shouldApplyAnonymousTypedefTransformation()
);
command->setPreprocessorOnly(indexerCommand.preprocessorOnly());
return command;
}
@@ -74,8 +77,9 @@ std::shared_ptr<IndexerCommand> SharedIndexerCommand::fromShared(const SharedInd
indexerCommand.getLanguageStandard(),
indexerCommand.getSystemHeaderSearchPaths(),
indexerCommand.getFrameworkSearchhPaths(),
indexerCommand.getCompilerFlags()
);
indexerCommand.getCompilerFlags(),
indexerCommand.shouldApplyAnonymousTypedefTransformation()
);
command->setPreprocessorOnly(indexerCommand.preprocessorOnly());
return command;
}
@@ -283,6 +287,16 @@ void SharedIndexerCommand::setPreprocessorOnly(bool preprocessorOnly)
m_preprocessorOnly = preprocessorOnly;
}
bool SharedIndexerCommand::shouldApplyAnonymousTypedefTransformation() const
{
return m_shouldApplyAnonymousTypedefTransformation;
}
void SharedIndexerCommand::setShouldApplyAnonymousTypedefTransformation(bool shouldApplyAnonymousTypedefTransformation)
{
m_shouldApplyAnonymousTypedefTransformation = shouldApplyAnonymousTypedefTransformation;
}
std::vector<FilePath> SharedIndexerCommand::getClassPaths() const
{
std::vector<FilePath> result;
@@ -44,6 +44,9 @@ public:
bool preprocessorOnly() const;
void setPreprocessorOnly(bool preprocessorOnly);
bool shouldApplyAnonymousTypedefTransformation() const;
void setShouldApplyAnonymousTypedefTransformation(bool shouldApplyAnonymousTypedefTransformation);
std::vector<FilePath> getClassPaths() const;
void setClassPaths(const std::vector<FilePath>& classPaths);
@@ -73,6 +76,7 @@ private:
SharedMemory::Vector<SharedMemory::String> m_systemHeaderSearchPaths;
SharedMemory::Vector<SharedMemory::String> m_frameworkSearchPaths;
bool m_preprocessorOnly;
bool m_shouldApplyAnonymousTypedefTransformation;
// java
SharedMemory::Vector<SharedMemory::String> m_classPaths;
@@ -1,8 +1,8 @@
#ifndef SHARED_INTERMEDIATE_STORAGE_H
#define SHARED_INTERMEDIATE_STORAGE_H
#include "data/StorageTypes.h"
#include "SharedStorageTypes.h"
#include "data/storage/StorageTypes.h"
#include "data/indexer/interprocess/shared_types/SharedStorageTypes.h"
#include "utility/interprocess/SharedMemory.h"
class SharedIntermediateStorage
+1 -1
View File
@@ -129,7 +129,7 @@ Node::NodeType ParserClientImpl::symbolKindToNodeType(SymbolKind symbolKind) con
case SYMBOL_TYPE_PARAMETER:
return Node::NODE_TYPE_PARAMETER;
case SYMBOL_UNION:
return Node::NODE_TYPE;
return Node::NODE_UNION;
default:
break;
}
+1 -1
View File
@@ -5,7 +5,7 @@
#include "data/DefinitionKind.h"
#include "data/graph/Node.h"
#include "data/IntermediateStorage.h"
#include "data/storage/IntermediateStorage.h"
#include "data/parser/ParserClient.h"
class ParserClientImpl
+1 -1
View File
@@ -1,7 +1,7 @@
#include "data/parser/TaskParseWrapper.h"
#include "component/view/DialogView.h"
#include "data/PersistentStorage.h"
#include "data/storage/PersistentStorage.h"
#include "utility/scheduling/Blackboard.h"
#include "utility/utility.h"
#include "Application.h"
@@ -1,4 +1,4 @@
#include "data/IntermediateStorage.h"
#include "data/storage/IntermediateStorage.h"
#include <set>
@@ -6,8 +6,8 @@
#include <unordered_map>
#include <unordered_set>
#include "data/StorageTypes.h"
#include "data/Storage.h"
#include "data/storage/StorageTypes.h"
#include "data/storage/Storage.h"
class IntermediateStorage: public Storage
{
@@ -1,4 +1,4 @@
#include "data/PersistentStorage.h"
#include "data/storage/PersistentStorage.h"
#include <sstream>
#include <queue>
@@ -8,9 +8,9 @@
#include "data/fulltextsearch/FullTextSearchIndex.h"
#include "data/search/SearchIndex.h"
#include "data/HierarchyCache.h"
#include "data/SqliteIndexStorage.h"
#include "data/SqliteBookmarkStorage.h"
#include "data/Storage.h"
#include "data/storage/sqlite/SqliteIndexStorage.h"
#include "data/storage/sqlite/SqliteBookmarkStorage.h"
#include "data/storage/Storage.h"
class PersistentStorage
: public Storage
@@ -1,8 +1,8 @@
#include "data/Storage.h"
#include "data/storage/Storage.h"
#include <unordered_map>
#include "data/StorageTypes.h"
#include "data/storage/StorageTypes.h"
#include "utility/tracing.h"
Storage::Storage()
@@ -5,7 +5,7 @@
#include <mutex>
#include <string>
#include "data/StorageTypes.h"
#include "data/storage/StorageTypes.h"
#include "utility/types.h"
class Storage
@@ -1,4 +1,4 @@
#include "data/StorageCache.h"
#include "data/storage/StorageCache.h"
void StorageCache::clear()
{
@@ -1,4 +1,4 @@
#include "data/StorageProvider.h"
#include "data/storage/StorageProvider.h"
#include "utility/logging/logging.h"
@@ -4,7 +4,7 @@
#include <memory>
#include <mutex>
#include <list>
#include "data/IntermediateStorage.h"
#include "data/storage/IntermediateStorage.h"
class StorageProvider
{
@@ -1,4 +1,4 @@
#include "data/SqliteStorageMigration.h"
#include "data/storage/migration/SqliteStorageMigration.h"
SqliteStorageMigration::~SqliteStorageMigration()
{
@@ -4,7 +4,7 @@
#include <string>
#include <vector>
#include "data/SqliteStorage.h"
#include "data/storage/sqlite/SqliteStorage.h"
#include "utility/migration/Migration.h"
class SqliteStorageMigration: public Migration<SqliteStorage>
@@ -1,4 +1,4 @@
#include "data/SqliteStorageMigrationLambda.h"
#include "data/storage/migration/SqliteStorageMigrationLambda.h"
SqliteStorageMigrationLambda::SqliteStorageMigrationLambda(std::function<void(const SqliteStorageMigration*, SqliteStorage*)> m_lambda)
@@ -3,7 +3,7 @@
#include <functional>
#include "data/SqliteStorageMigration.h"
#include "data/storage/migration/SqliteStorageMigration.h"
class SqliteStorageMigrationLambda: public SqliteStorageMigration
{
@@ -1,7 +1,7 @@
#include "SqliteBookmarkStorage.h"
#include "data/storage/sqlite/SqliteBookmarkStorage.h"
#include "data/SqliteStorageMigrationLambda.h"
#include "data/SqliteStorageMigrator.h"
#include "data/storage/migration/SqliteStorageMigrationLambda.h"
#include "data/storage/migration/SqliteStorageMigrator.h"
#include "settings/ProjectSettings.h"
#include "utility/logging/logging.h"
#include "Application.h"
@@ -1,8 +1,8 @@
#ifndef SQLITE_BOOKMARK_STORAGE_H
#define SQLITE_BOOKMARK_STORAGE_H
#include "data/SqliteStorage.h"
#include "data/StorageTypes.h"
#include "data/storage/sqlite/SqliteStorage.h"
#include "data/storage/StorageTypes.h"
#include "utility/types.h"
class SqliteBookmarkStorage
@@ -1,4 +1,4 @@
#include "data/SqliteDatabaseIndex.h"
#include "data/storage/sqlite/SqliteDatabaseIndex.h"
#include "utility/logging/logging.h"
@@ -1,4 +1,4 @@
#include "data/SqliteIndexStorage.h"
#include "data/storage/sqlite/SqliteIndexStorage.h"
#include <unordered_map>
@@ -6,9 +6,9 @@
#include <vector>
#include "data/location/SourceLocationFile.h"
#include "data/SqliteDatabaseIndex.h"
#include "data/SqliteStorage.h"
#include "data/StorageTypes.h"
#include "data/storage/sqlite/SqliteDatabaseIndex.h"
#include "data/storage/sqlite/SqliteStorage.h"
#include "data/storage/StorageTypes.h"
#include "utility/types.h"
#include "utility/utility.h"
#include "utility/utilityString.h"
@@ -1,4 +1,4 @@
#include "SqliteStorage.h"
#include "data/storage/sqlite/SqliteStorage.h"
#include "utility/logging/logging.h"
#include "utility/TimePoint.h"
@@ -3,7 +3,7 @@
#include "sqlite/CppSQLite3.h"
#include "data/SqliteDatabaseIndex.h"
#include "data/storage/sqlite/SqliteDatabaseIndex.h"
#include "utility/file/FilePath.h"
class SqliteStorageMigration;
+2 -2
View File
@@ -7,8 +7,8 @@
#include "data/indexer/IndexerCommandList.h"
#include "data/indexer/TaskBuildIndex.h"
#include "data/parser/TaskParseWrapper.h"
#include "data/StorageProvider.h"
#include "data/PersistentStorage.h"
#include "data/storage/StorageProvider.h"
#include "data/storage/PersistentStorage.h"
#include "data/TaskCleanStorage.h"
#include "data/TaskMergeStorages.h"
#include "data/TaskShowStatusDialog.h"
+2
View File
@@ -156,6 +156,7 @@ std::vector<std::shared_ptr<SourceGroupSettings>> ProjectSettings::getAllSourceG
{
cxxSettings->setCompilationDatabasePath(FilePath(getValue<std::string>(key + "/build_file_path/compilation_db_path", "")));
}
cxxSettings->setShouldApplyAnonymousTypedefTransformation(getValue<bool>(key + "/should_apply_anonymous_typedef_transformation", true));
settings = cxxSettings;
}
break;
@@ -232,6 +233,7 @@ void ProjectSettings::setAllSourceGroupSettings(const std::vector<std::shared_pt
{
setValue(key + "/build_file_path/compilation_db_path", cxxSettings->getCompilationDatabasePath().str());
}
setValue(key + "/should_apply_anonymous_typedef_transformation", cxxSettings->getShouldApplyAnonymousTypedefTransformation());
}
break;
case SOURCE_GROUP_JAVA_EMPTY:
@@ -171,6 +171,16 @@ void SourceGroupSettingsCxx::setCompilationDatabasePath(const FilePath& compilat
m_compilationDatabasePath = compilationDatabasePath;
}
bool SourceGroupSettingsCxx::getShouldApplyAnonymousTypedefTransformation() const
{
return m_shouldApplyAnonymousTypedefTransformation;
}
void SourceGroupSettingsCxx::setShouldApplyAnonymousTypedefTransformation(bool shouldApplyAnonymousTypedefTransformation)
{
m_shouldApplyAnonymousTypedefTransformation = shouldApplyAnonymousTypedefTransformation;
}
std::vector<std::string> SourceGroupSettingsCxx::getDefaultSourceExtensions() const
{
std::vector<std::string> defaultValues;
@@ -36,6 +36,9 @@ public:
FilePath getCompilationDatabasePathExpandedAndAbsolute() const;
void setCompilationDatabasePath(const FilePath& compilationDatabasePath);
bool getShouldApplyAnonymousTypedefTransformation() const;
void setShouldApplyAnonymousTypedefTransformation(bool shouldApplyAnonymousTypedefTransformation);
private:
virtual std::vector<std::string> getDefaultSourceExtensions() const;
virtual std::string getDefaultStandard() const;
@@ -46,6 +49,7 @@ private:
bool m_useSourcePathsForHeaderSearch;
bool m_hasDefinedUseSourcePathsForHeaderSearch;
FilePath m_compilationDatabasePath;
bool m_shouldApplyAnonymousTypedefTransformation;
};
#endif // SOURCE_GROUP_SETTINGS_CXX_H
+20
View File
@@ -110,6 +110,16 @@ namespace utility
return str;
}
std::string substrBeforeFirst(const std::string& str, const std::string& delimiter)
{
size_t pos = str.find(delimiter);
if (pos != std::string::npos)
{
return str.substr(0, pos);
}
return str;
}
std::string substrBeforeLast(const std::string& str, char delimiter)
{
size_t pos = str.rfind(delimiter);
@@ -130,6 +140,16 @@ namespace utility
return str;
}
std::string substrAfter(const std::string& str, const std::string& delimiter)
{
size_t pos = str.find(delimiter);
if (pos != std::string::npos)
{
return str.substr(pos + delimiter.size(), str.size());
}
return str;
}
bool isPrefix(const std::string& prefix, const std::string& text)
{
if (prefix.size() <= text.size())
+2
View File
@@ -30,8 +30,10 @@ namespace utility
std::deque<std::string> tokenize(const std::deque<std::string>& list, const std::string& delimiter);
std::string substrBeforeFirst(const std::string& str, char delimiter);
std::string substrBeforeFirst(const std::string& str, const std::string& delimiter);
std::string substrBeforeLast(const std::string& str, char delimiter);
std::string substrAfter(const std::string& str, char delimiter);
std::string substrAfter(const std::string& str, const std::string& delimiter);
std::string substrBetween(const std::string& str, const std::string& delimiter1, const std::string& delimiter2);