IVGCVSW-4513 Remove boost/algorithm/string *

 * Removed split, classification, trim, string, join, contains
 * Added StringUtils.hpp to replace the removed Boost String functionality


Signed-off-by: David Monahan <david.monahan@arm.com>
Change-Id: I8aa938dc3942cb65c512cccb2c069da66aa24668
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9697a5a..9e31a03 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -251,6 +251,7 @@
     include/armnn/utility/IgnoreUnused.hpp
     include/armnn/utility/NumericCast.hpp
     include/armnn/utility/PolymorphicDowncast.hpp
+    include/armnn/utility/StringUtils.hpp
     profiling/common/include/SocketConnectionException.hpp
     src/armnn/layers/LayerCloneBase.hpp
     src/armnn/layers/LayerWithParameters.hpp
diff --git a/include/armnn/utility/StringUtils.hpp b/include/armnn/utility/StringUtils.hpp
new file mode 100644
index 0000000..c56a215
--- /dev/null
+++ b/include/armnn/utility/StringUtils.hpp
@@ -0,0 +1,120 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <iostream>
+#include <sstream>
+
+namespace armnn
+{
+
+namespace stringUtils
+{
+
+/// Function to take a string and a list of delimiters and split the string into tokens based on those delimiters
+/// This assumes that tokens are also to be split by newlines
+/// Enabling token compression causes this to ignore multiple concurrent delimiters
+inline std::vector<std::string> StringTokenizer(const std::string& str,
+                                                const char* delimiters,
+                                                bool tokenCompression = true)
+{
+    std::stringstream stringStream(str);
+    std::string line;
+    std::vector<std::string> wordVector;
+    while (std::getline(stringStream, line))
+    {
+        std::size_t prev = 0;
+        std::size_t pos;
+        while ((pos = line.find_first_of(delimiters, prev)) != std::string::npos)
+        {
+            if (pos > prev)
+            {
+                // If token compression is enabled ignore delimiters that are next to each other
+                if (tokenCompression && (pos - prev == 1))
+                {
+                    prev = pos + 1;
+                    continue;
+                }
+                wordVector.push_back(line.substr(prev, pos - prev));
+            }
+            prev = pos + 1;
+        }
+        if (prev < line.length())
+        {
+            wordVector.push_back(line.substr(prev, std::string::npos));
+        }
+    }
+    return wordVector;
+}
+
+// Set of 3 utility functions for trimming std::strings
+// Default char set for common whitespace characters
+
+///
+/// Trim from the start of a string
+///
+inline std::string& StringStartTrim(std::string& str, const std::string& chars = "\t\n\v\f\r ")
+{
+    str.erase(0, str.find_first_not_of(chars));
+    return str;
+}
+
+///
+/// Trim for the end of a string
+///
+inline std::string& StringEndTrim(std::string& str, const std::string& chars = "\t\n\v\f\r ")
+{
+    str.erase(str.find_last_not_of(chars) + 1);
+    return str;
+}
+
+///
+/// Trim from both the start and the end of a string
+///
+inline std::string& StringTrim(std::string& str, const std::string& chars = "\t\n\v\f\r ")
+{
+    return StringStartTrim(StringEndTrim(str, chars), chars);
+}
+
+///
+/// Trim from both the start and the end of a string, returns a trimmed copy of the string
+///
+inline std::string StringTrimCopy(const std::string& str, const std::string& chars = "\t\n\v\f\r ")
+{
+    std::string strCopy = str;
+    return StringStartTrim(StringEndTrim(strCopy, chars), chars);
+}
+
+/// Takes a vector of strings and concatenates them together into one long std::string with an optional
+/// seperator between each.
+inline std::string StringConcat(const std::vector<std::string>& strings, std::string seperator = "")
+{
+    std::stringstream ss;
+    for (auto string : strings)
+    {
+        ss << string << seperator;
+    }
+    return ss.str();
+}
+
+///
+/// Iterates over a given str and replaces all instance of substring oldStr with newStr
+///
+inline void StringReplaceAll(std::string& str,
+                             const std::string& oldStr,
+                             const std::string& newStr)
+{
+    std::string::size_type pos = 0u;
+    while ((pos = str.find(oldStr, pos)) != std::string::npos)
+    {
+        str.replace(pos, oldStr.length(), newStr);
+        pos += newStr.length();
+    }
+}
+
+} // namespace stringUtils
+
+} // namespace armnn
\ No newline at end of file
diff --git a/src/armnn/Profiling.cpp b/src/armnn/Profiling.cpp
index 7194064..9a9021a 100644
--- a/src/armnn/Profiling.cpp
+++ b/src/armnn/Profiling.cpp
@@ -21,8 +21,6 @@
 #include <map>
 #include <stack>
 
