stringutil.cpp

Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If you
00004 **  did not receive the LICENSE file with this file, you may obtain it from the
00005 **  Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.vidalia-project.net/. No part of Vidalia, including this file,
00007 **  may be copied, modified, propagated, or distributed except according to the
00008 **  terms described in the LICENSE file.
00009 */
00010 
00011 /*
00012 ** \file stringutil.cpp
00013 ** \version $Id: stringutil.cpp 2486 2008-04-05 14:43:08Z edmanm $
00014 ** \brief Common string manipulation functions
00015 */
00016 
00017 #include "stringutil.h"
00018 
00019 
00020 /** Create a QStringList from the array of C-style strings. */
00021 QStringList
00022 char_array_to_stringlist(char **arr, int len)
00023 {
00024   QStringList list;
00025   for (int i = 0; i < len; i++) {
00026     list << QString(arr[i]);
00027   }
00028   return list;
00029 }
00030 
00031 /** Conditionally assigns errmsg to str if str is not null and returns false.
00032  * This is a seemingly pointless function, but it saves some messiness in
00033  * methods whose QString *errmsg parameter is optional. */
00034 bool
00035 err(QString *str, const QString &errmsg)
00036 {
00037   if (str) {
00038     *str = errmsg;
00039   }
00040   return false;
00041 }
00042 
00043 /** Ensures all characters in str are in validChars. If a character appears
00044  * in str but not in validChars, it will be removed and the resulting
00045  * string returned. */
00046 QString
00047 ensure_valid_chars(const QString &str, const QString &validChars)
00048 {
00049   QString out = str;
00050   for (int i = 0; i < str.length(); i++) {
00051     QChar c = str.at(i);
00052     if (validChars.indexOf(c) < 0) {
00053       out.remove(c);
00054     }
00055   }
00056   return out;
00057 }
00058 
00059 /** Scrubs an email address by replacing "@" with " at " and "." with " dot ". */
00060 QString
00061 scrub_email_addr(const QString &email)
00062 {
00063   QString scrubbed = email;
00064   scrubbed = scrubbed.replace("@", " at ");
00065   scrubbed = scrubbed.replace(".", " dot ");
00066   return scrubbed;
00067 }
00068 
00069 /** Wraps <b>str</b> at <b>width</b> characters wide, using <b>sep</b> as the
00070  * word separator (" ", for example), and placing the line ending <b>le</b> at
00071  * the end of each line, except the last. */
00072 QString
00073 string_wrap(const QString &str, int width,
00074             const QString &sep, const QString &le)
00075 {
00076   QString wrapped;
00077   int pos, nextsep, wordlen, n;
00078   int seplen = sep.length();
00079  
00080   if (str.length() < width) {
00081     return str;
00082   }
00083 
00084   pos = 0; 
00085   n = width;
00086   while (pos < str.length()) {
00087     /* Get the length of a "word" */
00088     nextsep = str.indexOf(sep, pos);
00089     if (nextsep < 0) {
00090       nextsep = str.length();
00091     }
00092     wordlen = nextsep-pos;
00093 
00094     /* Check if there is room for the word on this line */
00095     if (wordlen > n) {
00096       /* Create a new line */
00097       wrapped.append(le);
00098       n = width;
00099     }
00100 
00101     /* Add the word to the current line */
00102     wrapped.append(str.mid(pos, wordlen+seplen));
00103     n = n - wordlen - seplen;
00104     pos += wordlen + seplen;
00105   }
00106   return wrapped.trimmed();
00107 }
00108 
00109 /** Encodes the bytes in <b>buf</b> as an uppercase hexadecimal string and
00110  * returns the result. This function is derived from base16_encode() in Tor's
00111  * util.c. See LICENSE for details on Tor's license. */
00112 QString
00113 base16_encode(const QByteArray &buf)
00114 {
00115   QString hex;
00116   for (int i = 0; i < buf.size(); i++) {
00117     hex += "0123456789ABCDEF"[((quint8)buf[i]) >>  4];
00118     hex += "0123456789ABCDEF"[((quint8)buf[i]) & 0xf];
00119   }
00120   return hex;
00121 }
00122 
00123 /** Given a string <b>str</b>, this function returns a quoted string with all
00124  * '"' and '\' characters escaped with a single '\'. */
00125 QString
00126 string_escape(const QString &str)
00127 {
00128   QString out;
00129   out.append("\"");
00130   for (int i = 0; i < str.length(); i++) {
00131     if (str[i] == '\"' || str[i] == '\\')
00132       out.append('\\');
00133     out.append(str[i]);
00134   }
00135   out.append("\"");
00136   return out;
00137 }
00138 
00139 /** Given a quoted string <b>str</b>, this function returns an unquoted,
00140  * unescaped string. <b>str</b> must start and end with an unescaped quote. */
00141 QString
00142 string_unescape(const QString &str, bool *ok)
00143 {
00144   QString out;
00145  
00146   /* The string must start and end with an unescaped dquote */
00147   if (str.length() < 2 || !str.startsWith("\"") || !str.endsWith("\"") ||
00148       (str.endsWith("\\\"") && !str.endsWith("\\\\\""))) {
00149     if (ok)
00150       *ok = false;
00151     return QString();
00152   }
00153   for (int i = 1; i < str.length()-1; i++) {
00154     if (str[i] == '\\')
00155       i++;
00156     out.append(str[i]);
00157   }
00158   if (ok)
00159     *ok = true;
00160   return out;
00161 }
00162 
00163 /** Parses a series of space-separated key[=value|="value"] tokens from
00164  * <b>str</b> and returns the mappings in a QHash. If <b>str</b> was unable
00165  * to be parsed, <b>ok</b> is set to false. */
00166 QHash<QString,QString>
00167 string_parse_keyvals(const QString &str, bool *ok)
00168 {
00169   int i, len;
00170   bool tmp_ok;
00171   QHash<QString,QString> keyvals;
00172   
00173   i = 0;
00174   len = str.length();
00175   while (i < len && str[i].isSpace())
00176     i++; /* Skip initial whitespace */
00177   while (i < len) {
00178     QString key, val;
00179     
00180     while (i < len && !str[i].isSpace() && str[i] != '=')
00181       key.append(str[i++]);
00182       
00183     if (i < len && str[i] == '=') {
00184       if (++i < len && str[i] == '\"') {
00185         /* The value is wrapped in quotes */
00186         val.append(str[i]);
00187         while (++i < len) {
00188           val.append(str[i]);
00189           if (str[i] == '\\') {
00190             if (++i == len)
00191               goto error;
00192             val.append(str[i]);
00193           } else if (str[i] == '\"') {
00194             i++;
00195             break;
00196           } 
00197         }
00198         val = string_unescape(val, &tmp_ok);
00199         if (!tmp_ok)
00200           goto error;
00201         keyvals.insert(key, val);
00202       } else {
00203         /* The value was not wrapped in quotes */
00204         while (i < len && !str[i].isSpace())
00205           val.append(str[i++]);
00206         keyvals.insert(key, val);
00207       }
00208     } else {
00209       /* The key had no value */
00210       keyvals.insert(key, QString(""));
00211     }
00212     while (i < len && str[i].isSpace())
00213       i++;
00214   }
00215   if (ok)
00216     *ok = true;
00217   return keyvals;
00218 
00219 error:
00220   if (ok)
00221     *ok = false;
00222   return QHash<QString,QString>();
00223 }
00224 
00225 /** Parses a series of command line arguments from <b>str</b>. If <b>str</b>
00226  * was unable to be parsed, <b>ok</b> is set to false. */
00227 QStringList
00228 string_parse_arguments(const QString &str, bool *ok)
00229 {
00230   QStringList args;
00231   int i, len;
00232   bool tmp_ok;
00233 
00234   i = 0;
00235   len = str.length();
00236   while (i < len && str[i].isSpace())
00237     i++; /* Skip initial whitespace */
00238   while (i < len) {
00239     QString arg;
00240     
00241     if (str[i] == '\"') {
00242       /* The value is wrapped in quotes */
00243       arg.append(str[i]);
00244       while (++i < len) {
00245         arg.append(str[i]);
00246         if (str[i] == '\\') {
00247           if (++i == len)
00248             goto error;
00249           arg.append(str[i]);
00250         } else if (str[i] == '\"') {
00251           i++;
00252           break;
00253         } 
00254       }
00255       arg = string_unescape(arg, &tmp_ok);
00256       if (!tmp_ok)
00257         goto error;
00258       args << arg;
00259     } else {
00260       /* The value was not wrapped in quotes */
00261       while (i < len && !str[i].isSpace())
00262         arg.append(str[i++]);
00263       args << arg;
00264     }
00265     while (i < len && str[i].isSpace())
00266       i++;
00267   }
00268 
00269   if (ok)
00270     *ok = true;
00271   return args;
00272 
00273 error:
00274   if (ok)
00275     *ok = false;
00276   return QStringList();
00277 }
00278 
00279 /** Formats the list of command line arguments in <b>args</b> as a string.
00280  * Arguments that contain ' ', '\', or '"' tokens will be escaped and
00281  * wrapped in double quotes. */
00282 QString
00283 string_format_arguments(const QStringList &args)
00284 {
00285   QStringList out;
00286   foreach (QString arg, args) {
00287     if (arg.contains("\"") || arg.contains("\\") || arg.contains(" "))
00288       out << string_escape(arg);
00289     else 
00290       out << arg;
00291   }
00292   return out.join(" ");
00293 }
00294 
00295 /** Returns true if <b>str</b> is a valid hexademical string. Returns false
00296  * otherwise. */
00297 bool
00298 string_is_hex(const QString &str)
00299 {
00300   for (int i = 0; i < str.length(); i++) {
00301     char c = str[i].toUpper().toAscii();
00302     if ((c < 'A' || c > 'F') && (c < '0' || c > '9'))
00303       return false;
00304   }
00305   return true;
00306 }
00307 

Generated on Tue Jul 7 16:58:11 2009 for Vidalia by  doxygen 1.4.7