LCOV - code coverage report
Current view: top level - src/util - string.h (source / functions) Hit Total Coverage
Test: report Lines: 69 111 62.2 %
Date: 2015-07-11 18:23:49 Functions: 17 26 65.4 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
       4             : 
       5             : This program is free software; you can redistribute it and/or modify
       6             : it under the terms of the GNU Lesser General Public License as published by
       7             : the Free Software Foundation; either version 2.1 of the License, or
       8             : (at your option) any later version.
       9             : 
      10             : This program is distributed in the hope that it will be useful,
      11             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             : GNU Lesser General Public License for more details.
      14             : 
      15             : You should have received a copy of the GNU Lesser General Public License along
      16             : with this program; if not, write to the Free Software Foundation, Inc.,
      17             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             : */
      19             : 
      20             : #ifndef UTIL_STRING_HEADER
      21             : #define UTIL_STRING_HEADER
      22             : 
      23             : #include "irrlichttypes_bloated.h"
      24             : #include <stdlib.h>
      25             : #include <string>
      26             : #include <cstring>
      27             : #include <vector>
      28             : #include <map>
      29             : #include <sstream>
      30             : #include <cctype>
      31             : 
      32             : #define STRINGIFY(x) #x
      33             : #define TOSTRING(x) STRINGIFY(x)
      34             : 
      35             : // Checks whether a byte is an inner byte for an utf-8 multibyte sequence
      36             : #define IS_UTF8_MULTB_INNER(x) (((unsigned char)x >= 0x80) && ((unsigned char)x < 0xc0))
      37             : 
      38             : typedef std::map<std::string, std::string> StringMap;
      39             : 
      40             : struct FlagDesc {
      41             :         const char *name;
      42             :         u32 flag;
      43             : };
      44             : 
      45             : // try not to convert between wide/utf8 encodings; this can result in data loss
      46             : // try to only convert between them when you need to input/output stuff via Irrlicht
      47             : std::wstring utf8_to_wide(const std::string &input);
      48             : std::string wide_to_utf8(const std::wstring &input);
      49             : 
      50             : // NEVER use those two functions unless you have a VERY GOOD reason to
      51             : // they just convert between wide and multibyte encoding
      52             : // multibyte encoding depends on current locale, this is no good, especially on Windows
      53             : 
      54             : // You must free the returned string!
      55             : // The returned string is allocated using new
      56             : wchar_t *narrow_to_wide_c(const char *str);
      57             : std::wstring narrow_to_wide(const std::string &mbs);
      58             : std::string wide_to_narrow(const std::wstring &wcs);
      59             : 
      60             : std::string urlencode(std::string str);
      61             : std::string urldecode(std::string str);
      62             : u32 readFlagString(std::string str, const FlagDesc *flagdesc, u32 *flagmask);
      63             : std::string writeFlagString(u32 flags, const FlagDesc *flagdesc, u32 flagmask);
      64             : size_t mystrlcpy(char *dst, const char *src, size_t size);
      65             : char *mystrtok_r(char *s, const char *sep, char **lasts);
      66             : u64 read_seed(const char *str);
      67             : bool parseColorString(const std::string &value, video::SColor &color, bool quiet);
      68             : 
      69             : 
      70             : /**
      71             :  * Returns a copy of \p str with spaces inserted at the right hand side to ensure
      72             :  * that the string is \p len characters in length. If \p str is <= \p len then the
      73             :  * returned string will be identical to str.
      74             :  */
      75           0 : inline std::string padStringRight(std::string str, size_t len)
      76             : {
      77           0 :         if (len > str.size())
      78           0 :                 str.insert(str.end(), len - str.size(), ' ');
      79             : 
      80           0 :         return str;
      81             : }
      82             : 
      83             : /**
      84             :  * Returns a version of \p str with the first occurrence of a string
      85             :  * contained within ends[] removed from the end of the string.
      86             :  *
      87             :  * @param str
      88             :  * @param ends A NULL- or ""- terminated array of strings to remove from s in
      89             :  *      the copy produced.  Note that once one of these strings is removed
      90             :  *      that no further postfixes contained within this array are removed.
      91             :  *
      92             :  * @return If no end could be removed then "" is returned.
      93             :  */
      94        9890 : inline std::string removeStringEnd(const std::string &str,
      95             :                 const char *ends[])
      96             : {
      97        9890 :         const char **p = ends;
      98             : 
      99       24282 :         for (; *p && (*p)[0] != '\0'; p++) {
     100       23724 :                 std::string end = *p;
     101       16528 :                 if (str.size() < end.size())
     102           0 :                         continue;
     103       16528 :                 if (str.compare(str.size() - end.size(), end.size(), end) == 0)
     104        9332 :                         return str.substr(0, str.size() - end.size());
     105             :         }
     106             : 
     107         558 :         return "";
     108             : }
     109             : 
     110             : 
     111             : /**
     112             :  * Check two strings for equivalence.  If \p case_insensitive is true
     113             :  * then the case of the strings is ignored (default is false).
     114             :  *
     115             :  * @param s1
     116             :  * @param s2
     117             :  * @param case_insensitive
     118             :  * @return true if the strings match
     119             :  */
     120             : template <typename T>
     121           0 : inline bool str_equal(const std::basic_string<T> &s1,
     122             :                 const std::basic_string<T> &s2,
     123             :                 bool case_insensitive = false)
     124             : {
     125           0 :         if (!case_insensitive)
     126           0 :                 return s1 == s2;
     127             : 
     128           0 :         if (s1.size() != s2.size())
     129           0 :                 return false;
     130             : 
     131           0 :         for (size_t i = 0; i < s1.size(); ++i)
     132           0 :                 if(tolower(s1[i]) != tolower(s2[i]))
     133           0 :                         return false;
     134             : 
     135           0 :         return true;
     136             : }
     137             : 
     138             : 
     139             : /**
     140             :  * Check whether \p str begins with the string prefix. If \p case_insensitive
     141             :  * is true then the check is case insensitve (default is false; i.e. case is
     142             :  * significant).
     143             :  *
     144             :  * @param str
     145             :  * @param prefix
     146             :  * @param case_insensitive
     147             :  * @return true if the str begins with prefix
     148             :  */
     149             : template <typename T>
     150       27280 : inline bool str_starts_with(const std::basic_string<T> &str,
     151             :                 const std::basic_string<T> &prefix,
     152             :                 bool case_insensitive = false)
     153             : {
     154       27280 :         if (str.size() < prefix.size())
     155           0 :                 return false;
     156             : 
     157       27280 :         if (!case_insensitive)
     158       27280 :                 return str.compare(0, prefix.size(), prefix) == 0;
     159             : 
     160           0 :         for (size_t i = 0; i < prefix.size(); ++i)
     161           0 :                 if (tolower(str[i]) != tolower(prefix[i]))
     162           0 :                         return false;
     163           0 :         return true;
     164             : }
     165             : 
     166             : /**
     167             :  * Check whether \p str begins with the string prefix. If \p case_insensitive
     168             :  * is true then the check is case insensitve (default is false; i.e. case is
     169             :  * significant).
     170             :  *
     171             :  * @param str
     172             :  * @param prefix
     173             :  * @param case_insensitive
     174             :  * @return true if the str begins with prefix
     175             :  */
     176             : template <typename T>
     177       27280 : inline bool str_starts_with(const std::basic_string<T> &str,
     178             :                 const T *prefix,
     179             :                 bool case_insensitive = false)
     180             : {
     181       54560 :         return str_starts_with(str, std::basic_string<T>(prefix),
     182       54560 :                         case_insensitive);
     183             : }
     184             : 
     185             : /**
     186             :  * Splits a string into its component parts separated by the character
     187             :  * \p delimiter.
     188             :  *
     189             :  * @return An std::vector<std::basic_string<T> > of the component parts
     190             :  */
     191             : template <typename T>
     192           0 : inline std::vector<std::basic_string<T> > str_split(
     193             :                 const std::basic_string<T> &str,
     194             :                 T delimiter)
     195             : {
     196           0 :         std::vector<std::basic_string<T> > parts;
     197           0 :         std::basic_stringstream<T> sstr(str);
     198           0 :         std::basic_string<T> part;
     199             : 
     200           0 :         while (std::getline(sstr, part, delimiter))
     201           0 :                 parts.push_back(part);
     202             : 
     203           0 :         return parts;
     204             : }
     205             : 
     206             : 
     207             : /**
     208             :  * @param str
     209             :  * @return A copy of \p str converted to all lowercase characters.
     210             :  */
     211       77537 : inline std::string lowercase(const std::string &str)
     212             : {
     213       77537 :         std::string s2;
     214             : 
     215       77537 :         s2.reserve(str.size());
     216             : 
     217      453780 :         for (size_t i = 0; i < str.size(); i++)
     218      376243 :                 s2 += tolower(str[i]);
     219             : 
     220       77537 :         return s2;
     221             : }
     222             : 
     223             : 
     224             : /**
     225             :  * @param str
     226             :  * @return A copy of \p str with leading and trailing whitespace removed.
     227             :  */
     228       78336 : inline std::string trim(const std::string &str)
     229             : {
     230       78336 :         size_t front = 0;
     231             : 
     232       78994 :         while (std::isspace(str[front]))
     233         329 :                 ++front;
     234             : 
     235       78336 :         size_t back = str.size();
     236       79002 :         while (back > front && std::isspace(str[back - 1]))
     237         333 :                 --back;
     238             : 
     239       78336 :         return str.substr(front, back - front);
     240             : }
     241             : 
     242             : 
     243             : /**
     244             :  * Returns whether \p str should be regarded as (bool) true.  Case and leading
     245             :  * and trailing whitespace are ignored.  Values that will return
     246             :  * true are "y", "yes", "true" and any number that is not 0.
     247             :  * @param str
     248             :  */
     249       76997 : inline bool is_yes(const std::string &str)
     250             : {
     251      153994 :         std::string s2 = lowercase(trim(str));
     252             : 
     253      153994 :         return s2 == "y" || s2 == "yes" || s2 == "true" || atoi(s2.c_str()) != 0;
     254             : }
     255             : 
     256             : 
     257             : /**
     258             :  * Converts the string \p str to a signed 32-bit integer. The converted value
     259             :  * is constrained so that min <= value <= max.
     260             :  *
     261             :  * @see atoi(3) for limitations
     262             :  *
     263             :  * @param str
     264             :  * @param min Range minimum
     265             :  * @param max Range maximum
     266             :  * @return The value converted to a signed 32-bit integer and constrained
     267             :  *      within the range defined by min and max (inclusive)
     268             :  */
     269       10372 : inline s32 mystoi(const std::string &str, s32 min, s32 max)
     270             : {
     271       10372 :         s32 i = atoi(str.c_str());
     272             : 
     273       10372 :         if (i < min)
     274           0 :                 i = min;
     275       10372 :         if (i > max)
     276           0 :                 i = max;
     277             : 
     278       10372 :         return i;
     279             : }
     280             : 
     281             : 
     282             : /// Returns a 64-bit value represented by the string \p str (decimal).
     283             : inline s64 stoi64(const std::string &str)
     284             : {
     285             :         std::stringstream tmp(str);
     286             :         s64 t;
     287             :         tmp >> t;
     288             :         return t;
     289             : }
     290             : 
     291             : // MSVC2010 includes it's own versions of these
     292             : //#if !defined(_MSC_VER) || _MSC_VER < 1600
     293             : 
     294             : 
     295             : /**
     296             :  * Returns a 32-bit value reprensented by the string \p str (decimal).
     297             :  * @see atoi(3) for further limitations
     298             :  */
     299        4420 : inline s32 mystoi(const std::string &str)
     300             : {
     301        4420 :         return atoi(str.c_str());
     302             : }
     303             : 
     304             : 
     305             : /**
     306             :  * Returns s 32-bit value represented by the wide string \p str (decimal).
     307             :  * @see atoi(3) for further limitations
     308             :  */
     309             : inline s32 mystoi(const std::wstring &str)
     310             : {
     311             :         return mystoi(wide_to_narrow(str));
     312             : }
     313             : 
     314             : 
     315             : /**
     316             :  * Returns a float reprensented by the string \p str (decimal).
     317             :  * @see atof(3)
     318             :  */
     319        7872 : inline float mystof(const std::string &str)
     320             : {
     321        7872 :         return atof(str.c_str());
     322             : }
     323             : 
     324             : //#endif
     325             : 
     326             : #define stoi mystoi
     327             : #define stof mystof
     328             : 
     329             : // TODO: Replace with C++11 std::to_string.
     330             : 
     331             : /// Returns A string representing the value \p val.
     332             : template <typename T>
     333       85275 : inline std::string to_string(T val)
     334             : {
     335      170559 :         std::ostringstream oss;
     336       85283 :         oss << val;
     337      170552 :         return oss.str();
     338             : }
     339             : 
     340             : /// Returns a string representing the decimal value of the 32-bit value \p i.
     341       85098 : inline std::string itos(s32 i) { return to_string(i); }
     342             : /// Returns a string representing the decimal value of the 64-bit value \p i.
     343             : inline std::string i64tos(s64 i) { return to_string(i); }
     344             : /// Returns a string representing the decimal value of the float value \p f.
     345         175 : inline std::string ftos(float f) { return to_string(f); }
     346             : 
     347             : 
     348             : /**
     349             :  * Replace all occurrences of \p pattern in \p str with \p replacement.
     350             :  *
     351             :  * @param str String to replace pattern with replacement within.
     352             :  * @param pattern The pattern to replace.
     353             :  * @param replacement What to replace the pattern with.
     354             :  */
     355           0 : inline void str_replace(std::string &str, const std::string &pattern,
     356             :                 const std::string &replacement)
     357             : {
     358           0 :         std::string::size_type start = str.find(pattern, 0);
     359           0 :         while (start != str.npos) {
     360           0 :                 str.replace(start, pattern.size(), replacement);
     361           0 :                 start = str.find(pattern, start + replacement.size());
     362             :         }
     363           0 : }
     364             : 
     365             : 
     366             : /**
     367             :  * Replace all occurrences of the character \p from in \p str with \p to.
     368             :  *
     369             :  * @param str The string to (potentially) modify.
     370             :  * @param from The character in str to replace.
     371             :  * @param to The replacement character.
     372             :  */
     373             : void str_replace(std::string &str, char from, char to);
     374             : 
     375             : 
     376             : /**
     377             :  * Check that a string only contains whitelisted characters. This is the
     378             :  * opposite of string_allowed_blacklist().
     379             :  *
     380             :  * @param str The string to be checked.
     381             :  * @param allowed_chars A string containing permitted characters.
     382             :  * @return true if the string is allowed, otherwise false.
     383             :  *
     384             :  * @see string_allowed_blacklist()
     385             :  */
     386        2635 : inline bool string_allowed(const std::string &str, const std::string &allowed_chars)
     387             : {
     388        2635 :         return str.find_first_not_of(allowed_chars) == str.npos;
     389             : }
     390             : 
     391             : 
     392             : /**
     393             :  * Check that a string contains no blacklisted characters. This is the
     394             :  * opposite of string_allowed().
     395             :  *
     396             :  * @param str The string to be checked.
     397             :  * @param blacklisted_chars A string containing prohibited characters.
     398             :  * @return true if the string is allowed, otherwise false.
     399             : 
     400             :  * @see string_allowed()
     401             :  */
     402           0 : inline bool string_allowed_blacklist(const std::string &str,
     403             :                 const std::string &blacklisted_chars)
     404             : {
     405           0 :         return str.find_first_of(blacklisted_chars) == str.npos;
     406             : }
     407             : 
     408             : 
     409             : /**
     410             :  * Create a string based on \p from where a newline is forcefully inserted
     411             :  * every \p row_len characters.
     412             :  *
     413             :  * @note This function does not honour word wraps and blindy inserts a newline
     414             :  *      every \p row_len characters whether it breaks a word or not.  It is
     415             :  *      intended to be used for, for example, showing paths in the GUI.
     416             :  *
     417             :  * @note This function doesn't wrap inside utf-8 multibyte sequences and also
     418             :  *      counts multibyte sequences correcly as single characters.
     419             :  *
     420             :  * @param from The (utf-8) string to be wrapped into rows.
     421             :  * @param row_len The row length (in characters).
     422             :  * @return A new string with the wrapping applied.
     423             :  */
     424           1 : inline std::string wrap_rows(const std::string &from,
     425             :                 unsigned row_len)
     426             : {
     427           1 :         std::string to;
     428             : 
     429           1 :         size_t character_idx = 0;
     430          22 :         for (size_t i = 0; i < from.size(); i++) {
     431          21 :                 if (!IS_UTF8_MULTB_INNER(from[i])) {
     432             :                         // Wrap string after last inner byte of char
     433          21 :                         if (character_idx > 0 && character_idx % row_len == 0)
     434           1 :                                 to += '\n';
     435          21 :                         character_idx++;
     436             :                 }
     437          21 :                 to += from[i];
     438             :         }
     439             : 
     440           1 :         return to;
     441             : }
     442             : 
     443             : 
     444             : /**
     445             :  * Removes backslashes from an escaped string (FormSpec strings)
     446             :  */
     447             : template <typename T>
     448          40 : inline std::basic_string<T> unescape_string(std::basic_string<T> &s)
     449             : {
     450          40 :         std::basic_string<T> res;
     451             : 
     452         751 :         for (size_t i = 0; i < s.length(); i++) {
     453         711 :                 if (s[i] == '\\') {
     454           0 :                         i++;
     455           0 :                         if (i >= s.length())
     456           0 :                                 break;
     457             :                 }
     458         711 :                 res += s[i];
     459             :         }
     460             : 
     461          40 :         return res;
     462             : }
     463             : 
     464             : 
     465             : /**
     466             :  * Checks that all characters in \p to_check are a decimal digits.
     467             :  *
     468             :  * @param to_check
     469             :  * @return true if to_check is not empty and all characters in to_check are
     470             :  *      decimal digits, otherwise false
     471             :  */
     472         203 : inline bool is_number(const std::string &to_check)
     473             : {
     474         721 :         for (size_t i = 0; i < to_check.size(); i++)
     475         518 :                 if (!std::isdigit(to_check[i]))
     476           0 :                         return false;
     477             : 
     478         203 :         return !to_check.empty();
     479             : }
     480             : 
     481             : 
     482             : /**
     483             :  * Returns a C-string, either "true" or "false", corresponding to \p val.
     484             :  *
     485             :  * @return If \p val is true, then "true" is returned, otherwise "false".
     486             :  */
     487           0 : inline const char *bool_to_cstr(bool val)
     488             : {
     489           0 :         return val ? "true" : "false";
     490             : }
     491             : 
     492             : #endif

Generated by: LCOV version 1.11