diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h index 46a574b16f5ca58b6c24b4b5981cae8090cd07de..5f20df7c10fd2cc7c1e52266ca8d473cbc437e70 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h @@ -9,6 +9,7 @@ #include <set> #include <sstream> #include <vector> +#include <map> #include <iterator> namespace Mantid @@ -135,6 +136,10 @@ namespace Mantid /// Split tring into spc deliminated components MANTID_KERNEL_DLL std::vector<std::string> StrParts(std::string Ln); + /// Splits a string into key value pairs + MANTID_KERNEL_DLL std::map<std::string,std::string> + splitToKeyValues(const std::string & input, const std::string & keyValSep = "=", const std::string & listSep=","); + /// Write a set of containers to a file template<template<typename T,typename A> class V,typename T,typename A> int writeFile(const std::string& Fname,const T & step,const V<T,A>& Y); diff --git a/Code/Mantid/Framework/Kernel/src/Strings.cpp b/Code/Mantid/Framework/Kernel/src/Strings.cpp index 56b507f8b572eab3592c1ca70b34343088299e58..5ad7310b0218b2e5e87bb125ca2714fcd2cb5283 100644 --- a/Code/Mantid/Framework/Kernel/src/Strings.cpp +++ b/Code/Mantid/Framework/Kernel/src/Strings.cpp @@ -1,14 +1,17 @@ -#include "MantidKernel/Exception.h" #include "MantidKernel/Strings.h" +#include "MantidKernel/Exception.h" + +#include <Poco/StringTokenizer.h> +#include <Poco/Path.h> + #include <cmath> #include <fstream> #include <iomanip> #include <iosfwd> #include <iostream> #include <list> -#include <Poco/Path.h> #include <sstream> -#include <string.h> +#include <cstring> #include <vector> using std::size_t; @@ -432,13 +435,38 @@ namespace Mantid * @return vector of components */ std::vector<std::string> StrParts(std::string Ln) - { + { std::vector<std::string> Out; std::string Part; while(section(Ln,Part)) Out.push_back(Part); return Out; - } + } + + /** + * Splits a string into key value pairs and returns them as a map. Whitespace between separators is ignored + * @param input :: The string containing the key/values + * @param keyValSep :: The separator that splits a key and value [default: "="] + * @param listSep :: The separator that splits elements of the list [default: ","] + * @returns A map of keys->values + */ + std::map<std::string,std::string> + splitToKeyValues(const std::string & input, const std::string & keyValSep, const std::string & listSep) + { + std::map<std::string,std::string> keyValues; + const int splitOptions = Poco::StringTokenizer::TOK_IGNORE_EMPTY + Poco::StringTokenizer::TOK_TRIM; + Poco::StringTokenizer listSplitter(input, listSep); + for(auto iter = listSplitter.begin(); iter != listSplitter.end(); ++iter) + { + Poco::StringTokenizer keyValSplitter(*iter, keyValSep, splitOptions); + if(keyValSplitter.count() == 2) + { + keyValues[keyValSplitter[0]] = keyValSplitter[1]; + } + } + + return keyValues; + } //------------------------------------------------------------------------------------------------ diff --git a/Code/Mantid/Framework/Kernel/test/StringsTest.h b/Code/Mantid/Framework/Kernel/test/StringsTest.h index f04ef08b367070d57ec62f514c988ce975044362..0f2292947501b326874d776cb12d33bd0f61aa49 100644 --- a/Code/Mantid/Framework/Kernel/test/StringsTest.h +++ b/Code/Mantid/Framework/Kernel/test/StringsTest.h @@ -182,6 +182,63 @@ public: TS_ASSERT_EQUALS(X,9.0); } + void test_SplitToKeyValuePairs_Returns_Empty_Map_For_Empty_String() + { + auto keyValues = splitToKeyValues(""); + + TS_ASSERT(keyValues.empty()); + } + + void test_SplitToKeyValuePairs_Returns_Empty_Map_For_String_With_No_Values() + { + auto keyValues = splitToKeyValues("key,key,key"); + + TS_ASSERT(keyValues.empty()); + } + + void test_SplitToKeyValuePairs_Uses_Equals_And_Comma_As_Separators_By_Default() + { + auto keyValues = splitToKeyValues("key1=value1, key2=value2"); + + TS_ASSERT_EQUALS(keyValues.size(), 2); + TS_ASSERT_EQUALS(keyValues.at("key1"), "value1"); + TS_ASSERT_EQUALS(keyValues.at("key2"), "value2"); + } + + void test_SplitToKeyValuePairs_Uses_KeyValueSep_If_Given() + { + auto keyValues = splitToKeyValues("key1@value1, key2@value2", "@"); + + TS_ASSERT_EQUALS(keyValues.size(), 2); + TS_ASSERT_EQUALS(keyValues.at("key1"), "value1"); + TS_ASSERT_EQUALS(keyValues.at("key2"), "value2"); + } + + void test_SplitToKeyValuePairs_Uses_KeyValueSep_And_ListSep_If_Given() + { + auto keyValues = splitToKeyValues("key1@value1: key2@value2", "@", ":"); + + TS_ASSERT_EQUALS(keyValues.size(), 2); + TS_ASSERT_EQUALS(keyValues.at("key1"), "value1"); + TS_ASSERT_EQUALS(keyValues.at("key2"), "value2"); + } + + void test_SplitToKeyValuePairs_Does_Not_Ignore_Spaces_Within_Key_Or_Value() + { + auto keyValues = splitToKeyValues("key 1@value1: key2@value 2", "@", ":"); + + TS_ASSERT_EQUALS(keyValues.size(), 2); + TS_ASSERT_EQUALS(keyValues.at("key 1"), "value1"); + TS_ASSERT_EQUALS(keyValues.at("key2"), "value 2"); + } + + void test_SplitToKeyValuePairs_Ignores_Items_Without_A_Key_Or_Value() + { + auto keyValues = splitToKeyValues("key1=,key2=value2,=value3"); + + TS_ASSERT_EQUALS(keyValues.size(), 1); + TS_ASSERT_EQUALS(keyValues.at("key2"), "value2"); + } void test_join() {