LCOV - code coverage report
Current view: top level - src/util - string.cpp (source / functions) Hit Total Coverage
Test: report Lines: 251 362 69.3 %
Date: 2015-07-11 18:23:49 Functions: 14 21 66.7 %

          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             : #include "string.h"
      21             : #include "pointer.h"
      22             : #include "numeric.h"
      23             : #include "log.h"
      24             : 
      25             : #include "hex.h"
      26             : #include "../porting.h"
      27             : 
      28             : #include <sstream>
      29             : #include <iomanip>
      30             : #include <map>
      31             : 
      32             : #ifndef _WIN32
      33             :         #include <iconv.h>
      34             : #else
      35             :         #define _WIN32_WINNT 0x0501
      36             :         #include <windows.h>
      37             : #endif
      38             : 
      39             : #if defined(_ICONV_H_) && (defined(__FreeBSD__) || defined(__NetBSD__) || \
      40             :         defined(__OpenBSD__) || defined(__DragonFly__))
      41             :         #define BSD_ICONV_USED
      42             : #endif
      43             : 
      44             : static bool parseHexColorString(const std::string &value, video::SColor &color);
      45             : static bool parseNamedColorString(const std::string &value, video::SColor &color);
      46             : 
      47             : #ifndef _WIN32
      48             : 
      49          65 : bool convert(const char *to, const char *from, char *outbuf,
      50             :                 size_t outbuf_size, char *inbuf, size_t inbuf_size)
      51             : {
      52          65 :         iconv_t cd = iconv_open(to, from);
      53             : 
      54             : #ifdef BSD_ICONV_USED
      55             :         const char *inbuf_ptr = inbuf;
      56             : #else
      57          65 :         char *inbuf_ptr = inbuf;
      58             : #endif
      59             : 
      60          65 :         char *outbuf_ptr = outbuf;
      61             : 
      62          65 :         size_t *inbuf_left_ptr = &inbuf_size;
      63          65 :         size_t *outbuf_left_ptr = &outbuf_size;
      64             : 
      65          65 :         size_t old_size = inbuf_size;
      66         195 :         while (inbuf_size > 0) {
      67          65 :                 iconv(cd, &inbuf_ptr, inbuf_left_ptr, &outbuf_ptr, outbuf_left_ptr);
      68          65 :                 if (inbuf_size == old_size) {
      69           0 :                         iconv_close(cd);
      70           0 :                         return false;
      71             :                 }
      72          65 :                 old_size = inbuf_size;
      73             :         }
      74             : 
      75          65 :         iconv_close(cd);
      76          65 :         return true;
      77             : }
      78             : 
      79          52 : std::wstring utf8_to_wide(const std::string &input)
      80             : {
      81          52 :         size_t inbuf_size = input.length() + 1;
      82             :         // maximum possible size, every character is sizeof(wchar_t) bytes
      83          52 :         size_t outbuf_size = (input.length() + 1) * sizeof(wchar_t);
      84             : 
      85          52 :         char *inbuf = new char[inbuf_size];
      86          52 :         memcpy(inbuf, input.c_str(), inbuf_size);
      87          52 :         char *outbuf = new char[outbuf_size];
      88          52 :         memset(outbuf, 0, outbuf_size);
      89             : 
      90          52 :         if (!convert("WCHAR_T", "UTF-8", outbuf, outbuf_size, inbuf, inbuf_size)) {
      91           0 :                 infostream << "Couldn't convert UTF-8 string 0x" << hex_encode(input)
      92           0 :                         << " into wstring" << std::endl;
      93           0 :                 delete[] inbuf;
      94           0 :                 delete[] outbuf;
      95           0 :                 return L"<invalid UTF-8 string>";
      96             :         }
      97         104 :         std::wstring out((wchar_t *)outbuf);
      98             : 
      99          52 :         delete[] inbuf;
     100          52 :         delete[] outbuf;
     101             : 
     102          52 :         return out;
     103             : }
     104             : 
     105             : #ifdef __ANDROID__
     106             : 
     107             : // TODO: this is an ugly fix for wide_to_utf8 somehow not working on android
     108             : std::string wide_to_utf8(const std::wstring &input)
     109             : {
     110             :         return wide_to_narrow(input);
     111             : }
     112             : 
     113             : #else // __ANDROID__
     114             : 
     115          13 : std::string wide_to_utf8(const std::wstring &input)
     116             : {
     117          13 :         size_t inbuf_size = (input.length() + 1) * sizeof(wchar_t);
     118             :         // maximum possible size: utf-8 encodes codepoints using 1 up to 6 bytes
     119          13 :         size_t outbuf_size = (input.length() + 1) * 6;
     120             : 
     121          13 :         char *inbuf = new char[inbuf_size];
     122          13 :         memcpy(inbuf, input.c_str(), inbuf_size);
     123          13 :         char *outbuf = new char[outbuf_size];
     124          13 :         memset(outbuf, 0, outbuf_size);
     125             : 
     126          13 :         if (!convert("UTF-8", "WCHAR_T", outbuf, outbuf_size, inbuf, inbuf_size)) {
     127           0 :                 infostream << "Couldn't convert wstring 0x" << hex_encode(inbuf, inbuf_size)
     128           0 :                         << " into UTF-8 string" << std::endl;
     129           0 :                 delete[] inbuf;
     130           0 :                 delete[] outbuf;
     131           0 :                 return "<invalid wstring>";
     132             :         }
     133          26 :         std::string out(outbuf);
     134             : 
     135          13 :         delete[] inbuf;
     136          13 :         delete[] outbuf;
     137             : 
     138          13 :         return out;
     139             : }
     140             : 
     141             : #endif // __ANDROID__
     142             : 
     143             : #else // _WIN32
     144             : 
     145             : std::wstring utf8_to_wide(const std::string &input)
     146             : {
     147             :         size_t outbuf_size = input.size() + 1;
     148             :         wchar_t *outbuf = new wchar_t[outbuf_size];
     149             :         memset(outbuf, 0, outbuf_size * sizeof(wchar_t));
     150             :         MultiByteToWideChar(CP_UTF8, 0, input.c_str(), input.size(),
     151             :                 outbuf, outbuf_size);
     152             :         std::wstring out(outbuf);
     153             :         delete[] outbuf;
     154             :         return out;
     155             : }
     156             : 
     157             : std::string wide_to_utf8(const std::wstring &input)
     158             : {
     159             :         size_t outbuf_size = (input.size() + 1) * 6;
     160             :         char *outbuf = new char[outbuf_size];
     161             :         memset(outbuf, 0, outbuf_size);
     162             :         WideCharToMultiByte(CP_UTF8, 0, input.c_str(), input.size(),
     163             :                 outbuf, outbuf_size, NULL, NULL);
     164             :         std::string out(outbuf);
     165             :         delete[] outbuf;
     166             :         return out;
     167             : }
     168             : 
     169             : #endif // _WIN32
     170             : 
     171             : // You must free the returned string!
     172             : // The returned string is allocated using new
     173          76 : wchar_t *narrow_to_wide_c(const char *str)
     174             : {
     175          76 :         wchar_t *nstr = NULL;
     176             : #if defined(_WIN32)
     177             :         int nResult = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) str, -1, 0, 0);
     178             :         if (nResult == 0) {
     179             :                 errorstream<<"gettext: MultiByteToWideChar returned null"<<std::endl;
     180             :         } else {
     181             :                 nstr = new wchar_t[nResult];
     182             :                 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) str, -1, (WCHAR *) nstr, nResult);
     183             :         }
     184             : #else
     185          76 :         size_t len = strlen(str);
     186          76 :         nstr = new wchar_t[len + 1];
     187             : 
     188         152 :         std::wstring intermediate = narrow_to_wide(str);
     189          76 :         memset(nstr, 0, (len + 1) * sizeof(wchar_t));
     190          76 :         memcpy(nstr, intermediate.c_str(), len * sizeof(wchar_t));
     191             : #endif
     192             : 
     193         152 :         return nstr;
     194             : }
     195             : 
     196             : 
     197             : #ifdef __ANDROID__
     198             : 
     199             : const wchar_t* wide_chars =
     200             :         L" !\"#$%&'()*+,-./0123456789:;<=>?@"
     201             :         L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"
     202             :         L"abcdefghijklmnopqrstuvwxyz{|}~";
     203             : 
     204             : int wctomb(char *s, wchar_t wc)
     205             : {
     206             :         for (unsigned int j = 0; j < (sizeof(wide_chars)/sizeof(wchar_t));j++) {
     207             :                 if (wc == wide_chars[j]) {
     208             :                         *s = (char) (j+32);
     209             :                         return 1;
     210             :                 }
     211             :                 else if (wc == L'\n') {
     212             :                         *s = '\n';
     213             :                         return 1;
     214             :                 }
     215             :         }
     216             :         return -1;
     217             : }
     218             : 
     219             : int mbtowc(wchar_t *pwc, const char *s, size_t n)
     220             : {
     221             :         std::wstring intermediate = narrow_to_wide(s);
     222             : 
     223             :         if (intermediate.length() > 0) {
     224             :                 *pwc = intermediate[0];
     225             :                 return 1;
     226             :         }
     227             :         else {
     228             :                 return -1;
     229             :         }
     230             : }
     231             : 
     232             : std::wstring narrow_to_wide(const std::string &mbs) {
     233             :         size_t wcl = mbs.size();
     234             : 
     235             :         std::wstring retval = L"";
     236             : 
     237             :         for (unsigned int i = 0; i < wcl; i++) {
     238             :                 if (((unsigned char) mbs[i] >31) &&
     239             :                  ((unsigned char) mbs[i] < 127)) {
     240             : 
     241             :                         retval += wide_chars[(unsigned char) mbs[i] -32];
     242             :                 }
     243             :                 //handle newline
     244             :                 else if (mbs[i] == '\n') {
     245             :                         retval += L'\n';
     246             :                 }
     247             :         }
     248             : 
     249             :         return retval;
     250             : }
     251             : 
     252             : #else // not Android
     253             : 
     254        4828 : std::wstring narrow_to_wide(const std::string &mbs)
     255             : {
     256        4828 :         size_t wcl = mbs.size();
     257        9656 :         Buffer<wchar_t> wcs(wcl + 1);
     258        4828 :         size_t len = mbstowcs(*wcs, mbs.c_str(), wcl);
     259        4828 :         if (len == (size_t)(-1))
     260           0 :                 return L"<invalid multibyte string>";
     261        4828 :         wcs[len] = 0;
     262        4828 :         return *wcs;
     263             : }
     264             : 
     265             : #endif
     266             : 
     267             : #ifdef __ANDROID__
     268             : 
     269             : std::string wide_to_narrow(const std::wstring &wcs) {
     270             :         size_t mbl = wcs.size()*4;
     271             : 
     272             :         std::string retval = "";
     273             :         for (unsigned int i = 0; i < wcs.size(); i++) {
     274             :                 wchar_t char1 = (wchar_t) wcs[i];
     275             : 
     276             :                 if (char1 == L'\n') {
     277             :                         retval += '\n';
     278             :                         continue;
     279             :                 }
     280             : 
     281             :                 for (unsigned int j = 0; j < wcslen(wide_chars);j++) {
     282             :                         wchar_t char2 = (wchar_t) wide_chars[j];
     283             : 
     284             :                         if (char1 == char2) {
     285             :                                 char toadd = (j+32);
     286             :                                 retval += toadd;
     287             :                                 break;
     288             :                         }
     289             :                 }
     290             :         }
     291             : 
     292             :         return retval;
     293             : }
     294             : 
     295             : #else // not Android
     296             : 
     297          42 : std::string wide_to_narrow(const std::wstring &wcs)
     298             : {
     299          42 :         size_t mbl = wcs.size() * 4;
     300          84 :         SharedBuffer<char> mbs(mbl+1);
     301          42 :         size_t len = wcstombs(*mbs, wcs.c_str(), mbl);
     302          42 :         if (len == (size_t)(-1))
     303           0 :                 return "Character conversion failed!";
     304             :         else
     305          42 :                 mbs[len] = 0;
     306          42 :         return *mbs;
     307             : }
     308             : 
     309             : #endif
     310             : 
     311           0 : std::string urlencode(std::string str)
     312             : {
     313             :         // Encodes non-unreserved URI characters by a percent sign
     314             :         // followed by two hex digits. See RFC 3986, section 2.3.
     315             :         static const char url_hex_chars[] = "0123456789ABCDEF";
     316           0 :         std::ostringstream oss(std::ios::binary);
     317           0 :         for (u32 i = 0; i < str.size(); i++) {
     318           0 :                 unsigned char c = str[i];
     319           0 :                 if (isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~')
     320           0 :                         oss << c;
     321             :                 else
     322           0 :                         oss << "%"
     323           0 :                                 << url_hex_chars[(c & 0xf0) >> 4]
     324           0 :                                 << url_hex_chars[c & 0x0f];
     325             :         }
     326           0 :         return oss.str();
     327             : }
     328             : 
     329           0 : std::string urldecode(std::string str)
     330             : {
     331             :         // Inverse of urlencode
     332           0 :         std::ostringstream oss(std::ios::binary);
     333           0 :         for (u32 i = 0; i < str.size(); i++) {
     334             :                 unsigned char highvalue, lowvalue;
     335           0 :                 if (str[i] == '%' &&
     336           0 :                                 hex_digit_decode(str[i+1], highvalue) &&
     337           0 :                                 hex_digit_decode(str[i+2], lowvalue)) {
     338           0 :                         oss << (char) ((highvalue << 4) | lowvalue);
     339           0 :                         i += 2;
     340             :                 }
     341             :                 else
     342           0 :                         oss << str[i];
     343             :         }
     344           0 :         return oss.str();
     345             : }
     346             : 
     347           0 : u32 readFlagString(std::string str, const FlagDesc *flagdesc, u32 *flagmask)
     348             : {
     349           0 :         u32 result = 0, mask = 0;
     350           0 :         char *s = &str[0];
     351           0 :         char *flagstr, *strpos = NULL;
     352             : 
     353           0 :         while ((flagstr = strtok_r(s, ",", &strpos))) {
     354           0 :                 s = NULL;
     355             : 
     356           0 :                 while (*flagstr == ' ' || *flagstr == '\t')
     357           0 :                         flagstr++;
     358             : 
     359           0 :                 bool flagset = true;
     360           0 :                 if (!strncasecmp(flagstr, "no", 2)) {
     361           0 :                         flagset = false;
     362           0 :                         flagstr += 2;
     363             :                 }
     364             : 
     365           0 :                 for (int i = 0; flagdesc[i].name; i++) {
     366           0 :                         if (!strcasecmp(flagstr, flagdesc[i].name)) {
     367           0 :                                 mask |= flagdesc[i].flag;
     368           0 :                                 if (flagset)
     369           0 :                                         result |= flagdesc[i].flag;
     370           0 :                                 break;
     371             :                         }
     372             :                 }
     373             :         }
     374             : 
     375           0 :         if (flagmask)
     376           0 :                 *flagmask = mask;
     377             : 
     378           0 :         return result;
     379             : }
     380             : 
     381           0 : std::string writeFlagString(u32 flags, const FlagDesc *flagdesc, u32 flagmask)
     382             : {
     383           0 :         std::string result;
     384             : 
     385           0 :         for (int i = 0; flagdesc[i].name; i++) {
     386           0 :                 if (flagmask & flagdesc[i].flag) {
     387           0 :                         if (!(flags & flagdesc[i].flag))
     388           0 :                                 result += "no";
     389             : 
     390           0 :                         result += flagdesc[i].name;
     391           0 :                         result += ", ";
     392             :                 }
     393             :         }
     394             : 
     395           0 :         size_t len = result.length();
     396           0 :         if (len >= 2)
     397           0 :                 result.erase(len - 2, 2);
     398             : 
     399           0 :         return result;
     400             : }
     401             : 
     402           1 : size_t mystrlcpy(char *dst, const char *src, size_t size)
     403             : {
     404           1 :         size_t srclen  = strlen(src) + 1;
     405           1 :         size_t copylen = MYMIN(srclen, size);
     406             : 
     407           1 :         if (copylen > 0) {
     408           1 :                 memcpy(dst, src, copylen);
     409           1 :                 dst[copylen - 1] = '\0';
     410             :         }
     411             : 
     412           1 :         return srclen;
     413             : }
     414             : 
     415           0 : char *mystrtok_r(char *s, const char *sep, char **lasts)
     416             : {
     417             :         char *t;
     418             : 
     419           0 :         if (!s)
     420           0 :                 s = *lasts;
     421             : 
     422           0 :         while (*s && strchr(sep, *s))
     423           0 :                 s++;
     424             : 
     425           0 :         if (!*s)
     426           0 :                 return NULL;
     427             : 
     428           0 :         t = s;
     429           0 :         while (*t) {
     430           0 :                 if (strchr(sep, *t)) {
     431           0 :                         *t++ = '\0';
     432           0 :                         break;
     433             :                 }
     434           0 :                 t++;
     435             :         }
     436             : 
     437           0 :         *lasts = t;
     438           0 :         return s;
     439             : }
     440             : 
     441           0 : u64 read_seed(const char *str)
     442             : {
     443             :         char *endptr;
     444             :         u64 num;
     445             : 
     446           0 :         if (str[0] == '0' && str[1] == 'x')
     447           0 :                 num = strtoull(str, &endptr, 16);
     448             :         else
     449           0 :                 num = strtoull(str, &endptr, 10);
     450             : 
     451           0 :         if (*endptr)
     452           0 :                 num = murmur_hash_64_ua(str, (int)strlen(str), 0x1337);
     453             : 
     454           0 :         return num;
     455             : }
     456             : 
     457         202 : bool parseColorString(const std::string &value, video::SColor &color, bool quiet)
     458             : {
     459             :         bool success;
     460             : 
     461         202 :         if (value[0] == '#')
     462         198 :                 success = parseHexColorString(value, color);
     463             :         else
     464           4 :                 success = parseNamedColorString(value, color);
     465             : 
     466         202 :         if (!success && !quiet)
     467           0 :                 errorstream << "Invalid color: \"" << value << "\"" << std::endl;
     468             : 
     469         202 :         return success;
     470             : }
     471             : 
     472         198 : static bool parseHexColorString(const std::string &value, video::SColor &color)
     473             : {
     474         198 :         unsigned char components[] = { 0x00, 0x00, 0x00, 0xff }; // R,G,B,A
     475             : 
     476         198 :         if (value[0] != '#')
     477           0 :                 return false;
     478             : 
     479         198 :         size_t len = value.size();
     480             :         bool short_form;
     481             : 
     482         198 :         if (len == 9 || len == 7) // #RRGGBBAA or #RRGGBB
     483         198 :                 short_form = false;
     484           0 :         else if (len == 5 || len == 4) // #RGBA or #RGB
     485           0 :                 short_form = true;
     486             :         else
     487           0 :                 return false;
     488             : 
     489         198 :         bool success = true;
     490             : 
     491         822 :         for (size_t pos = 1, cc = 0; pos < len; pos++, cc++) {
     492             :                 assert(cc < sizeof components / sizeof components[0]);
     493         624 :                 if (short_form) {
     494             :                         unsigned char d;
     495           0 :                         if (!hex_digit_decode(value[pos], d)) {
     496           0 :                                 success = false;
     497           0 :                                 break;
     498             :                         }
     499           0 :                         components[cc] = (d & 0xf) << 4 | (d & 0xf);
     500             :                 } else {
     501             :                         unsigned char d1, d2;
     502        1248 :                         if (!hex_digit_decode(value[pos], d1) ||
     503         624 :                                         !hex_digit_decode(value[pos+1], d2)) {
     504           0 :                                 success = false;
     505           0 :                                 break;
     506             :                         }
     507         624 :                         components[cc] = (d1 & 0xf) << 4 | (d2 & 0xf);
     508         624 :                         pos++;  // skip the second digit -- it's already used
     509             :                 }
     510             :         }
     511             : 
     512         198 :         if (success) {
     513         198 :                 color.setRed(components[0]);
     514         198 :                 color.setGreen(components[1]);
     515         198 :                 color.setBlue(components[2]);
     516         198 :                 color.setAlpha(components[3]);
     517             :         }
     518             : 
     519         198 :         return success;
     520             : }
     521             : 
     522           1 : struct ColorContainer {
     523             :         ColorContainer();
     524             :         std::map<const std::string, u32> colors;
     525             : };
     526             : 
     527           1 : ColorContainer::ColorContainer()
     528             : {
     529           1 :         colors["aliceblue"]              = 0xf0f8ff;
     530           1 :         colors["antiquewhite"]           = 0xfaebd7;
     531           1 :         colors["aqua"]                   = 0x00ffff;
     532           1 :         colors["aquamarine"]             = 0x7fffd4;
     533           1 :         colors["azure"]                  = 0xf0ffff;
     534           1 :         colors["beige"]                  = 0xf5f5dc;
     535           1 :         colors["bisque"]                 = 0xffe4c4;
     536           1 :         colors["black"]                  = 00000000;
     537           1 :         colors["blanchedalmond"]         = 0xffebcd;
     538           1 :         colors["blue"]                   = 0x0000ff;
     539           1 :         colors["blueviolet"]             = 0x8a2be2;
     540           1 :         colors["brown"]                  = 0xa52a2a;
     541           1 :         colors["burlywood"]              = 0xdeb887;
     542           1 :         colors["cadetblue"]              = 0x5f9ea0;
     543           1 :         colors["chartreuse"]             = 0x7fff00;
     544           1 :         colors["chocolate"]              = 0xd2691e;
     545           1 :         colors["coral"]                  = 0xff7f50;
     546           1 :         colors["cornflowerblue"]         = 0x6495ed;
     547           1 :         colors["cornsilk"]               = 0xfff8dc;
     548           1 :         colors["crimson"]                = 0xdc143c;
     549           1 :         colors["cyan"]                   = 0x00ffff;
     550           1 :         colors["darkblue"]               = 0x00008b;
     551           1 :         colors["darkcyan"]               = 0x008b8b;
     552           1 :         colors["darkgoldenrod"]          = 0xb8860b;
     553           1 :         colors["darkgray"]               = 0xa9a9a9;
     554           1 :         colors["darkgreen"]              = 0x006400;
     555           1 :         colors["darkkhaki"]              = 0xbdb76b;
     556           1 :         colors["darkmagenta"]            = 0x8b008b;
     557           1 :         colors["darkolivegreen"]         = 0x556b2f;
     558           1 :         colors["darkorange"]             = 0xff8c00;
     559           1 :         colors["darkorchid"]             = 0x9932cc;
     560           1 :         colors["darkred"]                = 0x8b0000;
     561           1 :         colors["darksalmon"]             = 0xe9967a;
     562           1 :         colors["darkseagreen"]           = 0x8fbc8f;
     563           1 :         colors["darkslateblue"]          = 0x483d8b;
     564           1 :         colors["darkslategray"]          = 0x2f4f4f;
     565           1 :         colors["darkturquoise"]          = 0x00ced1;
     566           1 :         colors["darkviolet"]             = 0x9400d3;
     567           1 :         colors["deeppink"]               = 0xff1493;
     568           1 :         colors["deepskyblue"]            = 0x00bfff;
     569           1 :         colors["dimgray"]                = 0x696969;
     570           1 :         colors["dodgerblue"]             = 0x1e90ff;
     571           1 :         colors["firebrick"]              = 0xb22222;
     572           1 :         colors["floralwhite"]            = 0xfffaf0;
     573           1 :         colors["forestgreen"]            = 0x228b22;
     574           1 :         colors["fuchsia"]                = 0xff00ff;
     575           1 :         colors["gainsboro"]              = 0xdcdcdc;
     576           1 :         colors["ghostwhite"]             = 0xf8f8ff;
     577           1 :         colors["gold"]                   = 0xffd700;
     578           1 :         colors["goldenrod"]              = 0xdaa520;
     579           1 :         colors["gray"]                   = 0x808080;
     580           1 :         colors["green"]                  = 0x008000;
     581           1 :         colors["greenyellow"]            = 0xadff2f;
     582           1 :         colors["honeydew"]               = 0xf0fff0;
     583           1 :         colors["hotpink"]                = 0xff69b4;
     584           1 :         colors["indianred "]             = 0xcd5c5c;
     585           1 :         colors["indigo "]                = 0x4b0082;
     586           1 :         colors["ivory"]                  = 0xfffff0;
     587           1 :         colors["khaki"]                  = 0xf0e68c;
     588           1 :         colors["lavender"]               = 0xe6e6fa;
     589           1 :         colors["lavenderblush"]          = 0xfff0f5;
     590           1 :         colors["lawngreen"]              = 0x7cfc00;
     591           1 :         colors["lemonchiffon"]           = 0xfffacd;
     592           1 :         colors["lightblue"]              = 0xadd8e6;
     593           1 :         colors["lightcoral"]             = 0xf08080;
     594           1 :         colors["lightcyan"]              = 0xe0ffff;
     595           1 :         colors["lightgoldenrodyellow"]   = 0xfafad2;
     596           1 :         colors["lightgray"]              = 0xd3d3d3;
     597           1 :         colors["lightgreen"]             = 0x90ee90;
     598           1 :         colors["lightpink"]              = 0xffb6c1;
     599           1 :         colors["lightsalmon"]            = 0xffa07a;
     600           1 :         colors["lightseagreen"]          = 0x20b2aa;
     601           1 :         colors["lightskyblue"]           = 0x87cefa;
     602           1 :         colors["lightslategray"]         = 0x778899;
     603           1 :         colors["lightsteelblue"]         = 0xb0c4de;
     604           1 :         colors["lightyellow"]            = 0xffffe0;
     605           1 :         colors["lime"]                   = 0x00ff00;
     606           1 :         colors["limegreen"]              = 0x32cd32;
     607           1 :         colors["linen"]                  = 0xfaf0e6;
     608           1 :         colors["magenta"]                = 0xff00ff;
     609           1 :         colors["maroon"]                 = 0x800000;
     610           1 :         colors["mediumaquamarine"]       = 0x66cdaa;
     611           1 :         colors["mediumblue"]             = 0x0000cd;
     612           1 :         colors["mediumorchid"]           = 0xba55d3;
     613           1 :         colors["mediumpurple"]           = 0x9370db;
     614           1 :         colors["mediumseagreen"]         = 0x3cb371;
     615           1 :         colors["mediumslateblue"]        = 0x7b68ee;
     616           1 :         colors["mediumspringgreen"]      = 0x00fa9a;
     617           1 :         colors["mediumturquoise"]        = 0x48d1cc;
     618           1 :         colors["mediumvioletred"]        = 0xc71585;
     619           1 :         colors["midnightblue"]           = 0x191970;
     620           1 :         colors["mintcream"]              = 0xf5fffa;
     621           1 :         colors["mistyrose"]              = 0xffe4e1;
     622           1 :         colors["moccasin"]               = 0xffe4b5;
     623           1 :         colors["navajowhite"]            = 0xffdead;
     624           1 :         colors["navy"]                   = 0x000080;
     625           1 :         colors["oldlace"]                = 0xfdf5e6;
     626           1 :         colors["olive"]                  = 0x808000;
     627           1 :         colors["olivedrab"]              = 0x6b8e23;
     628           1 :         colors["orange"]                 = 0xffa500;
     629           1 :         colors["orangered"]              = 0xff4500;
     630           1 :         colors["orchid"]                 = 0xda70d6;
     631           1 :         colors["palegoldenrod"]          = 0xeee8aa;
     632           1 :         colors["palegreen"]              = 0x98fb98;
     633           1 :         colors["paleturquoise"]          = 0xafeeee;
     634           1 :         colors["palevioletred"]          = 0xdb7093;
     635           1 :         colors["papayawhip"]             = 0xffefd5;
     636           1 :         colors["peachpuff"]              = 0xffdab9;
     637           1 :         colors["peru"]                   = 0xcd853f;
     638           1 :         colors["pink"]                   = 0xffc0cb;
     639           1 :         colors["plum"]                   = 0xdda0dd;
     640           1 :         colors["powderblue"]             = 0xb0e0e6;
     641           1 :         colors["purple"]                 = 0x800080;
     642           1 :         colors["red"]                    = 0xff0000;
     643           1 :         colors["rosybrown"]              = 0xbc8f8f;
     644           1 :         colors["royalblue"]              = 0x4169e1;
     645           1 :         colors["saddlebrown"]            = 0x8b4513;
     646           1 :         colors["salmon"]                 = 0xfa8072;
     647           1 :         colors["sandybrown"]             = 0xf4a460;
     648           1 :         colors["seagreen"]               = 0x2e8b57;
     649           1 :         colors["seashell"]               = 0xfff5ee;
     650           1 :         colors["sienna"]                 = 0xa0522d;
     651           1 :         colors["silver"]                 = 0xc0c0c0;
     652           1 :         colors["skyblue"]                = 0x87ceeb;
     653           1 :         colors["slateblue"]              = 0x6a5acd;
     654           1 :         colors["slategray"]              = 0x708090;
     655           1 :         colors["snow"]                   = 0xfffafa;
     656           1 :         colors["springgreen"]            = 0x00ff7f;
     657           1 :         colors["steelblue"]              = 0x4682b4;
     658           1 :         colors["tan"]                    = 0xd2b48c;
     659           1 :         colors["teal"]                   = 0x008080;
     660           1 :         colors["thistle"]                = 0xd8bfd8;
     661           1 :         colors["tomato"]                 = 0xff6347;
     662           1 :         colors["turquoise"]              = 0x40e0d0;
     663           1 :         colors["violet"]                 = 0xee82ee;
     664           1 :         colors["wheat"]                  = 0xf5deb3;
     665           1 :         colors["white"]                  = 0xffffff;
     666           1 :         colors["whitesmoke"]             = 0xf5f5f5;
     667           1 :         colors["yellow"]                 = 0xffff00;
     668           1 :         colors["yellowgreen"]            = 0x9acd32;
     669             : 
     670           1 : }
     671             : 
     672           1 : static const ColorContainer named_colors;
     673             : 
     674           4 : static bool parseNamedColorString(const std::string &value, video::SColor &color)
     675             : {
     676           8 :         std::string color_name;
     677           8 :         std::string alpha_string;
     678             : 
     679             :         /* If the string has a # in it, assume this is the start of a specified
     680             :          * alpha value (if it isn't the string is invalid and the error will be
     681             :          * caught later on, either because the color name won't be found or the
     682             :          * alpha value will fail conversion)
     683             :          */
     684           4 :         size_t alpha_pos = value.find('#');
     685           4 :         if (alpha_pos != std::string::npos) {
     686           0 :                 color_name = value.substr(0, alpha_pos);
     687           0 :                 alpha_string = value.substr(alpha_pos + 1);
     688             :         } else {
     689           4 :                 color_name = value;
     690             :         }
     691             : 
     692           4 :         color_name = lowercase(value);
     693             : 
     694           4 :         std::map<const std::string, unsigned>::const_iterator it;
     695           4 :         it = named_colors.colors.find(color_name);
     696           4 :         if (it == named_colors.colors.end())
     697           0 :                 return false;
     698             : 
     699           4 :         u32 color_temp = it->second;
     700             : 
     701             :         /* An empty string for alpha is ok (none of the color table entries
     702             :          * have an alpha value either). Color strings without an alpha specified
     703             :          * are interpreted as fully opaque
     704             :          *
     705             :          * For named colors the supplied alpha string (representing a hex value)
     706             :          * must be exactly two digits. For example:  colorname#08
     707             :          */
     708           4 :         if (!alpha_string.empty()) {
     709           0 :                 if (alpha_string.length() != 2)
     710           0 :                         return false;
     711             : 
     712             :                 unsigned char d1, d2;
     713           0 :                 if (!hex_digit_decode(alpha_string.at(0), d1)
     714           0 :                                 || !hex_digit_decode(alpha_string.at(1), d2))
     715           0 :                         return false;
     716           0 :                 color_temp |= ((d1 & 0xf) << 4 | (d2 & 0xf)) << 24;
     717             :         } else {
     718           4 :                 color_temp |= 0xff << 24;  // Fully opaque
     719             :         }
     720             : 
     721           4 :         color = video::SColor(color_temp);
     722             : 
     723           4 :         return true;
     724             : }
     725             : 
     726           0 : void str_replace(std::string &str, char from, char to)
     727             : {
     728           0 :         std::replace(str.begin(), str.end(), from, to);
     729           3 : }

Generated by: LCOV version 1.11