src/str.cc

changeset 75
bf8c57437231
child 79
2425fa6a4f21
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/str.cc	Mon Jan 13 23:44:15 2014 +0200
@@ -0,0 +1,482 @@
+/*
+	Copyright (c) 2013-2014, Santeri Piippo
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+		* Redistributions of source code must retain the above copyright
+		  notice, this list of conditions and the following disclaimer.
+
+		* Redistributions in binary form must reproduce the above copyright
+		  notice, this list of conditions and the following disclaimer in the
+		  documentation and/or other materials provided with the distribution.
+
+		* Neither the name of the <organization> nor the
+		  names of its contributors may be used to endorse or promote products
+		  derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+	ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+	DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+	DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+	(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+	ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstring>
+#include "main.h"
+#include "str.h"
+
+// =============================================================================
+//
+int string::compare (const string& other) const
+{
+    return m_string.compare (other.std_string());
+}
+
+// =============================================================================
+//
+void string::trim (string::length_type n)
+{
+    if (n > 0)
+        m_string = substring (0, length() - n).std_string();
+    else
+        m_string = substring (n, -1).std_string();
+}
+
+// =============================================================================
+//
+string string::strip (list<char> unwanted)
+{
+    string copy (m_string);
+
+    for (char c : unwanted)
+        for (int i = 0; i < copy.length(); ++i)
+            if (copy[i] == c)
+                copy.erase (i);
+
+    /*
+    while(( pos = copy.first( c )) != -1 )
+    	copy.erase( pos );
+    */
+
+    return copy;
+}
+
+// =============================================================================
+//
+string string::to_uppercase() const
+{
+    string newstr = m_string;
+
+    for (char& c : newstr)
+        if (c >= 'a' && c <= 'z')
+            c -= 'a' - 'A';
+
+    return newstr;
+}
+
+// =============================================================================
+//
+string string::to_lowercase() const
+{
+    string newstr = m_string;
+
+    for (char & c : newstr)
+        if (c >= 'A' && c <= 'Z')
+            c += 'a' - 'A';
+
+    return newstr;
+}
+
+// =============================================================================
+//
+string_list string::split (char del) const
+{
+    string delimstr;
+    delimstr += del;
+    return split (delimstr);
+}
+
+// =============================================================================
+//
+string_list string::split (string del) const
+{
+    string_list res;
+    long a = 0;
+
+    // Find all separators and store the text left to them.
+    for (;;)
+    {
+        long b = first (del, a);
+
+        if (b == -1)
+            break;
+
+        string sub = substring (a, b);
+
+        if (sub.length() > 0)
+            res.push_back (substring (a, b));
+
+        a = b + strlen (del);
+    }
+
+    // Add the string at the right of the last separator
+    if (a < (int) length())
+        res.push_back (substring (a, length()));
+
+    return res;
+}
+
+// =============================================================================
+//
+void string::replace (const char* a, const char* b)
+{
+    long pos;
+
+    while ( (pos = first (a)) != -1)
+        m_string = m_string.replace (pos, strlen (a), b);
+}
+
+// =============================================================================
+//
+int string::count (const char needle) const
+{
+    int needles = 0;
+
+    for (const char & c : m_string)
+        if (c == needle)
+            needles++;
+
+    return needles;
+}
+
+// =============================================================================
+//
+string string::substring (long a, long b) const
+{
+    if (b == -1)
+        b = length();
+
+    if (b == a)
+        return "";
+
+    if (b < a)
+    {
+        // Swap the variables
+        int c = a;
+        a = b;
+        b = c;
+    }
+
+    char* newstr = new char[b - a + 1];
+    strncpy (newstr, m_string.c_str() + a, b - a);
+    newstr[b - a] = '\0';
+
+    string other (newstr);
+    delete[] newstr;
+    return other;
+}
+
+// =============================================================================
+//
+string::length_type string::posof (int n) const
+{
+    int count = 0;
+
+    for (int i = 0; i < length(); ++i)
+    {
+        if (m_string[i] != ' ')
+            continue;
+
+        if (++count < n)
+            continue;
+
+        return i;
+    }
+
+    return -1;
+}
+
+// =============================================================================
+//
+int string::first (const char* c, string::length_type a) const
+{
+    for (; a < length(); a++)
+        if (m_string[a] == c[0] && strncmp (m_string.c_str() + a, c, strlen (c)) == 0)
+            return a;
+
+    return -1;
+}
+
+// =============================================================================
+//
+int string::last (const char* c, string::length_type a) const
+{
+    if (a == -1 || a >= length())
+        a = length() - 1;
+
+    for (; a > 0; a--)
+        if (m_string[a] == c[0] && strncmp (m_string.c_str() + a, c, strlen (c)) == 0)
+            return a;
+
+    return -1;
+}
+
+// =============================================================================
+//
+void string::dump() const
+{
+    print ("`%1`:\n", chars());
+    int i = 0;
+
+    for (char u : m_string)
+        print ("\t%1. [%d2] `%3`\n", i++, u, string (u));
+}
+
+// =============================================================================
+//
+long string::to_long (bool* ok, int base) const
+{
+    errno = 0;
+    char* endptr;
+    long i = strtol (m_string.c_str(), &endptr, base);
+    *ok = (errno == 0 && *endptr == '\0');
+    return i;
+}
+
+// =============================================================================
+//
+float string::to_float (bool* ok) const
+{
+    errno = 0;
+    char* endptr;
+    float i = strtof (m_string.c_str(), &endptr);
+    *ok = (errno == 0 && *endptr == '\0');
+    return i;
+}
+
+// =============================================================================
+//
+double string::to_double (bool* ok) const
+{
+    errno = 0;
+    char* endptr;
+    double i = strtod (m_string.c_str(), &endptr);
+    *ok = (errno == 0 && *endptr == '\0');
+    return i;
+}
+
+// =============================================================================
+//
+bool operator== (const char* a, const string& b)
+{
+    return b == a;
+}
+
+// =============================================================================
+//
+string operator+ (const char* a, const string& b)
+{
+    return string (a) + b;
+}
+
+// =============================================================================
+//
+string string::operator+ (const string data) const
+{
+    string newString = *this;
+    newString += data;
+    return newString;
+}
+
+// =============================================================================
+//
+string string::operator+ (const char* data) const
+{
+    string newstr = *this;
+    newstr += data;
+    return newstr;
+}
+
+// =============================================================================
+//
+string& string::operator+= (const string data)
+{
+    append (data);
+    return *this;
+}
+
+// =============================================================================
+//
+string& string::operator+= (const char* data)
+{
+    append (data);
+    return *this;
+}
+
+// =============================================================================
+//
+bool string::is_numeric() const
+{
+    bool gotDot = false;
+
+    for (const char & c : m_string)
+    {
+        // Allow leading hyphen for negatives
+        if (&c == &m_string[0] && c == '-')
+            continue;
+
+        // Check for decimal point
+        if (!gotDot && c == '.')
+        {
+            gotDot = true;
+            continue;
+        }
+
+        if (c >= '0' && c <= '9')
+            continue; // Digit
+
+        // If the above cases didn't catch this character, it was
+        // illegal and this is therefore not a number.
+        return false;
+    }
+
+    return true;
+}
+
+// =============================================================================
+//
+bool string::ends_with (const string& other)
+{
+    if (length() < other.length())
+        return false;
+
+    const int ofs = length() - other.length();
+    return strncmp (chars() + ofs, other.chars(), other.length()) == 0;
+}
+
+// =============================================================================
+//
+bool string::starts_with (const string& other)
+{
+    if (length() < other.length())
+        return false;
+
+    return strncmp (chars(), other.chars(), other.length()) == 0;
+}
+
+// =============================================================================
+//
+void string::sprintf (const char* fmtstr, ...)
+{
+    char* buf;
+    int bufsize = 256;
+    va_list va;
+    va_start (va, fmtstr);
+
+    do
+        buf = new char[bufsize];
+
+    while (vsnprintf (buf, bufsize, fmtstr, va) >= bufsize);
+
+    va_end (va);
+    m_string = buf;
+    delete[] buf;
+}
+
+// =============================================================================
+//
+void string::prepend (string a)
+{
+    m_string = (a + m_string).std_string();
+}
+
+// =============================================================================
+//
+string string_list::join (const string& delim)
+{
+    string result;
+
+    for (const string & it : std_deque())
+    {
+        if (!result.is_empty())
+            result += delim;
+
+        result += it;
+    }
+
+    return result;
+}
+
+// =============================================================================
+//
+bool string::mask (const string& pattern) const
+{
+    // Elevate to uppercase for case-insensitive matching
+    string pattern_upper = pattern.to_uppercase();
+    string this_upper = to_uppercase();
+    const char* maskstring = pattern_upper.chars();
+    const char* mptr = &maskstring[0];
+
+    for (const char* sptr = this_upper.chars(); *sptr != '\0'; sptr++)
+    {
+        if (*mptr == '?')
+        {
+            if (* (sptr + 1) == '\0')
+            {
+                // ? demands that there's a character here and there wasn't.
+                // Therefore, mask matching fails
+                return false;
+            }
+        }
+
+        elif (*mptr == '*')
+        {
+            char end = * (++mptr);
+
+            // If '*' is the final character of the message, all of the remaining
+            // string matches against the '*'. We don't need to bother checking
+            // the string any further.
+            if (end == '\0')
+                return true;
+
+            // Skip to the end character
+            while (*sptr != end && *sptr != '\0')
+                sptr++;
+
+            // String ended while the mask still had stuff
+            if (*sptr == '\0')
+                return false;
+        }
+        elif (*sptr != *mptr)
+        return false;
+
+        mptr++;
+    }
+
+    return true;
+}
+
+// =============================================================================
+//
+string string::from_number (int a)
+{
+	char buf[32];
+	::sprintf (buf, "%d", a);
+	return string (buf);
+}
+
+// =============================================================================
+//
+string string::from_number (long a)
+{
+	char buf[32];
+	::sprintf (buf, "%ld", a);
+	return string (buf);
+}
\ No newline at end of file

mercurial