// Copyright (c) 2022 Dominic Masters // // This software is released under the MIT License. // https://opensource.org/licenses/MIT #pragma once #include "assert/assert.hpp" /** * Finds the next instance of a character within a string, safely (with a * limit). The returned pointer will be NULL if not found, or a pointer to a * point within the string where the instance is. * * @param haystack String to search. * @param needle Character to search for. * @param limit Max length you want to search for to limit yourself to. * @return Pointer to the character found, or NULL if not found. */ static inline char * stringFindNext( char *haystack, char needle, size_t limit ) { char *p; assertNotNull(haystack, "String find haystack cannot be null"); assertTrue(limit > 0, "String find limit must be greater than 0"); for(p = haystack; (size_t)(p - haystack) < limit; p++) { if(*p == needle) return p; assertFalse(*p == '\0', "String find limit reached"); } return NULL; } /** * Splits a string into a vector of strings, using a delimiter. * * @param s String to split. * @param delim Delimiter to split by. * @return Vector of strings. */ static inline std::vector stringSplit( const std::string &s, const std::string delim ) { size_t posStart = 0, posEnd, delimLength = delim.length(); std::string token; std::vector res; while((posEnd = s.find(delim, posStart)) != std::string::npos) { token = s.substr(posStart, posEnd - posStart); posStart = posEnd + delimLength; res.push_back (token); } res.push_back(s.substr(posStart)); return res; } /** * Trims the whitespace from the left side of a string. * * @param i Input string to trim. * @return Trimmed string. */ static inline std::string stringLTrim(const std::string &i) { std::string s = i; s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); return s; } /** * Trims the whitespace from the right side of a string. * * @param i Input string to trim. * @return Trimmed string. */ static inline std::string stringRTrim(const std::string &i) { std::string s = i; s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); return s; } /** * Trims the whitespace from both sides of a string. * * @param s Input string to trim. * @return Trimmed string. */ static inline std::string stringTrim(const std::string &s) { return stringLTrim(stringRTrim(s)); } /** * Checks if a string contains another string. * * @param haystack String to scan. * @param needle String to search for. * @return True if the string is found, false otherwise. */ static inline bool_t stringIncludes(const std::string &haystack, const std::string &needle) { return haystack.find(needle) != std::string::npos; } /** * Converts an entire string to lowercase. * * @param str String to convert. * @return A new string with all lowercase characters. */ static inline std::string stringToLowercase(const std::string &str) { std::string data = str; std::transform( data.begin(), data.end(), data.begin(), [](char c) { return std::tolower(c); } ); return data; } /** * Replace all instances of a string with another string within a string. * * @param str String to replace the contents of. * @param needle Needle to look for. * @param replace String to replace the needle with. * @return A new string instance with the replacements made. */ static inline std::string stringReplaceAll( const std::string &str, const std::string &needle, const std::string &replace ) { std::string newString = str; size_t startPos = 0; while((startPos = newString.find(needle, startPos)) != std::string::npos) { newString.replace(startPos, needle.length(), replace); startPos += replace.length(); } return newString; } /** * Joins a vector of strings into a single string, using a delimiter. * * @param strings Vector of strings to join. * @param delim Delimiter to join the strings with. */ static inline std::string stringJoin( const std::vector &strings, const std::string &delim ) { std::string result; for(size_t i = 0; i < strings.size(); i++) { if(i > 0) result += delim; result += strings[i]; } return result; }