-#include <boost/algorithm/string.hpp>
-
 namespace armnn
 {
 
diff --git a/src/armnn/test/CsvReaderTest.cpp b/src/armnn/test/CsvReaderTest.cpp
index ed27e57..8491ad7 100644
--- a/src/armnn/test/CsvReaderTest.cpp
+++ b/src/armnn/test/CsvReaderTest.cpp
@@ -4,7 +4,6 @@
 //
 #include "CsvReader.hpp"
 
-#include <boost/algorithm/string.hpp>
 #include <boost/test/unit_test.hpp>
 
 #include <iostream>
diff --git a/src/armnn/test/InferOutputTests.hpp b/src/armnn/test/InferOutputTests.hpp
index 70afbc9..0413682 100644
--- a/src/armnn/test/InferOutputTests.hpp
+++ b/src/armnn/test/InferOutputTests.hpp
@@ -14,7 +14,6 @@
 #include <layers/PreluLayer.hpp>
 #include <layers/StackLayer.hpp>
 
-#include <boost/algorithm/string.hpp>
 #include <boost/test/unit_test.hpp>
 
 void ArgMinMaxInferOutputShapeImpl(const armnn::ArgMinMaxDescriptor       descriptor,
diff --git a/src/armnn/test/ModelAccuracyCheckerTest.cpp b/src/armnn/test/ModelAccuracyCheckerTest.cpp
index 8bbe3d9..1bffa9c 100644
--- a/src/armnn/test/ModelAccuracyCheckerTest.cpp
+++ b/src/armnn/test/ModelAccuracyCheckerTest.cpp
@@ -4,7 +4,6 @@
 //
 #include "ModelAccuracyChecker.hpp"
 
-#include <boost/algorithm/string.hpp>
 #include <boost/test/unit_test.hpp>
 
 #include <boost/filesystem.hpp>
diff --git a/src/armnn/test/ProfilerTests.cpp b/src/armnn/test/ProfilerTests.cpp
index 40e9f47..7bd258e 100644
--- a/src/armnn/test/ProfilerTests.cpp
+++ b/src/armnn/test/ProfilerTests.cpp
@@ -9,7 +9,6 @@
 
 #include <boost/test/unit_test.hpp>
 #include <boost/test/tools/output_test_stream.hpp>
-#include <boost/algorithm/string.hpp>
 
 #include <memory>
 #include <thread>
@@ -231,21 +230,21 @@
         BOOST_TEST(!output.is_empty(false));
 
         // output should contain event name 'test'
-        BOOST_CHECK(boost::contains(output.str(), "test"));
+        BOOST_CHECK(output.str().find("test") != std::string::npos);
 
         // output should contain headers
-        BOOST_CHECK(boost::contains(output.str(), "Event Sequence - Name"));
-        BOOST_CHECK(boost::contains(output.str(), "Event Stats - Name"));
-        BOOST_CHECK(boost::contains(output.str(), "Total"));
-        BOOST_CHECK(boost::contains(output.str(), "Device"));
+        BOOST_CHECK(output.str().find("Event Sequence - Name") != std::string::npos);
+        BOOST_CHECK(output.str().find("Event Stats - Name") != std::string::npos);
+        BOOST_CHECK(output.str().find("Total") != std::string::npos);
+        BOOST_CHECK(output.str().find("Device") != std::string::npos);
         // output should contain compute device 'CpuAcc'
-        BOOST_CHECK(boost::contains(output.str(), "CpuAcc"));
+        BOOST_CHECK(output.str().find("CpuAcc") != std::string::npos);
         // output should not contain un-readable numbers
-        BOOST_CHECK(!(boost::contains(output.str(), "e+")));
+        BOOST_CHECK(output.str().find("e+") == std::string::npos);
         // output should not contain un-readable numbers
-        BOOST_CHECK(!(boost::contains(output.str(), "+")));
+        BOOST_CHECK(output.str().find("+") == std::string::npos);
         // output should not contain zero value
-        BOOST_CHECK(!(boost::contains(output.str(), " 0 ")));
+        BOOST_CHECK(output.str().find(" 0 ") == std::string::npos);
     }
 
     // Disable profiling here to not print out anything on stdout.
diff --git a/src/armnn/test/UnitTests.cpp b/src/armnn/test/UnitTests.cpp
index 7d171a8..071bff0 100644
--- a/src/armnn/test/UnitTests.cpp
+++ b/src/armnn/test/UnitTests.cpp
@@ -8,8 +8,6 @@
 #include "UnitTests.hpp"
 #include <armnn/Logging.hpp>
 
-#include <boost/algorithm/string.hpp>
-
 struct ConfigureLoggingFixture
 {
     ConfigureLoggingFixture()
@@ -103,12 +101,12 @@
 
     }
 
-    BOOST_CHECK(boost::contains(ss.str(), "Trace: My trace message; -2"));
-    BOOST_CHECK(boost::contains(ss.str(), "Debug: My debug message; -1"));
-    BOOST_CHECK(boost::contains(ss.str(), "Info: My info message; 0"));
-    BOOST_CHECK(boost::contains(ss.str(), "Warning: My warning message; 1"));
-    BOOST_CHECK(boost::contains(ss.str(), "Error: My error message; 2"));
-    BOOST_CHECK(boost::contains(ss.str(), "Fatal: My fatal message; 3"));
+    BOOST_CHECK(ss.str().find("Trace: My trace message; -2") != std::string::npos);
+    BOOST_CHECK(ss.str().find("Debug: My debug message; -1") != std::string::npos);
+    BOOST_CHECK(ss.str().find("Info: My info message; 0") != std::string::npos);
+    BOOST_CHECK(ss.str().find("Warning: My warning message; 1") != std::string::npos);
+    BOOST_CHECK(ss.str().find("Error: My error message; 2") != std::string::npos);
+    BOOST_CHECK(ss.str().find("Fatal: My fatal message; 3") != std::string::npos);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/armnnConverter/ArmnnConverter.cpp b/src/armnnConverter/ArmnnConverter.cpp
index e0a659d..6d0952a 100644
--- a/src/armnnConverter/ArmnnConverter.cpp
+++ b/src/armnnConverter/ArmnnConverter.cpp
@@ -21,10 +21,9 @@
 #endif
 
 #include <HeapProfiling.hpp>
+#include "armnn/utility/StringUtils.hpp"
 
 #include <boost/format.hpp>
-#include <boost/algorithm/string/split.hpp>
-#include <boost/algorithm/string/classification.hpp>
 #include <boost/program_options.hpp>
 
 #include <cstdlib>
@@ -43,17 +42,7 @@
 
     while (std::getline(stream, line))
     {
-        std::vector<std::string> tokens;
-        try
-        {
-            // Coverity fix: boost::split() may throw an exception of type boost::bad_function_call.
-            boost::split(tokens, line, boost::algorithm::is_any_of(","), boost::token_compress_on);
-        }
-        catch (const std::exception& e)
-        {
-            ARMNN_LOG(error) << "An error occurred when splitting tokens: " << e.what();
-            continue;
-        }
+        std::vector<std::string> tokens = armnn::stringUtils::StringTokenizer(line, ",");
         for (const std::string& token : tokens)
         {
             if (!token.empty())
diff --git a/src/armnnUtils/CsvReader.cpp b/src/armnnUtils/CsvReader.cpp
index ba6c42c..feee4d1 100644
--- a/src/armnnUtils/CsvReader.cpp
+++ b/src/armnnUtils/CsvReader.cpp
@@ -4,8 +4,8 @@
 //
 
 #include "CsvReader.hpp"
+#include "armnn/utility/StringUtils.hpp"
 
-#include <boost/algorithm/string.hpp>
 #include <boost/tokenizer.hpp>
 
 #include <fstream>
@@ -24,7 +24,7 @@
 
     for (const auto &token : tokenizer)
     {
-        entry.values.push_back(boost::trim_copy(token));
+        entry.values.push_back(armnn::stringUtils::StringTrimCopy(token));
     }
     return entry;
 }
diff --git a/src/armnnUtils/DotSerializer.cpp b/src/armnnUtils/DotSerializer.cpp
index 80043a9..87376e6 100644
--- a/src/armnnUtils/DotSerializer.cpp
+++ b/src/armnnUtils/DotSerializer.cpp
@@ -4,8 +4,8 @@
 //
 
 #include "DotSerializer.hpp"
+#include "armnn/utility/StringUtils.hpp"
 
-#include <boost/algorithm/string/replace.hpp>
 #include <sstream>
 #include <cstring>
 
@@ -26,8 +26,8 @@
 
 std::string Escape(std::string s)
 {
-    boost::replace_all(s, "<", "\\<");
-    boost::replace_all(s, ">", "\\>");
+    armnn::stringUtils::StringReplaceAll(s, "<", "\\<");
+    armnn::stringUtils::StringReplaceAll(s, ">", "\\>");
     return s;
 }
 
diff --git a/src/backends/backendsCommon/DynamicBackendUtils.cpp b/src/backends/backendsCommon/DynamicBackendUtils.cpp
index ea08692..5b675ba 100644
--- a/src/backends/backendsCommon/DynamicBackendUtils.cpp
+++ b/src/backends/backendsCommon/DynamicBackendUtils.cpp
@@ -5,9 +5,9 @@
 
 #include <armnn/Logging.hpp>
 #include <backendsCommon/DynamicBackendUtils.hpp>
+#include "armnn/utility/StringUtils.hpp"
 
 #include <boost/filesystem.hpp>
-#include <boost/algorithm/string.hpp>
 
 #include <regex>
 
@@ -110,11 +110,10 @@
     }
 
     std::unordered_set<std::string> uniqueBackendPaths;
-    std::vector<std::string> tempBackendPaths;
     std::vector<std::string> validBackendPaths;
 
     // Split the given list of paths
-    boost::split(tempBackendPaths, backendPaths, boost::is_any_of(":"));
+    std::vector<std::string> tempBackendPaths = armnn::stringUtils::StringTokenizer(backendPaths, ":");
 
     for (const std::string& path : tempBackendPaths)
     {
diff --git a/src/backends/backendsCommon/test/BackendProfilingTests.cpp b/src/backends/backendsCommon/test/BackendProfilingTests.cpp
index 7c78e14..9f1898a 100644
--- a/src/backends/backendsCommon/test/BackendProfilingTests.cpp
+++ b/src/backends/backendsCommon/test/BackendProfilingTests.cpp
@@ -21,7 +21,6 @@
 #include <armnn/Logging.hpp>
 #include <armnn/profiling/ISendTimelinePacket.hpp>
 
-#include <boost/algorithm/string.hpp>
 #include <boost/numeric/conversion/cast.hpp>
 #include <boost/test/unit_test.hpp>
 #include <vector>
@@ -441,7 +440,7 @@
     periodicCounterCapture.Stop();
     SetLogFilter(armnn::LogSeverity::Fatal);
 
-    BOOST_CHECK(boost::contains(ss.str(), "ActivateCounters example test error"));
+    BOOST_CHECK(ss.str().find("ActivateCounters example test error") != std::string::npos);
 }
 
 BOOST_AUTO_TEST_CASE(BackendProfilingContextGetSendTimelinePacket)
diff --git a/src/backends/backendsCommon/test/JsonPrinterTestImpl.cpp b/src/backends/backendsCommon/test/JsonPrinterTestImpl.cpp
index 91ce150..2aa713f 100644
--- a/src/backends/backendsCommon/test/JsonPrinterTestImpl.cpp
+++ b/src/backends/backendsCommon/test/JsonPrinterTestImpl.cpp
@@ -4,6 +4,7 @@
 //
 
 #include "JsonPrinterTestImpl.hpp"
+#include "armnn/utility/StringUtils.hpp"
 
 #include <Profiling.hpp>
 
@@ -11,7 +12,6 @@
 #include <armnn/IRuntime.hpp>
 #include <armnn/INetwork.hpp>
 
-#include <boost/algorithm/string.hpp>
 #include <boost/test/unit_test.hpp>
 
 #include <sstream>
@@ -62,7 +62,7 @@
         {
             try
             {
-                boost::trim_if(numberString, boost::is_any_of("\t,\n"));
+                armnn::stringUtils::StringTrim(numberString, "\t,\n");
                 numbers.push_back(std::stod(numberString));
             }
             catch (std::invalid_argument const& e)
@@ -77,7 +77,7 @@
         {
             try
             {
-                boost::trim_if(numberString, boost::is_any_of("\t,\n"));
+                armnn::stringUtils::StringTrim(numberString, "\t,\n");
                 numbers.push_back(std::stod(numberString));
             }
             catch (std::invalid_argument const& e)
@@ -212,8 +212,9 @@
         std::vector<std::string> sectionVector = ExtractSections(result);
         for (size_t i = 0; i < sectionVector.size(); ++i)
         {
-            if (boost::contains(sectionVector[i], "\"ArmNN\":")
-                || boost::contains(sectionVector[i], "\"inference_measurements\":"))
+
+            if (sectionVector[i].find("\"ArmNN\":") != std::string::npos
+                || sectionVector[i].find("\"inference_measurements\":") != std::string::npos)
             {
                 sectionVector.erase(sectionVector.begin() + static_cast<int>(i));
             }
@@ -221,10 +222,10 @@
         BOOST_CHECK(!sectionVector.empty());
 
         BOOST_CHECK(std::all_of(sectionVector.begin(), sectionVector.end(),
-                                [](std::string i) { return boost::contains(i, "\"raw\":"); }));
+                                [](std::string i) { return (i.find("\"raw\":") != std::string::npos); }));
 
         BOOST_CHECK(std::all_of(sectionVector.begin(), sectionVector.end(),
-                                [](std::string i) { return boost::contains(i, "\"unit\":"); }));
+                                [](std::string i) { return (i.find("\"unit\":") != std::string::npos); }));
     }
 
     // remove the time measurements as they vary from test to test
