]> Dogcows Code - chaz/yoink/blobdiff - src/stlplus/strings/string_utilities.cpp
cleanup stlplus files
[chaz/yoink] / src / stlplus / strings / string_utilities.cpp
index 9ff5345c7615958264c7160a92ac36e548e1cb9e..7e04824583bdbd4bb09743d03c73e357cf0886db 100644 (file)
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-//   Author:    Andy Rushton\r
-//   Copyright: (c) Southampton University 1999-2004\r
-//              (c) Andy Rushton           2004-2009\r
-//   License:   BSD License, see ../docs/license.html\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#include "string_utilities.hpp"\r
-#include "string_basic.hpp"\r
-#include <stdlib.h>\r
-#include <ctype.h>\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-\r
-namespace stlplus\r
-{\r
-\r
-  // added as a local copy to break the dependency on the portability library\r
-  static std::string local_dformat(const char* format, ...) throw(std::invalid_argument)\r
-  {\r
-    std::string formatted;\r
-    va_list args;\r
-    va_start(args, format);\r
-#ifdef MSWINDOWS\r
-    int length = 0;\r
-    char* buffer = 0;\r
-    for(int buffer_length = 256; ; buffer_length*=2)\r
-    {\r
-      buffer = (char*)malloc(buffer_length);\r
-      if (!buffer) throw std::invalid_argument("string_utilities");\r
-      length = _vsnprintf(buffer, buffer_length-1, format, args);\r
-      if (length >= 0)\r
-      {\r
-        buffer[length] = 0;\r
-        formatted += std::string(buffer);\r
-        free(buffer);\r
-        break;\r
-      }\r
-      free(buffer);\r
-    }\r
-#else\r
-    char* buffer = 0;\r
-    int length = vasprintf(&buffer, format, args);\r
-    if (!buffer) throw std::invalid_argument("string_utilities");\r
-    if (length >= 0)\r
-      formatted += std::string(buffer);\r
-    free(buffer);\r
-#endif\r
-    va_end(args);\r
-    if (length < 0) throw std::invalid_argument("string_utilities");\r
-    return formatted;\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-\r
-  std::string pad(const std::string& str, alignment_t alignment, unsigned width, char padch)\r
-    throw(std::invalid_argument)\r
-  {\r
-    std::string result = str;\r
-    switch(alignment)\r
-    {\r
-    case align_left:\r
-    {\r
-      unsigned padding = width>str.size() ? width - str.size() : 0;\r
-      unsigned i = 0;\r
-      while (i++ < padding)\r
-        result.insert(result.end(), padch);\r
-      break;\r
-    }\r
-    case align_right:\r
-    {\r
-      unsigned padding = width>str.size() ? width - str.size() : 0;\r
-      unsigned i = 0;\r
-      while (i++ < padding)\r
-        result.insert(result.begin(), padch);\r
-      break;\r
-    }\r
-    case align_centre:\r
-    {\r
-      unsigned padding = width>str.size() ? width - str.size() : 0;\r
-      unsigned i = 0;\r
-      while (i++ < padding/2)\r
-        result.insert(result.end(), padch);\r
-      i--;\r
-      while (i++ < padding)\r
-        result.insert(result.begin(), padch);\r
-      break;\r
-    }\r
-    default:\r
-      throw std::invalid_argument("invalid alignment value");\r
-    }\r
-    return result;\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-\r
-  std::string trim_left(const std::string& val)\r
-  {\r
-    std::string result = val;\r
-    while (!result.empty() && isspace(result[0]))\r
-      result.erase(result.begin());\r
-    return result;\r
-  }\r
-\r
-  std::string trim_right(const std::string& val)\r
-  {\r
-    std::string result = val;\r
-    while (!result.empty() && isspace(result[result.size()-1]))\r
-      result.erase(result.end()-1);\r
-    return result;\r
-  }\r
-\r
-  std::string trim(const std::string& val)\r
-  {\r
-    std::string result = val;\r
-    while (!result.empty() && isspace(result[0]))\r
-      result.erase(result.begin());\r
-    while (!result.empty() && isspace(result[result.size()-1]))\r
-      result.erase(result.end()-1);\r
-    return result;\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-\r
-  std::string lowercase(const std::string& val)\r
-  {\r
-    std::string text = val;\r
-    for (unsigned i = 0; i < text.size(); i++)\r
-      text[i] = tolower(text[i]);\r
-    return text;\r
-  }\r
-\r
-  std::string uppercase(const std::string& val)\r
-  {\r
-    std::string text = val;\r
-    for (unsigned i = 0; i < text.size(); i++)\r
-      text[i] = toupper(text[i]);\r
-    return text;\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-\r
-  std::string translate(const std::string& input, const std::string& from_set, const std::string& to_set)\r
-  {\r
-    std::string result;\r
-    for (unsigned i = 0; i < input.size(); i++)\r
-    {\r
-      char ch = input[i];\r
-      // check to see if the character is in the from set\r
-      std::string::size_type found = from_set.find(ch);\r
-      if (found == std::string::npos)\r
-      {\r
-        // not found so just copy across\r
-        result += ch;\r
-      }\r
-      else if (found < to_set.size())\r
-      {\r
-        // found and in range so translate\r
-        result += to_set[found];\r
-      }\r
-    }\r
-    return result;\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-  // WARNING: wheel re-invention follows\r
-  // Given that all shells perform wildcard matching, why don't the library writers put it in the C run-time????????\r
-  // The problem:\r
-  //   *  matches any number of characters - this is achieved by matching 1 and seeing if the remainder matches\r
-  //      if not, try 2 characters and see if the remainder matches etc.\r
-  //      this must be recursive, not iterative, so that multiple *s can appear in the same wildcard expression\r
-  //   ?  matches exactly one character so doesn't need the what-if approach\r
-  //   \  escapes special characters such as *, ? and [\r
-  //   [] matches exactly one character in the set - the difficulty is the set can contain ranges, e.g [a-zA-Z0-9]\r
-  //      a set cannot be empty and the ] character can be included by making it the first character\r
-\r
-  // function for testing whether a character matches a set\r
-  // I can't remember the exact rules and I have no definitive references but:\r
-  // a set contains characters, escaped characters (I think) and ranges in the form a-z\r
-  // The character '-' can only appear at the start of the set where it is not interpreted as a range\r
-  // This is a horrible mess - blame the Unix folks for making a hash of wildcards\r
-\r
-  static bool match_set (const std::string& set, char match)\r
-  {\r
-    // first expand any ranges and remove escape characters to make life more palatable\r
-    std::string simple_set;\r
-    for (std::string::const_iterator i = set.begin(); i != set.end(); ++i)\r
-    {\r
-      switch(*i)\r
-      {\r
-      case '-':\r
-      {\r
-        if (i == set.begin())\r
-        {\r
-          simple_set += *i;\r
-        }\r
-        else if (i+1 == set.end())\r
-        {\r
-          return false;\r
-        }\r
-        else\r
-        {\r
-          // found a set. The first character is already in the result, so first remove it (the set might be empty)\r
-          simple_set.erase(simple_set.end()-1);\r
-          char last = *++i;\r
-          for (char ch = *(i-2); ch <= last; ch++)\r
-          {\r
-            simple_set += ch;\r
-          }\r
-        }\r
-        break;\r
-      }\r
-      case '\\':\r
-        if (i+1 == set.end()) {return false;}\r
-        simple_set += *++i;\r
-        break;\r
-      default:\r
-        simple_set += *i;\r
-        break;\r
-      }\r
-    }\r
-    std::string::size_type result = simple_set.find(match);\r
-    return result != std::string::npos;\r
-  }\r
-\r
-  // the recursive bit - basically whenever a * is found you recursively call this for each candidate substring match\r
-  // until either it succeeds or you run out of string to match\r
-  // for each * in the wildcard another level of recursion is created\r
-\r
-  static bool match_remainder (const std::string& wild, std::string::const_iterator wildi,\r
-                               const std::string& match, std::string::const_iterator matchi)\r
-  {\r
-    //cerr << "match_remainder called at " << *matchi << " with wildcard " << *wildi << endl;\r
-    while (wildi != wild.end() && matchi != match.end())\r
-    {\r
-      //cerr << "trying to match " << *matchi << " with wildcard " << *wildi << endl;\r
-      switch(*wildi)\r
-      {\r
-      case '*':\r
-      {\r
-        ++wildi;\r
-        ++matchi;\r
-        for (std::string::const_iterator i = matchi; i != match.end(); ++i)\r
-        {\r
-          // deal with * at the end of the wildcard - there is no remainder then\r
-          if (wildi == wild.end())\r
-          {\r
-            if (i == match.end()-1)\r
-              return true;\r
-          }\r
-          else if (match_remainder(wild, wildi, match, i))\r
-          {\r
-            return true;\r
-          }\r
-        }\r
-        return false;\r
-      }\r
-      case '[':\r
-      {\r
-        // scan for the end of the set using a similar method for avoiding escaped characters\r
-        bool found = false;\r
-        std::string::const_iterator end = wildi + 1;\r
-        for (; !found && end != wild.end(); ++end)\r
-        {\r
-          switch(*end)\r
-          {\r
-          case ']':\r
-          {\r
-            // found the set, now match with its contents excluding the brackets\r
-            if (!match_set(wild.substr(wildi - wild.begin() + 1, end - wildi - 1), *matchi))\r
-              return false;\r
-            found = true;\r
-            break;\r
-          }\r
-          case '\\':\r
-            if (end == wild.end()-1)\r
-              return false;\r
-            ++end;\r
-            break;\r
-          default:\r
-            break;\r
-          }\r
-        }\r
-        if (!found)\r
-          return false;\r
-        ++matchi;\r
-        wildi = end;\r
-        break;\r
-      }\r
-      case '?':\r
-        ++wildi;\r
-        ++matchi;\r
-        break;\r
-      case '\\':\r
-        if (wildi == wild.end()-1)\r
-          return false;\r
-        ++wildi;\r
-        if (*wildi != *matchi)\r
-          return false;\r
-        ++wildi;\r
-        ++matchi;\r
-        break;\r
-      default:\r
-        if (*wildi != *matchi)\r
-          return false;\r
-        ++wildi;\r
-        ++matchi;\r
-        break;\r
-      }\r
-    }\r
-    bool result = wildi == wild.end() && matchi == match.end();\r
-    return result;\r
-  }\r
-\r
-  // like all recursions the exported function has a simpler interface than the\r
-  // recursive function and is just a 'seed' to the recursion itself\r
-\r
-  bool match_wildcard(const std::string& wild, const std::string& match)\r
-  {\r
-    return match_remainder(wild, wild.begin(), match, match.begin());\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-\r
-  std::vector<std::string> split(const std::string& str, const std::string& splitter)\r
-  {\r
-    std::vector<std::string> result;\r
-    if (!str.empty())\r
-    {\r
-      for(std::string::size_type offset = 0;;)\r
-      {\r
-        std::string::size_type found = str.find(splitter, offset);\r
-        if (found != std::string::npos)\r
-        {\r
-          result.push_back(str.substr(offset, found-offset));\r
-          offset = found + splitter.size();\r
-        }\r
-        else\r
-        {\r
-          result.push_back(str.substr(offset, str.size()-offset));\r
-          break;\r
-        }\r
-      }\r
-    }\r
-    return result;\r
-  }\r
-\r
-  std::string join (const std::vector<std::string>& str,\r
-                    const std::string& joiner,\r
-                    const std::string& prefix,\r
-                    const std::string& suffix)\r
-  {\r
-    std::string result = prefix;\r
-    for (unsigned i = 0; i < str.size(); i++)\r
-    {\r
-      if (i) result += joiner;\r
-      result += str[i];\r
-    }\r
-    result += suffix;\r
-    return result;\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-\r
-  std::string display_bytes(long bytes)\r
-  {\r
-    std::string result;\r
-    if (bytes < 0)\r
-    {\r
-      result += '-';\r
-      bytes = -bytes;\r
-    }\r
-    static const long kB = 1024l;\r
-    static const long MB = kB * kB;\r
-    static const long GB = MB * kB;\r
-    if (bytes < kB)\r
-      result += local_dformat("%i", bytes);\r
-    else if (bytes < (10l * kB))\r
-      result += local_dformat("%.2fk", ((float)bytes / (float)kB));\r
-    else if (bytes < (100l * kB))\r
-      result += local_dformat("%.1fk", ((float)bytes / (float)kB));\r
-    else if (bytes < MB)\r
-      result += local_dformat("%.0fk", ((float)bytes / (float)kB));\r
-    else if (bytes < (10l * MB))\r
-      result += local_dformat("%.2fM", ((float)bytes / (float)MB));\r
-    else if (bytes < (100l * MB))\r
-      result += local_dformat("%.1fM", ((float)bytes / (float)MB));\r
-    else if (bytes < GB)\r
-      result += local_dformat("%.0fM", ((float)bytes / (float)MB));\r
-    else\r
-      result += local_dformat("%.2fG", ((float)bytes / (float)GB));\r
-    return result;\r
-  }\r
-\r
-  std::string display_time(time_t seconds)\r
-  {\r
-    unsigned minutes = (unsigned)seconds / 60;\r
-    seconds %= 60;\r
-    unsigned hours = minutes / 60;\r
-    minutes %= 60;\r
-    unsigned days = hours / 24;\r
-    hours %= 24;\r
-    unsigned weeks = days / 7;\r
-    days %= 7;\r
-    std::string result;\r
-    if (weeks > 0)\r
-    {\r
-      result += unsigned_to_string(weeks, 10, radix_none, 1);\r
-      result += "w ";\r
-    }\r
-    if (!result.empty() || days > 0)\r
-    {\r
-      result += unsigned_to_string(days, 10, radix_none, 1);\r
-      result += "d ";\r
-    }\r
-    if (!result.empty() || hours > 0)\r
-    {\r
-      result += unsigned_to_string(hours, 10, radix_none, 1);\r
-      result += ":";\r
-    }\r
-    if (!result.empty() || minutes > 0)\r
-    {\r
-      if (!result.empty())\r
-        result += unsigned_to_string(minutes, 10, radix_none, 2);\r
-      else\r
-        result += unsigned_to_string(minutes, 10, radix_none, 1);\r
-      result += ":";\r
-    }\r
-    if (!result.empty())\r
-      result += unsigned_to_string((unsigned)seconds, 10, radix_none, 2);\r
-    else\r
-    {\r
-      result += unsigned_to_string((unsigned)seconds, 10, radix_none, 1);\r
-      result += "s";\r
-    }\r
-    return result;\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-\r
-} // end namespace stlplus\r
+////////////////////////////////////////////////////////////////////////////////
+
+//   Author:    Andy Rushton
+//   Copyright: (c) Southampton University 1999-2004
+//              (c) Andy Rushton           2004-2009
+//   License:   BSD License, see ../docs/license.html
+
+////////////////////////////////////////////////////////////////////////////////
+#include "string_utilities.hpp"
+#include "string_basic.hpp"
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+namespace stlplus
+{
+
+  // added as a local copy to break the dependency on the portability library
+  static std::string local_dformat(const char* format, ...) throw(std::invalid_argument)
+  {
+    std::string formatted;
+    va_list args;
+    va_start(args, format);
+#ifdef MSWINDOWS
+    int length = 0;
+    char* buffer = 0;
+    for(int buffer_length = 256; ; buffer_length*=2)
+    {
+      buffer = (char*)malloc(buffer_length);
+      if (!buffer) throw std::invalid_argument("string_utilities");
+      length = _vsnprintf(buffer, buffer_length-1, format, args);
+      if (length >= 0)
+      {
+        buffer[length] = 0;
+        formatted += std::string(buffer);
+        free(buffer);
+        break;
+      }
+      free(buffer);
+    }
+#else
+    char* buffer = 0;
+    int length = vasprintf(&buffer, format, args);
+    if (!buffer) throw std::invalid_argument("string_utilities");
+    if (length >= 0)
+      formatted += std::string(buffer);
+    free(buffer);
+#endif
+    va_end(args);
+    if (length < 0) throw std::invalid_argument("string_utilities");
+    return formatted;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+
+  std::string pad(const std::string& str, alignment_t alignment, unsigned width, char padch)
+    throw(std::invalid_argument)
+  {
+    std::string result = str;
+    switch(alignment)
+    {
+    case align_left:
+    {
+      unsigned padding = width>str.size() ? width - str.size() : 0;
+      unsigned i = 0;
+      while (i++ < padding)
+        result.insert(result.end(), padch);
+      break;
+    }
+    case align_right:
+    {
+      unsigned padding = width>str.size() ? width - str.size() : 0;
+      unsigned i = 0;
+      while (i++ < padding)
+        result.insert(result.begin(), padch);
+      break;
+    }
+    case align_centre:
+    {
+      unsigned padding = width>str.size() ? width - str.size() : 0;
+      unsigned i = 0;
+      while (i++ < padding/2)
+        result.insert(result.end(), padch);
+      i--;
+      while (i++ < padding)
+        result.insert(result.begin(), padch);
+      break;
+    }
+    default:
+      throw std::invalid_argument("invalid alignment value");
+    }
+    return result;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+
+  std::string trim_left(const std::string& val)
+  {
+    std::string result = val;
+    while (!result.empty() && isspace(result[0]))
+      result.erase(result.begin());
+    return result;
+  }
+
+  std::string trim_right(const std::string& val)
+  {
+    std::string result = val;
+    while (!result.empty() && isspace(result[result.size()-1]))
+      result.erase(result.end()-1);
+    return result;
+  }
+
+  std::string trim(const std::string& val)
+  {
+    std::string result = val;
+    while (!result.empty() && isspace(result[0]))
+      result.erase(result.begin());
+    while (!result.empty() && isspace(result[result.size()-1]))
+      result.erase(result.end()-1);
+    return result;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+
+  std::string lowercase(const std::string& val)
+  {
+    std::string text = val;
+    for (unsigned i = 0; i < text.size(); i++)
+      text[i] = tolower(text[i]);
+    return text;
+  }
+
+  std::string uppercase(const std::string& val)
+  {
+    std::string text = val;
+    for (unsigned i = 0; i < text.size(); i++)
+      text[i] = toupper(text[i]);
+    return text;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+
+  std::string translate(const std::string& input, const std::string& from_set, const std::string& to_set)
+  {
+    std::string result;
+    for (unsigned i = 0; i < input.size(); i++)
+    {
+      char ch = input[i];
+      // check to see if the character is in the from set
+      std::string::size_type found = from_set.find(ch);
+      if (found == std::string::npos)
+      {
+        // not found so just copy across
+        result += ch;
+      }
+      else if (found < to_set.size())
+      {
+        // found and in range so translate
+        result += to_set[found];
+      }
+    }
+    return result;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+  // WARNING: wheel re-invention follows
+  // Given that all shells perform wildcard matching, why don't the library writers put it in the C run-time????????
+  // The problem:
+  //   *  matches any number of characters - this is achieved by matching 1 and seeing if the remainder matches
+  //      if not, try 2 characters and see if the remainder matches etc.
+  //      this must be recursive, not iterative, so that multiple *s can appear in the same wildcard expression
+  //   ?  matches exactly one character so doesn't need the what-if approach
+  //   \  escapes special characters such as *, ? and [
+  //   [] matches exactly one character in the set - the difficulty is the set can contain ranges, e.g [a-zA-Z0-9]
+  //      a set cannot be empty and the ] character can be included by making it the first character
+
+  // function for testing whether a character matches a set
+  // I can't remember the exact rules and I have no definitive references but:
+  // a set contains characters, escaped characters (I think) and ranges in the form a-z
+  // The character '-' can only appear at the start of the set where it is not interpreted as a range
+  // This is a horrible mess - blame the Unix folks for making a hash of wildcards
+
+  static bool match_set (const std::string& set, char match)
+  {
+    // first expand any ranges and remove escape characters to make life more palatable
+    std::string simple_set;
+    for (std::string::const_iterator i = set.begin(); i != set.end(); ++i)
+    {
+      switch(*i)
+      {
+      case '-':
+      {
+        if (i == set.begin())
+        {
+          simple_set += *i;
+        }
+        else if (i+1 == set.end())
+        {
+          return false;
+        }
+        else
+        {
+          // found a set. The first character is already in the result, so first remove it (the set might be empty)
+          simple_set.erase(simple_set.end()-1);
+          char last = *++i;
+          for (char ch = *(i-2); ch <= last; ch++)
+          {
+            simple_set += ch;
+          }
+        }
+        break;
+      }
+      case '\\':
+        if (i+1 == set.end()) {return false;}
+        simple_set += *++i;
+        break;
+      default:
+        simple_set += *i;
+        break;
+      }
+    }
+    std::string::size_type result = simple_set.find(match);
+    return result != std::string::npos;
+  }
+
+  // the recursive bit - basically whenever a * is found you recursively call this for each candidate substring match
+  // until either it succeeds or you run out of string to match
+  // for each * in the wildcard another level of recursion is created
+
+  static bool match_remainder (const std::string& wild, std::string::const_iterator wildi,
+                               const std::string& match, std::string::const_iterator matchi)
+  {
+    //cerr << "match_remainder called at " << *matchi << " with wildcard " << *wildi << endl;
+    while (wildi != wild.end() && matchi != match.end())
+    {
+      //cerr << "trying to match " << *matchi << " with wildcard " << *wildi << endl;
+      switch(*wildi)
+      {
+      case '*':
+      {
+        ++wildi;
+        ++matchi;
+        for (std::string::const_iterator i = matchi; i != match.end(); ++i)
+        {
+          // deal with * at the end of the wildcard - there is no remainder then
+          if (wildi == wild.end())
+          {
+            if (i == match.end()-1)
+              return true;
+          }
+          else if (match_remainder(wild, wildi, match, i))
+          {
+            return true;
+          }
+        }
+        return false;
+      }
+      case '[':
+      {
+        // scan for the end of the set using a similar method for avoiding escaped characters
+        bool found = false;
+        std::string::const_iterator end = wildi + 1;
+        for (; !found && end != wild.end(); ++end)
+        {
+          switch(*end)
+          {
+          case ']':
+          {
+            // found the set, now match with its contents excluding the brackets
+            if (!match_set(wild.substr(wildi - wild.begin() + 1, end - wildi - 1), *matchi))
+              return false;
+            found = true;
+            break;
+          }
+          case '\\':
+            if (end == wild.end()-1)
+              return false;
+            ++end;
+            break;
+          default:
+            break;
+          }
+        }
+        if (!found)
+          return false;
+        ++matchi;
+        wildi = end;
+        break;
+      }
+      case '?':
+        ++wildi;
+        ++matchi;
+        break;
+      case '\\':
+        if (wildi == wild.end()-1)
+          return false;
+        ++wildi;
+        if (*wildi != *matchi)
+          return false;
+        ++wildi;
+        ++matchi;
+        break;
+      default:
+        if (*wildi != *matchi)
+          return false;
+        ++wildi;
+        ++matchi;
+        break;
+      }
+    }
+    bool result = wildi == wild.end() && matchi == match.end();
+    return result;
+  }
+
+  // like all recursions the exported function has a simpler interface than the
+  // recursive function and is just a 'seed' to the recursion itself
+
+  bool match_wildcard(const std::string& wild, const std::string& match)
+  {
+    return match_remainder(wild, wild.begin(), match, match.begin());
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+
+  std::vector<std::string> split(const std::string& str, const std::string& splitter)
+  {
+    std::vector<std::string> result;
+    if (!str.empty())
+    {
+      for(std::string::size_type offset = 0;;)
+      {
+        std::string::size_type found = str.find(splitter, offset);
+        if (found != std::string::npos)
+        {
+          result.push_back(str.substr(offset, found-offset));
+          offset = found + splitter.size();
+        }
+        else
+        {
+          result.push_back(str.substr(offset, str.size()-offset));
+          break;
+        }
+      }
+    }
+    return result;
+  }
+
+  std::string join (const std::vector<std::string>& str,
+                    const std::string& joiner,
+                    const std::string& prefix,
+                    const std::string& suffix)
+  {
+    std::string result = prefix;
+    for (unsigned i = 0; i < str.size(); i++)
+    {
+      if (i) result += joiner;
+      result += str[i];
+    }
+    result += suffix;
+    return result;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+
+  std::string display_bytes(long bytes)
+  {
+    std::string result;
+    if (bytes < 0)
+    {
+      result += '-';
+      bytes = -bytes;
+    }
+    static const long kB = 1024l;
+    static const long MB = kB * kB;
+    static const long GB = MB * kB;
+    if (bytes < kB)
+      result += local_dformat("%i", bytes);
+    else if (bytes < (10l * kB))
+      result += local_dformat("%.2fk", ((float)bytes / (float)kB));
+    else if (bytes < (100l * kB))
+      result += local_dformat("%.1fk", ((float)bytes / (float)kB));
+    else if (bytes < MB)
+      result += local_dformat("%.0fk", ((float)bytes / (float)kB));
+    else if (bytes < (10l * MB))
+      result += local_dformat("%.2fM", ((float)bytes / (float)MB));
+    else if (bytes < (100l * MB))
+      result += local_dformat("%.1fM", ((float)bytes / (float)MB));
+    else if (bytes < GB)
+      result += local_dformat("%.0fM", ((float)bytes / (float)MB));
+    else
+      result += local_dformat("%.2fG", ((float)bytes / (float)GB));
+    return result;
+  }
+
+  std::string display_time(time_t seconds)
+  {
+    unsigned minutes = (unsigned)seconds / 60;
+    seconds %= 60;
+    unsigned hours = minutes / 60;
+    minutes %= 60;
+    unsigned days = hours / 24;
+    hours %= 24;
+    unsigned weeks = days / 7;
+    days %= 7;
+    std::string result;
+    if (weeks > 0)
+    {
+      result += unsigned_to_string(weeks, 10, radix_none, 1);
+      result += "w ";
+    }
+    if (!result.empty() || days > 0)
+    {
+      result += unsigned_to_string(days, 10, radix_none, 1);
+      result += "d ";
+    }
+    if (!result.empty() || hours > 0)
+    {
+      result += unsigned_to_string(hours, 10, radix_none, 1);
+      result += ":";
+    }
+    if (!result.empty() || minutes > 0)
+    {
+      if (!result.empty())
+        result += unsigned_to_string(minutes, 10, radix_none, 2);
+      else
+        result += unsigned_to_string(minutes, 10, radix_none, 1);
+      result += ":";
+    }
+    if (!result.empty())
+      result += unsigned_to_string((unsigned)seconds, 10, radix_none, 2);
+    else
+    {
+      result += unsigned_to_string((unsigned)seconds, 10, radix_none, 1);
+      result += "s";
+    }
+    return result;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+
+} // end namespace stlplus
This page took 0.048522 seconds and 4 git commands to generate.