00001
00002
00003
00004
00005 #include "wvtclstring.h"
00006 #include "wvbackslash.h"
00007 #include "wvbuf.h"
00008 #include <wvstream.h>
00009
00010 WvString wvtcl_escape(WvStringParm s, const char *nasties)
00011 {
00012 WvString allnasties(WVTCL_ALWAYS_NASTY);
00013 allnasties.append(nasties);
00014
00015 bool backslashify = false, inescape = false;
00016 int unprintables = 0, bracecount = 0;
00017 const char *cptr;
00018
00019
00020 if (!(const char *)s)
00021 return s;
00022
00023
00024 if (!s)
00025 return "{}";
00026
00027
00028
00029
00030 for (cptr = s; *cptr; cptr++)
00031 {
00032 if (!inescape && *cptr == '{')
00033 bracecount++;
00034 else if (!inescape && *cptr == '}')
00035 bracecount--;
00036 if (bracecount < 0)
00037 backslashify = true;
00038
00039 if (strchr(allnasties.cstr(), *cptr))
00040 unprintables++;
00041
00042 if (*cptr == '\\')
00043 inescape = !inescape;
00044 else
00045 inescape = false;
00046 }
00047
00048
00049 if (bracecount != 0)
00050 backslashify = true;
00051
00052 if (!backslashify && !unprintables)
00053 return s;
00054
00055 if (backslashify)
00056 {
00057
00058 return WvBackslashEncoder(allnasties).strflushstr(s, true);
00059 }
00060 else
00061 {
00062
00063 return WvString("{%s}", s);
00064 }
00065 }
00066
00067
00068 WvString wvtcl_unescape(WvStringParm s)
00069 {
00070
00071
00072
00073 if (!s)
00074 return s;
00075
00076 int slen = s.len();
00077 bool skipquotes = false;
00078
00079
00080 if (s[0] == '{' && s[slen-1] == '}')
00081 {
00082 WvString out;
00083 char *optr;
00084
00085 out = s+1;
00086 optr = out.edit() + slen - 2;
00087 *optr = 0;
00088 return out;
00089 }
00090
00091
00092 if (s[0] == '"' && s[slen-1] == '"')
00093 skipquotes = true;
00094
00095
00096 if (!skipquotes && !strchr(s, '\\'))
00097 return s;
00098
00099
00100 return WvBackslashDecoder().strflushmem(
00101 s.cstr() + int(skipquotes),
00102 slen - int(skipquotes) * 2, true);
00103 }
00104
00105
00106 WvString wvtcl_encode(WvList<WvString> &l, const char *nasties,
00107 const char *splitchars)
00108 {
00109 WvDynBuf b;
00110 WvList<WvString>::Iter i(l);
00111 for (i.rewind(); i.next(); )
00112 {
00113
00114 if (b.used())
00115 b.put(splitchars, 1);
00116
00117
00118 b.putstr(wvtcl_escape(*i, nasties));
00119 }
00120
00121 return b.getstr();
00122 }
00123
00124 WvString wvtcl_getword(WvBuf &buf, const char *splitchars, bool do_unescape)
00125 {
00126 int origsize = buf.used();
00127 if (origsize == 0)
00128 return WvString::null;
00129
00130 bool inescape = false;
00131 bool inquote = false;
00132 bool incontinuation = false;
00133 int bracecount = 0;
00134 const char *sptr = (const char*)buf.get(origsize);
00135 int len = 0;
00136
00137
00138 while (strchr(splitchars, *sptr) && origsize > 0)
00139 {
00140 sptr++;
00141 origsize--;
00142 }
00143
00144 if (origsize == 0)
00145 return WvString::null;
00146
00147
00148 if (*sptr == '"')
00149 {
00150 inquote = true;
00151 len = 1;
00152 }
00153
00154
00155 for (; len < origsize; ++len)
00156 {
00157 char ch = sptr[len];
00158
00159
00160
00161
00162 incontinuation = false;
00163 if (inescape)
00164 {
00165 if (ch == '\n')
00166
00167 incontinuation = true;
00168 else
00169 inescape = false;
00170 continue;
00171 }
00172 else
00173 {
00174 if (ch == '\\')
00175 {
00176 inescape = true;
00177 continue;
00178 }
00179 }
00180
00181
00182 if (bracecount == 0)
00183 {
00184 if (inquote)
00185 {
00186 if (ch == '"')
00187 {
00188 len += 1;
00189 goto returnstring;
00190 }
00191 }
00192 else
00193 {
00194 if (strchr(splitchars, ch))
00195 {
00196 origsize -= 1;
00197 goto returnstring;
00198 }
00199 }
00200 }
00201
00202 if (! inquote)
00203 {
00204 if (ch == '{')
00205 bracecount += 1;
00206 else if (ch == '}')
00207 bracecount -= 1;
00208 }
00209 }
00210
00211
00212 if (bracecount == 0 && len != 0 && !inquote && !inescape && !incontinuation)
00213 goto returnstring;
00214
00215
00216 buf.unget(origsize);
00217 return WvString::null;
00218
00219 returnstring:
00220 char *str = (char*) alloca(len + 1);
00221 memcpy(str, sptr, len);
00222 str[len] = '\0';
00223 buf.unget(origsize - len);
00224
00225 if (do_unescape)
00226 return wvtcl_unescape(str).unique();
00227 return WvString(str).unique();
00228 }
00229
00230 void wvtcl_decode(WvList<WvString> &l, WvStringParm _s,
00231 const char *splitchars, bool do_unescape)
00232 {
00233
00234 if (!_s)
00235 return;
00236
00237 WvConstStringBuffer buf(_s);
00238 while (buf.used() > 0)
00239 {
00240 WvString appendword = wvtcl_getword(buf, splitchars, do_unescape);
00241 if (! appendword.isnull())
00242 {
00243 l.append(new WvString(appendword), true);
00244 }
00245 else
00246 break;
00247 }
00248 }