@@ -234,8 +235,8 @@
     result.erase(std::remove_if (result.begin(),result.end(),
                                  [](char c) { return c == '\t'; }), result.end());
 
-    BOOST_CHECK(boost::contains(result, "ArmNN"));
-    BOOST_CHECK(boost::contains(result, "inference_measurements"));
+    BOOST_CHECK(result.find("ArmNN") != std::string::npos);
+    BOOST_CHECK(result.find("inference_measurements") != std::string::npos);
 
     // ensure no spare parenthesis present in print output
     BOOST_CHECK(AreParenthesesMatching(result));
@@ -252,12 +253,11 @@
     const armnn::BackendId& firstBackend = backends.at(0);
     if (firstBackend == armnn::Compute::GpuAcc)
     {
-        BOOST_CHECK(boost::contains(result,
-            "OpenClKernelTimer/: softmax_layer_max_shift_exp_sum_quantized_serial GWS[,,]"));
+        BOOST_CHECK(result.find("OpenClKernelTimer/: softmax_layer_max_shift_exp_sum_quantized_serial GWS[,,]")
+                    != std::string::npos);
     }
     else if (firstBackend == armnn::Compute::CpuAcc)
     {
-        BOOST_CHECK(boost::contains(result,
-            "NeonKernelTimer/: NEFillBorderKernel"));
+        BOOST_CHECK(result.find("NeonKernelTimer/: NEFillBorderKernel") != std::string::npos);
     }
 }
