From 672b988c5e68d8e8fb35b5347849984decb1d202 Mon Sep 17 00:00:00 2001 From: Martyn Gigg <martyn.gigg@stfc.ac.uk> Date: Wed, 25 Jul 2012 12:06:17 +0100 Subject: [PATCH] Add Strings function to create a map from key/val pairs. Refs #5644 --- .../Kernel/inc/MantidKernel/Strings.h | 5 ++ Code/Mantid/Framework/Kernel/src/Strings.cpp | 38 +++++++++++-- .../Framework/Kernel/test/StringsTest.h | 57 +++++++++++++++++++ 3 files changed, 95 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h index 46a574b16f5..5f20df7c10f 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 56b507f8b57..5ad7310b021 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 f04ef08b367..0f229294750 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() { -- GitLab