summaryrefslogtreecommitdiff
path: root/cpp/src/IceUtil/StringUtil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/IceUtil/StringUtil.cpp')
-rw-r--r--cpp/src/IceUtil/StringUtil.cpp260
1 files changed, 260 insertions, 0 deletions
diff --git a/cpp/src/IceUtil/StringUtil.cpp b/cpp/src/IceUtil/StringUtil.cpp
new file mode 100644
index 00000000000..389da0c6f6c
--- /dev/null
+++ b/cpp/src/IceUtil/StringUtil.cpp
@@ -0,0 +1,260 @@
+// **********************************************************************
+//
+// Copyright (c) 2003
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <IceUtil/StringUtil.h>
+
+using namespace std;
+
+static string
+toOctalString(unsigned int n)
+{
+ string s;
+ s.resize(32);
+ string::size_type charPos = 32;
+ const int radix = 1 << 3;
+ int mask = radix - 1;
+ do
+ {
+ s[--charPos] = '0' + (n & mask);
+ n >>= 3;
+ }
+ while(n != 0);
+
+ return string(s, charPos, (32 - charPos));
+}
+
+static void
+escapeChar(string::value_type b, string& s, const string& special)
+{
+ switch(b)
+ {
+ case '\\':
+ {
+ s.append("\\\\");
+ break;
+ }
+ case '\'':
+ {
+ s.append("\\'");
+ break;
+ }
+ case '"':
+ {
+ s.append("\\\"");
+ break;
+ }
+ case '\b':
+ {
+ s.append("\\b");
+ break;
+ }
+ case '\f':
+ {
+ s.append("\\f");
+ break;
+ }
+ case '\n':
+ {
+ s.append("\\n");
+ break;
+ }
+ case '\r':
+ {
+ s.append("\\r");
+ break;
+ }
+ case '\t':
+ {
+ s.append("\\t");
+ break;
+ }
+ default:
+ {
+ if(static_cast<signed char>(b) <= 31 || b == 127)
+ {
+ s.push_back('\\');
+ string octal = toOctalString(b);
+
+ //
+ // Add leading zeroes so that we avoid problems during
+ // decoding. For example, consider the escaped string
+ // \0013 (i.e., a character with value 1 followed by the
+ // character '3'). If the leading zeroes were omitted, the
+ // result would be incorrectly interpreted as a single
+ // character with value 11.
+ //
+ for(string::size_type j = octal.size(); j < 3; j++)
+ {
+ s.push_back('0');
+ }
+ s.append(octal);
+ }
+ else if(special.find(b) != string::npos)
+ {
+ s.push_back('\\');
+ escapeChar(b, s, "");
+ }
+ else
+ {
+ s.push_back(b);
+ }
+ }
+ }
+}
+
+string
+IceUtil::escapeString(const string& s, const string& special)
+{
+ string result;
+ result.reserve(s.size());
+
+ for(string::size_type i = 0; i < s.size(); i++)
+ {
+ escapeChar(s[i], result, special);
+ }
+
+ return result;
+}
+
+bool
+IceUtil::unescapeString(const string& s, string::size_type start, string::size_type end, string& result)
+{
+ assert(end <= s.size());
+ assert(start <= end);
+
+ while(start < end)
+ {
+ char ch = s[start];
+ if(ch == '\\')
+ {
+ start++;
+ if(start == end)
+ {
+ return false; // Missing character.
+ }
+ ch = s[start];
+ switch(ch)
+ {
+ case '\\':
+ {
+ result.push_back('\\');
+ break;
+ }
+ case '\'':
+ case '"':
+ {
+ result.push_back(ch);
+ break;
+ }
+ case 'b':
+ {
+ result.push_back('\b');
+ break;
+ }
+ case 'f':
+ {
+ result.push_back('\f');
+ break;
+ }
+ case 'n':
+ {
+ result.push_back('\n');
+ break;
+ }
+ case 'r':
+ {
+ result.push_back('\r');
+ break;
+ }
+ case 't':
+ {
+ result.push_back('\t');
+ break;
+ }
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int count = 0;
+ int val = 0;
+ while(count < 3 && start < end && s[start] >= '0' && s[start] <= '9')
+ {
+ val <<= 3;
+ val |= s[start] - '0';
+ start++;
+ count++;
+ }
+ if(val > 255)
+ {
+ return false; // Octal value out of range.
+ }
+ result.push_back((string::value_type)val);
+ continue; // Don't increment start.
+ }
+ default:
+ {
+ if(static_cast<signed char>(ch) <= 31 || ch == 127)
+ {
+ return false; // Malformed encoding.
+ }
+ else
+ {
+ result.push_back(ch);
+ }
+ }
+ }
+ }
+ else
+ {
+ result.push_back(ch);
+ }
+ start++;
+ }
+
+ return true;
+}
+
+//
+// If a single or double quotation mark is found at the start position,
+// then the position of the matching closing quote is returned. If no
+// quotation mark is found at the start position, then 0 is returned.
+// If no matching closing quote is found, then -1 is returned.
+//
+string::size_type
+IceUtil::checkQuote(const string& s, string::size_type start)
+{
+ string::value_type quoteChar = s[start];
+ if(quoteChar == '"' || quoteChar == '\'')
+ {
+ start++;
+ string::size_type pos;
+ while(start < s.size() && (pos = s.find(quoteChar, start)) != string::npos)
+ {
+ if(s[pos - 1] != '\\')
+ {
+ return pos;
+ }
+ start = pos + 1;
+ }
+ return string::npos; // Unmatched quote.
+ }
+ return 0; // Not quoted.
+}