Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvtclstring.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 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 // NULL strings remain such 00020 if (!(const char *)s) 00021 return s; 00022 00023 // empty strings are just {} 00024 if (!s) 00025 return "{}"; 00026 00027 // figure out which method we need to use: backslashify or embrace. 00028 // also count the number of unprintable characters we'll need to 00029 // backslashify, if it turns out that's necessary. 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 // if the braces aren't balanced, backslashify 00049 if (bracecount != 0) 00050 backslashify = true; 00051 00052 if (!backslashify && !unprintables) 00053 return s; // no work needed! 00054 00055 if (backslashify) 00056 { 00057 // the backslashify method: backslash-escape _all_ suspicious chars. 00058 return WvBackslashEncoder(allnasties).strflushstr(s, true); 00059 } 00060 else 00061 { 00062 // the embrace method: just take the string and put braces around it 00063 return WvString("{%s}", s); 00064 } 00065 } 00066 00067 00068 WvString wvtcl_unescape(WvStringParm s) 00069 { 00070 //printf(" unescape '%s'\n", (const char *)s); 00071 00072 // empty or NULL strings remain themselves 00073 if (!s) 00074 return s; 00075 00076 int slen = s.len(); 00077 bool skipquotes = false; 00078 00079 // deal with embraced strings by simply removing the braces 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 // deal with quoted strings by ignoring the quotes _and_ unbackslashifying. 00092 if (s[0] == '"' && s[slen-1] == '"') 00093 skipquotes = true; 00094 00095 // strings without backslashes don't need to be unbackslashified! 00096 if (!skipquotes && !strchr(s, '\\')) 00097 return s; 00098 00099 // otherwise, unbackslashify it. 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 // elements are separated by spaces 00114 if (b.used()) 00115 b.put(splitchars, 1); 00116 00117 // escape and add the element 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 // skip leading whitespace/separators 00138 while (strchr(splitchars, *sptr) && origsize > 0) 00139 { 00140 sptr++; 00141 origsize--; 00142 } 00143 00144 if (origsize == 0) 00145 return WvString::null; 00146 00147 // detect initial quote 00148 if (*sptr == '"') 00149 { 00150 inquote = true; 00151 len = 1; 00152 } 00153 00154 // loop over string until something satisfactory is found 00155 for (; len < origsize; ++len) 00156 { 00157 char ch = sptr[len]; 00158 00159 // handle escapes and line continuations 00160 // we wait until we receive the next character after these 00161 // before returning any data 00162 incontinuation = false; 00163 if (inescape) 00164 { 00165 if (ch == '\n') 00166 // need a char from next line before the escape is done 00167 incontinuation = true; 00168 else 00169 inescape = false; 00170 continue; // don't process this char 00171 } 00172 else 00173 { 00174 if (ch == '\\') 00175 { 00176 inescape = true; 00177 continue; // need a character to complete escape 00178 } 00179 } 00180 00181 // detect end of a quoted/unquoted string 00182 if (bracecount == 0) 00183 { 00184 if (inquote) 00185 { 00186 if (ch == '"') 00187 { 00188 len += 1; // include the quote 00189 goto returnstring; 00190 } 00191 } 00192 else 00193 { 00194 if (strchr(splitchars, ch)) 00195 { 00196 origsize -= 1; // consume the delimiter 00197 goto returnstring; 00198 } 00199 } 00200 } 00201 // match braces 00202 if (! inquote) 00203 { 00204 if (ch == '{') 00205 bracecount += 1; 00206 else if (ch == '}') 00207 bracecount -= 1; 00208 } 00209 } 00210 00211 // finished the string - get the terminating element, if any. 00212 if (bracecount == 0 && len != 0 && !inquote && !inescape && !incontinuation) 00213 goto returnstring; 00214 00215 // give up 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 // empty or null strings are empty lists 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 }

Generated on Tue Oct 5 01:09:21 2004 for WvStreams by doxygen 1.3.7