]> git.lizzy.rs Git - minetest.git/blobdiff - src/util/string.cpp
Add capability to read table flag fields from Lua API
[minetest.git] / src / util / string.cpp
index ee4df849e1200167c577ec492ae98ba457ccae67..a3888c9ce9d16767059437e27721ee12b759e02a 100644 (file)
@@ -1,6 +1,6 @@
 /*
-Minetest-c55
-Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
@@ -18,9 +18,40 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "string.h"
+#include "pointer.h"
+#include "numeric.h"
 
-#include "sha1.h"
-#include "base64.h"
+#include <sstream>
+#include <iomanip>
+
+#include "../sha1.h"
+#include "../base64.h"
+#include "../hex.h"
+#include "../porting.h"
+
+std::wstring narrow_to_wide(const std::string& mbs)
+{
+       size_t wcl = mbs.size();
+       Buffer<wchar_t> wcs(wcl+1);
+       size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
+       if(l == (size_t)(-1))
+               return L"<invalid multibyte string>";
+       wcs[l] = 0;
+       return *wcs;
+}
+
+std::string wide_to_narrow(const std::wstring& wcs)
+{
+       size_t mbl = wcs.size()*4;
+       SharedBuffer<char> mbs(mbl+1);
+       size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
+       if(l == (size_t)(-1)) {
+               return "Character conversion failed!";
+       }
+       else
+               mbs[l] = 0;
+       return *mbs;
+}
 
 // Get an sha-1 hash of the player's name combined with
 // the password entered. That's what the server uses as
@@ -41,3 +72,148 @@ std::string translatePassword(std::string playername, std::wstring password)
        return pwd;
 }
 
+std::string urlencode(std::string str)
+{
+       // Encodes non-unreserved URI characters by a percent sign
+       // followed by two hex digits. See RFC 3986, section 2.3.
+       static const char url_hex_chars[] = "0123456789ABCDEF";
+       std::ostringstream oss(std::ios::binary);
+       for (u32 i = 0; i < str.size(); i++) {
+               unsigned char c = str[i];
+               if (isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~')
+                       oss << c;
+               else
+                       oss << "%"
+                               << url_hex_chars[(c & 0xf0) >> 4]
+                               << url_hex_chars[c & 0x0f];
+       }
+       return oss.str();
+}
+
+std::string urldecode(std::string str)
+{
+       // Inverse of urlencode
+       std::ostringstream oss(std::ios::binary);
+       for (u32 i = 0; i < str.size(); i++) {
+               unsigned char highvalue, lowvalue;
+               if (str[i] == '%' &&
+                               hex_digit_decode(str[i+1], highvalue) &&
+                               hex_digit_decode(str[i+2], lowvalue)) {
+                       oss << (char) ((highvalue << 4) | lowvalue);
+                       i += 2;
+               }
+               else
+                       oss << str[i];
+       }
+       return oss.str();
+}
+
+u32 readFlagString(std::string str, FlagDesc *flagdesc, u32 *flagmask)
+{
+       u32 result = 0, mask = 0;
+       char *s = &str[0];
+       char *flagstr, *strpos = NULL;
+
+       while ((flagstr = strtok_r(s, ",", &strpos))) {
+               s = NULL;
+
+               while (*flagstr == ' ' || *flagstr == '\t')
+                       flagstr++;
+
+               bool flagset = true;
+               if (!strncasecmp(flagstr, "no", 2)) {
+                       flagset = false;
+                       flagstr += 2;
+               }
+
+               for (int i = 0; flagdesc[i].name; i++) {
+                       if (!strcasecmp(flagstr, flagdesc[i].name)) {
+                               mask |= flagdesc[i].flag;
+                               if (flagset)
+                                       result |= flagdesc[i].flag;
+                               break;
+                       }
+               }
+       }
+
+       if (flagmask)
+               *flagmask = mask;
+
+       return result;
+}
+
+std::string writeFlagString(u32 flags, FlagDesc *flagdesc, u32 flagmask)
+{
+       std::string result;
+
+       for (int i = 0; flagdesc[i].name; i++) {
+               if (flagmask & flagdesc[i].flag) {
+                       if (!(flags & flagdesc[i].flag))
+                               result += "no";
+
+                       result += flagdesc[i].name;
+                       result += ", ";
+               }
+       }
+
+       size_t len = result.length();
+       if (len >= 2)
+               result.erase(len - 2, 2);
+
+       return result;
+}
+
+size_t mystrlcpy(char *dst, const char *src, size_t size)
+{
+       size_t srclen  = strlen(src) + 1;
+       size_t copylen = MYMIN(srclen, size);
+
+       if (copylen > 0) {
+               memcpy(dst, src, copylen);
+               dst[copylen - 1] = '\0';
+       }
+
+       return srclen;
+}
+
+char *mystrtok_r(char *s, const char *sep, char **lasts)
+{
+       char *t;
+
+       if (!s)
+               s = *lasts;
+
+       while (*s && strchr(sep, *s))
+               s++;
+
+       if (!*s)
+               return NULL;
+
+       t = s;
+       while (*t) {
+               if (strchr(sep, *t)) {
+                       *t++ = '\0';
+                       break;
+               }
+               t++;
+       }
+       
+       *lasts = t;
+       return s;
+}
+
+u64 read_seed(const char *str)
+{
+       char *endptr;
+       u64 num;
+       
+       if (str[0] == '0' && str[1] == 'x')
+               num = strtoull(str, &endptr, 16);
+       else
+               num = strtoull(str, &endptr, 10);
+               
+       if (*endptr)
+               num = murmur_hash_64_ua(str, (int)strlen(str), 0x1337);
+               
+       return num;
+}