diff --git a/src/backends/reference/test/RefLayerSupportTests.cpp b/src/backends/reference/test/RefLayerSupportTests.cpp
index f0c69f9..1d4b4a0 100644
--- a/src/backends/reference/test/RefLayerSupportTests.cpp
+++ b/src/backends/reference/test/RefLayerSupportTests.cpp
@@ -14,7 +14,6 @@
 #include <backendsCommon/test/IsLayerSupportedTestImpl.hpp>
 
 #include <boost/test/unit_test.hpp>
-#include <boost/algorithm/string/trim.hpp>
 
 #include <string>
 
@@ -231,9 +230,9 @@
 
     BOOST_CHECK(!result);
 
-    boost::algorithm::trim(reasonIfUnsupported);
-    BOOST_CHECK_EQUAL(reasonIfUnsupported,
-                      "Reference Mean: Expected 4 dimensions but got 2 dimensions instead, for the 'output' tensor.");
+    BOOST_CHECK(reasonIfUnsupported.find(
+        "Reference Mean: Expected 4 dimensions but got 2 dimensions instead, for the 'output' tensor.")
+        != std::string::npos);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/profiling/test/ProfilingTests.cpp b/src/profiling/test/ProfilingTests.cpp
index f252579..b3326e0 100644
--- a/src/profiling/test/ProfilingTests.cpp
+++ b/src/profiling/test/ProfilingTests.cpp
@@ -37,7 +37,6 @@
 #include <armnn/Utils.hpp>
 #include <armnn/utility/IgnoreUnused.hpp>
 
