+ return str_starts_with(str, std::basic_string<T>(prefix),
+ case_insensitive);
+}
+
+
+/**
+ * Check whether \p str ends with the string suffix. If \p case_insensitive
+ * is true then the check is case insensitve (default is false; i.e. case is
+ * significant).
+ *
+ * @param str
+ * @param suffix
+ * @param case_insensitive
+ * @return true if the str begins with suffix
+ */
+template <typename T>
+inline bool str_ends_with(const std::basic_string<T> &str,
+ const std::basic_string<T> &suffix,
+ bool case_insensitive = false)
+{
+ if (str.size() < suffix.size())
+ return false;
+
+ size_t start = str.size() - suffix.size();
+ if (!case_insensitive)
+ return str.compare(start, suffix.size(), suffix) == 0;
+
+ for (size_t i = 0; i < suffix.size(); ++i)
+ if (tolower(str[start + i]) != tolower(suffix[i]))
+ return false;
+ return true;
+}
+
+
+/**
+ * Check whether \p str ends with the string suffix. If \p case_insensitive
+ * is true then the check is case insensitve (default is false; i.e. case is
+ * significant).
+ *
+ * @param str
+ * @param suffix
+ * @param case_insensitive
+ * @return true if the str begins with suffix
+ */
+template <typename T>
+inline bool str_ends_with(const std::basic_string<T> &str,
+ const T *suffix,
+ bool case_insensitive = false)
+{
+ return str_ends_with(str, std::basic_string<T>(suffix),
+ case_insensitive);
+}
+
+
+/**
+ * Splits a string into its component parts separated by the character
+ * \p delimiter.
+ *
+ * @return An std::vector<std::basic_string<T> > of the component parts
+ */
+template <typename T>
+inline std::vector<std::basic_string<T> > str_split(
+ const std::basic_string<T> &str,
+ T delimiter)
+{
+ std::vector<std::basic_string<T> > parts;
+ std::basic_stringstream<T> sstr(str);
+ std::basic_string<T> part;
+
+ while (std::getline(sstr, part, delimiter))