string.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *  Vidalia is distributed under the following license:
00003  *
00004  *  Copyright (C) 2006,  Matt Edman, Justin Hipple
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00019  *  Boston, MA  02110-1301, USA.
00020  ****************************************************************/
00021 
00022 /** 
00023  * \file string.cpp
00024  * \version $Id: string.cpp 1856 2007-08-23 01:58:58Z edmanm $
00025  * \brief Common string manipulation functions
00026  */
00027 
00028 #include "string.h"
00029 
00030 
00031 /** Create a QStringList from the array of C-style strings. */
00032 QStringList
00033 char_array_to_stringlist(char **arr, int len)
00034 {
00035   QStringList list;
00036   for (int i = 0; i < len; i++) {
00037     list << QString(arr[i]);
00038   }
00039   return list;
00040 }
00041 
00042 /** Conditionally assigns errmsg to str if str is not null and returns false.
00043  * This is a seemingly pointless function, but it saves some messiness in
00044  * methods whose QString *errmsg parameter is optional. */
00045 bool
00046 err(QString *str, QString errmsg)
00047 {
00048   if (str) {
00049     *str = errmsg;
00050   }
00051   return false;
00052 }
00053 
00054 /** Ensures all characters in str are in validChars. If a character appears
00055  * in str but not in validChars, it will be removed and the resulting
00056  * string returned. */
00057 QString
00058 ensure_valid_chars(QString str, QString validChars)
00059 {
00060   QString out = str;
00061   for (int i = 0; i < str.length(); i++) {
00062     QChar c = str.at(i);
00063     if (validChars.indexOf(c) < 0) {
00064       out.remove(c);
00065     }
00066   }
00067   return out;
00068 }
00069 
00070 /** Scrubs an email address by replacing "@" with " at " and "." with " dot ". */
00071 QString
00072 scrub_email_addr(QString email)
00073 {
00074   QString scrubbed = email;
00075   scrubbed = scrubbed.replace("@", " at ");
00076   scrubbed = scrubbed.replace(".", " dot ");
00077   return scrubbed;
00078 }
00079 
00080 /** Wraps <b>str</b> at <b>width</b> characters wide, using <b>sep</b> as the
00081  * word separator (" ", for example), and placing the line ending <b>le</b> at
00082  * the end of each line, except the last. */
00083 QString
00084 string_wrap(QString str, int width, QString sep, QString le)
00085 {
00086   QString wrapped;
00087   int pos, nextsep, wordlen, n;
00088   int seplen = sep.length();
00089  
00090   if (str.length() < width) {
00091     return str;
00092   }
00093 
00094   pos = 0; 
00095   n = width;
00096   while (pos < str.length()) {
00097     /* Get the length of a "word" */
00098     nextsep = str.indexOf(sep, pos);
00099     if (nextsep < 0) {
00100       nextsep = str.length();
00101     }
00102     wordlen = nextsep-pos;
00103 
00104     /* Check if there is room for the word on this line */
00105     if (wordlen > n) {
00106       /* Create a new line */
00107       wrapped.append(le);
00108       n = width;
00109     }
00110 
00111     /* Add the word to the current line */
00112     wrapped.append(str.mid(pos, wordlen+seplen));
00113     n = n - wordlen - seplen;
00114     pos += wordlen + seplen;
00115   }
00116   return wrapped.trimmed();
00117 }
00118 
00119 /** Encodes the bytes in <b>buf</b> as an uppercase hexadecimal string and
00120  * returns the result. This function is derived from base16_encode() in Tor's
00121  * util.c. See LICENSE for details on Tor's license. */
00122 QString
00123 base16_encode(const QByteArray buf)
00124 {
00125   QString hex;
00126   for (int i = 0; i < buf.size(); i++) {
00127     hex += "0123456789ABCDEF"[((quint8)buf[i]) >>  4];
00128     hex += "0123456789ABCDEF"[((quint8)buf[i]) & 0xf];
00129   }
00130   return hex;
00131 }
00132 
00133 /** Given a string <b>str</b>, this function returns a quoted string with all
00134  * '"' and '\' characters escaped with a single '\'. */
00135 QString
00136 string_escape(const QString str)
00137 {
00138   QString out;
00139   out.append('\"');
00140   for (int i = 0; i < str.length(); i++) {
00141     if (str[i] == '\"' || str[i] == '\\')
00142       out.append('\\');
00143     out.append(str[i]);
00144   }
00145   out.append('\"');
00146   return out;
00147 }
00148 
00149 /** Given a quoted string <b>str</b>, this function returns an unquoted,
00150  * unescaped string. <b>str</b> must start and end with an unescaped quote. */
00151 QString
00152 string_unescape(const QString str, bool *ok)
00153 {
00154   QString out;
00155  
00156   /* The string must start and end with an unescaped dquote */
00157   if (str.length() < 2 || !str.startsWith("\"") || !str.endsWith("\"") ||
00158       (str.endsWith("\\\"") && !str.endsWith("\\\\\""))) {
00159     if (ok)
00160       *ok = false;
00161     return QString();
00162   }
00163   for (int i = 1; i < str.length()-1; i++) {
00164     if (str[i] == '\\')
00165       i++;
00166     out.append(str[i]);
00167   }
00168   if (ok)
00169     *ok = true;
00170   return out;
00171 }
00172 
00173 /** Parses a series of space-separated key[=value|="value"] tokens from
00174  * <b>str</b> and returns the mappings in a QHash. If <b>str</b> was unable
00175  * to be parsed, <b>ok</b> is set to false. */
00176 QHash<QString,QString>
00177 string_parse_keyvals(const QString str, bool *ok)
00178 {
00179   int i, len;
00180   bool tmp_ok;
00181   QHash<QString,QString> keyvals;
00182   
00183   i = 0;
00184   len = str.length();
00185   while (i < len && str[i].isSpace())
00186     i++; /* Skip initial whitespace */
00187   while (i < len) {
00188     QString key, val;
00189     
00190     while (i < len && !str[i].isSpace() && str[i] != '=')
00191       key.append(str[i++]);
00192       
00193     if (i < len && str[i] == '=') {
00194       if (++i < len && str[i] == '\"') {
00195         /* The value is wrapped in quotes */
00196         val.append(str[i]);
00197         while (++i < len) {
00198           val.append(str[i]);
00199           if (str[i] == '\\') {
00200             if (++i == len)
00201               goto error;
00202             val.append(str[i]);
00203           } else if (str[i] == '\"') {
00204             i++;
00205             break;
00206           } 
00207         }
00208         val = string_unescape(val, &tmp_ok);
00209         if (!tmp_ok)
00210           goto error;
00211         keyvals.insert(key, val);
00212       } else {
00213         /* The value was not wrapped in quotes */
00214         while (i < len && !str[i].isSpace())
00215           val.append(str[i++]);
00216         keyvals.insert(key, val);
00217       }
00218     } else {
00219       /* The key had no value */
00220       keyvals.insert(key, QString(""));
00221     }
00222     while (i < len && str[i].isSpace())
00223       i++;
00224   }
00225   if (ok)
00226     *ok = true;
00227   return keyvals;
00228 
00229 error:
00230   if (ok)
00231     *ok = false;
00232   return QHash<QString,QString>();
00233 }
00234 

Generated on Wed Sep 5 15:49:28 2007 for Vidalia by  doxygen 1.5.3