-#include <boost/algorithm/string.hpp>
 #include <boost/numeric/conversion/cast.hpp>
 
 #include <cstdint>
@@ -3054,7 +3053,7 @@
     streamRedirector.CancelRedirect();
 
     // Check that the expected error has occurred and logged to the standard output
-    if (!boost::contains(ss.str(), "Cannot connect to stream socket: Connection refused"))
+    if (ss.str().find("Cannot connect to stream socket: Connection refused") == std::string::npos)
     {
         std::cout << ss.str();
         BOOST_FAIL("Expected string not found.");
@@ -3089,7 +3088,7 @@
     streamRedirector.CancelRedirect();
 
     // Check that the expected error has occurred and logged to the standard output
-    if (!boost::contains(ss.str(), "Cannot connect to stream socket: Connection refused"))
+    if (ss.str().find("Cannot connect to stream socket: Connection refused") == std::string::npos)
     {
         std::cout << ss.str();
         BOOST_FAIL("Expected string not found.");
@@ -3152,7 +3151,7 @@
     streamRedirector.CancelRedirect();
 
     // Check that the expected error has occurred and logged to the standard output
-    if (!boost::contains(ss.str(), "Functor with requested PacketId=37 and Version=4194304 does not exist"))
+    if (ss.str().find("Functor with requested PacketId=37 and Version=4194304 does not exist") == std::string::npos)
     {
         std::cout << ss.str();
         BOOST_FAIL("Expected string not found.");
@@ -3216,7 +3215,7 @@
     streamRedirector.CancelRedirect();
 
     // Check that the expected error has occurred and logged to the standard output
-    if (!boost::contains(ss.str(), "Functor with requested PacketId=123 and Version=4194304 does not exist"))
+    if (ss.str().find("Functor with requested PacketId=123 and Version=4194304 does not exist") == std::string::npos)
     {
         std::cout << ss.str();
         BOOST_FAIL("Expected string not found.");
@@ -3280,7 +3279,7 @@
     streamRedirector.CancelRedirect();
 
     // Check that the expected error has occurred and logged to the standard output
-    if (!boost::contains(ss.str(), "Functor with requested PacketId=999 and Version=4194304 does not exist"))
+    if (ss.str().find("Functor with requested PacketId=999 and Version=4194304 does not exist") == std::string::npos)
     {
         std::cout << ss.str();
         BOOST_FAIL("Expected string not found.");
@@ -3604,7 +3603,7 @@
     streamRedirector.CancelRedirect();
 
     // Check that the expected error has occurred and logged to the standard output
-    if (!boost::contains(ss.str(), "Unsupported profiling file format, only binary is supported"))
+    if (ss.str().find("Unsupported profiling file format, only binary is supported") == std::string::npos)
     {
         std::cout << ss.str();
         BOOST_FAIL("Expected string not found.");
diff --git a/tests/DeepSpeechV1Database.hpp b/tests/DeepSpeechV1Database.hpp
index 8152377..85654b6 100644
--- a/tests/DeepSpeechV1Database.hpp
+++ b/tests/DeepSpeechV1Database.hpp
@@ -30,17 +30,7 @@
     std::string line;
     while (std::getline(stream, line))
     {
-        std::vector<std::string> tokens;
-        try
-        {
-            // Coverity fix: boost::split() may throw an exception of type boost::bad_function_call.
-            boost::split(tokens, line, boost::algorithm::is_any_of(chars), boost::token_compress_on);
-        }
-        catch (const std::exception& e)
-        {
-            ARMNN_LOG(error) << "An error occurred when splitting tokens: " << e.what();
-            continue;
-        }
+        std::vector<std::string> tokens = armnn::stringUtils::StringTokenizer(line, chars);
         for (const std::string& token : tokens)
         {
             if (!token.empty()) // See https://stackoverflow.com/questions/10437406/
diff --git a/tests/InferenceModel.hpp b/tests/InferenceModel.hpp
index af931f9..410bc7c 100644
--- a/tests/InferenceModel.hpp
+++ b/tests/InferenceModel.hpp
@@ -22,7 +22,7 @@
 #include <HeapProfiling.hpp>
 #include <TensorIOUtils.hpp>
 
-#include <boost/algorithm/string/join.hpp>
+#include "armnn/utility/StringUtils.hpp"
 #include <boost/exception/exception.hpp>
 #include <boost/exception/diagnostic_information.hpp>
 #include <boost/format.hpp>
@@ -354,7 +354,7 @@
             ("model-dir,m", po::value<std::string>(&options.m_ModelDir)->required(),
                 "Path to directory containing model files (.caffemodel/.prototxt/.tflite)")
             ("compute,c", po::value<std::vector<std::string>>(&options.m_ComputeDevices)->
-                default_value(defaultComputes, boost::algorithm::join(defaultComputes, ", "))->
+                default_value(defaultComputes, armnn::stringUtils::StringConcat(defaultComputes, ", "))->
                 multitoken(), backendsMessage.c_str())
             ("dynamic-backends-path,b", po::value(&options.m_DynamicBackendsPath),
                 "Path where to load any available dynamic backend from. "
diff --git a/tests/InferenceTest.cpp b/tests/InferenceTest.cpp
index 7e165b5..1df399b 100644
--- a/tests/InferenceTest.cpp
+++ b/tests/InferenceTest.cpp
@@ -7,7 +7,6 @@
 #include <armnn/utility/Assert.hpp>
 
 #include "../src/armnn/Profiling.hpp"
-#include <boost/algorithm/string.hpp>
 #include <boost/numeric/conversion/cast.hpp>
 #include <boost/filesystem/path.hpp>
 #include <boost/format.hpp>
diff --git a/tests/InferenceTest.inl b/tests/InferenceTest.inl
index ed16464..32a164d 100644
--- a/tests/InferenceTest.inl
+++ b/tests/InferenceTest.inl
@@ -5,7 +5,6 @@
 #include "InferenceTest.hpp"
 
 #include <armnn/utility/Assert.hpp>
-#include <boost/algorithm/string.hpp>
 #include <boost/numeric/conversion/cast.hpp>
 #include <boost/filesystem/path.hpp>
 #include <boost/format.hpp>
diff --git a/tests/ModelAccuracyTool-Armnn/ModelAccuracyTool-Armnn.cpp b/tests/ModelAccuracyTool-Armnn/ModelAccuracyTool-Armnn.cpp
index dd1c295..20f6180 100644
--- a/tests/ModelAccuracyTool-Armnn/ModelAccuracyTool-Armnn.cpp
+++ b/tests/ModelAccuracyTool-Armnn/ModelAccuracyTool-Armnn.cpp
@@ -8,7 +8,6 @@
 #include "ModelAccuracyChecker.hpp"
 #include "armnnDeserializer/IDeserializer.hpp"
 
-#include <boost/algorithm/string.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/program_options/variables_map.hpp>
 #include <boost/range/iterator_range.hpp>
diff --git a/tests/NetworkExecutionUtils/NetworkExecutionUtils.hpp b/tests/NetworkExecutionUtils/NetworkExecutionUtils.hpp
index 278ba1b..a922228 100644
--- a/tests/NetworkExecutionUtils/NetworkExecutionUtils.hpp
+++ b/tests/NetworkExecutionUtils/NetworkExecutionUtils.hpp
@@ -26,9 +26,6 @@
 #include <Profiling.hpp>
 #include <ResolveType.hpp>
 
-#include <boost/algorithm/string/trim.hpp>
-#include <boost/algorithm/string/split.hpp>
-#include <boost/algorithm/string/classification.hpp>
 #include <boost/program_options.hpp>
 #include <boost/variant.hpp>
 
@@ -53,17 +50,7 @@
     std::string line;
     while (std::getline(stream, line))
     {
-        std::vector<std::string> tokens;
-        try
-        {
-            // Coverity fix: boost::split() may throw an exception of type boost::bad_function_call.
-            boost::split(tokens, line, boost::algorithm::is_any_of(chars), boost::token_compress_on);
-        }
-        catch (const std::exception& e)
-        {
-            ARMNN_LOG(error) << "An error occurred when splitting tokens: " << e.what();
-            continue;
-        }
+        std::vector<std::string> tokens = armnn::stringUtils::StringTokenizer(line, chars);
         for (const std::string& token : tokens)
         {
             if (!token.empty()) // See https://stackoverflow.com/questions/10437406/
@@ -174,7 +161,8 @@
 std::vector<std::string> ParseStringList(const std::string & inputString, const char * delimiter)
 {
     std::stringstream stream(inputString);
-    return ParseArrayImpl<std::string>(stream, [](const std::string& s) { return boost::trim_copy(s); }, delimiter);
+    return ParseArrayImpl<std::string>(stream, [](const std::string& s) {
+           return armnn::stringUtils::StringTrimCopy(s); }, delimiter);
 }
 
 void RemoveDuplicateDevices(std::vector<armnn::BackendId>& computeDevices)
@@ -559,8 +547,8 @@
             bool parseUnsupported = false,
             const std::shared_ptr<armnn::IRuntime>& runtime = nullptr)
 {
-    std::string modelFormat = boost::trim_copy(format);
-    std::string modelPath = boost::trim_copy(path);
+    std::string modelFormat = armnn::stringUtils::StringTrimCopy(format);
+    std::string modelPath = armnn::stringUtils::StringTrimCopy(path);
     std::vector<std::string> inputNamesVector = ParseStringList(inputNames, ",");
     std::vector<std::string> inputTensorShapesVector = ParseStringList(inputTensorShapesStr, ":");
     std::vector<std::string> inputTensorDataFilePathsVector = ParseStringList(