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 Sat Mar 13 14:55:59 2004 for WvStreams by doxygen 1.3.6-20040222