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

strutils.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * Various useful string-based utilities.
00006  *
00007  */
00008 #include "strutils.h"
00009 #include "wvbuf.h"
00010 #include <ctype.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <time.h>
00014 
00015 #ifndef _WIN32
00016 #include <errno.h>
00017 #include <netdb.h>
00018 #include <unistd.h>
00019 #else
00020 #undef errno
00021 #define errno GetLastError()
00022 #define strcasecmp _stricmp
00023 #include <winsock2.h>
00024 #endif
00025 
00026 char *terminate_string(char *string, char c)
00027 /**********************************************/
00028 // Add character c to the end of a string after removing crlf's.
00029 // NOTE: You need a buffer that's at least one character bigger than the
00030 // current length of the string, including the terminating NULL.
00031 {
00032     char *p;
00033 
00034     if (string == NULL)
00035         return NULL;
00036 
00037     p = string + strlen(string) - 1;
00038     while (*p == '\r' || *p == '\n')
00039         p--;
00040 
00041     *(++p) = c;
00042     *(++p) = 0;
00043 
00044     return string;
00045 }
00046 
00047 
00048 char *trim_string(char *string)
00049 /*********************************/
00050 // Trims spaces off the front and end of strings.  Modifies the string.
00051 // Specifically DOES allow string==NULL; returns NULL in that case.
00052 {
00053     char *p;
00054     char *q;
00055 
00056     if (string == NULL)
00057         return NULL;
00058 
00059     p = string;
00060     q = string + strlen(string) - 1;
00061 
00062     while (q >= p && isspace(*q))
00063         *(q--) = 0;
00064     while (isspace(*p))
00065         p++;
00066 
00067     return p;
00068 }
00069 
00070 
00071 char *trim_string(char *string, char c)
00072 // Searches the string for c and removes it plus everything afterwards.
00073 // Modifies the string and returns NULL if string == NULL.
00074 {
00075     char *p;
00076 
00077     if (string == NULL)
00078         return NULL;
00079 
00080     p = string;
00081 
00082     while (*p != 0 && *p != c)
00083         p++;
00084 
00085     while (*p)
00086         *(p++) = 0;
00087 
00088     return string;
00089 }
00090 
00091 
00092 // Replaces whitespace characters with nonbreaking spaces.
00093 char *non_breaking(char * string)
00094 {
00095     if (string == NULL)
00096         return (NULL);
00097 
00098     WvDynBuf buf;
00099 
00100     while (*string)
00101     {
00102         if (isspace(*string))
00103             buf.putstr("&nbsp;");
00104         else 
00105             buf.putch(*string);
00106         string++;
00107     }
00108 
00109     WvString s(buf.getstr());
00110     return s.edit();
00111 }
00112 
00113 
00114 // Searches _string (up to length bytes), replacing any occurrences of c1
00115 // with c2.
00116 void replace_char(void *_string, char c1, char c2, int length)
00117 {
00118     char *string = (char *)_string;
00119     for (int i=0; i < length; i++)
00120         if (*(string+i) == c1)
00121             *(string+i) = c2;
00122 }
00123 
00124 // Snip off the first part of 'haystack' if it consists of 'needle'.
00125 char *snip_string(char *haystack, char *needle)
00126 {
00127     if(!haystack)
00128         return NULL;
00129     if(!needle)
00130         return haystack;
00131     char *p = strstr(haystack, needle);
00132     if(!p || p != haystack)
00133         return haystack;
00134     else
00135         return haystack + strlen(needle);
00136 }
00137 
00138 #ifndef _WIN32
00139 char *strlwr(char *string)
00140 {
00141     char *p = string;
00142     while (*p)
00143     {
00144         *p = tolower(*p);
00145         p++;
00146     }
00147 
00148     return string;
00149 }
00150 
00151 
00152 char *strupr(char *string)
00153 {
00154     char *p = string;
00155     while (*p)
00156     {
00157         *p = toupper(*p);
00158         p++;
00159     }
00160 
00161     return string;
00162 }
00163 #endif
00164 
00165 // true if all the characters in "string" are isalnum().
00166 bool is_word(const char *p)
00167 {
00168     while (*p)
00169     {
00170         if(!isalnum(*p++))
00171             return false;
00172     }
00173     
00174     return true;
00175 }
00176 
00177 
00178 // produce a hexadecimal dump of the data buffer in 'buf' of length 'len'.
00179 // it is formatted with 16 bytes per line; each line has an address offset,
00180 // hex representation, and printable representation.
00181 WvString hexdump_buffer(const void *_buf, size_t len, bool charRep)
00182 {
00183     const unsigned char *buf = (const unsigned char *)_buf;
00184     size_t count, count2, top;
00185     WvString out;
00186 
00187     out.setsize(len / 16 * 80 + 80);
00188     char *cptr = out.edit();
00189     
00190     for (count = 0; count < len; count+=16)
00191     {
00192         top = len-count < 16 ? len-count : 16;
00193         cptr += sprintf(cptr, "[%03X] ", (unsigned int)count);
00194         
00195         // dump hex values
00196         for (count2 = 0; count2 < top; count2++)
00197         {
00198             if (count2 && !(count2 % 4))
00199                 *cptr++ = ' ';
00200             cptr += sprintf(cptr, "%02X", buf[count+count2]);
00201         }
00202         
00203         // print horizontal separation
00204         for (count2 = top; count2 < 16; count2++)
00205         {
00206             if (count2 && !(count2 % 4))
00207             {
00208                 strcat(cptr, "   ");
00209                 cptr += 3;
00210             }
00211             else
00212             {
00213                 strcat(cptr, "  ");
00214                 cptr += 2;
00215             }
00216         }
00217         
00218         *cptr++ = ' ';
00219         
00220         // dump character representation
00221         if (charRep)
00222             for (count2 = 0; count2 < top; count2++)
00223                 *cptr++ = (isprint(buf[count+count2])
00224                            ? buf[count+count2] : '.');
00225 
00226         *cptr++ = '\n';
00227     }
00228     *cptr = 0;
00229     return out;
00230 }
00231 
00232 
00233 // return true if the character is a newline.
00234 bool isnewline(char c)
00235 {
00236     return c=='\n' || c=='\r';
00237 }
00238 
00239 // ex: WvString foo = web_unescape("I+am+text.%0D%0A");
00240 WvString web_unescape(const char *str)
00241 {
00242     const char *iptr;
00243     char *optr;
00244     char *idx1, *idx2;
00245     static const char hex[] = "0123456789ABCDEF";
00246     WvString in, intmp(str), out;
00247  
00248     in = trim_string(intmp.edit());
00249     out.setsize(strlen(in) + 1);
00250 
00251     optr = out.edit();
00252     for (iptr = in, optr = out.edit(); *iptr; iptr++)
00253     {
00254         if (*iptr == '+')
00255             *optr++ = ' ';
00256         else if (*iptr == '%' && iptr[1] && iptr[2])
00257         {
00258             idx1 = strchr(hex, toupper((unsigned char) iptr[1]));
00259             idx2 = strchr(hex, toupper((unsigned char) iptr[2]));
00260 
00261             if (idx1 && idx2)
00262                 *optr++ = ((idx1 - hex) << 4) | (idx2 - hex);
00263 
00264             iptr += 2;
00265         }
00266         else
00267             *optr++ = *iptr;
00268     }
00269 
00270     *optr = 0;
00271 
00272     return out;
00273 }
00274 
00275 
00276 // And it's magic companion: url_encode
00277 WvString url_encode(WvStringParm stuff)
00278 {
00279     unsigned int i;
00280     WvDynBuf retval;
00281 
00282     for (i=0; i < stuff.len(); i++)
00283     {
00284         if (isalnum(stuff[i]) || strchr("/_.-~", stuff[i]))
00285         {
00286             retval.put(&stuff[i], 1);
00287         }               
00288         else            
00289         {               
00290             char buf[3];
00291             sprintf(buf, "%%%02x", stuff[i] & 0xff);
00292             retval.put(&buf, 3);
00293         }
00294     }
00295     return retval.getstr();
00296 }
00297 
00298 
00299 WvString rfc822_date(time_t when)
00300 {
00301     WvString out;
00302     out.setsize(80);
00303 
00304     if (when < 0)
00305         when = time(NULL);
00306 
00307     struct tm *tmwhen = localtime(&when);
00308     strftime(out.edit(), 80, "%a, %d %b %Y %H:%M:%S %z", tmwhen);
00309 
00310     return out;
00311 }
00312 
00313 
00314 WvString backslash_escape(WvStringParm s1)
00315 {
00316     // stick a backslash in front of every !isalnum() character in s1
00317     if (!s1)
00318         return "";
00319 
00320     WvString s2;
00321     s2.setsize(s1.len() * 2 + 1);
00322 
00323     const char *p1 = s1;
00324     char *p2 = s2.edit();
00325     while (*p1)
00326     {
00327         if (!isalnum(*p1))
00328             *p2++ = '\\';
00329         *p2++ = *p1++;
00330     }
00331     *p2 = 0;
00332 
00333     return s2;
00334 }
00335 
00336 
00337 int strcount(WvStringParm s, const char c)
00338 {
00339     int n=0;
00340     const char *p = s;
00341     while ((p=strchr(p, c)) != NULL && p++)
00342         n++;
00343 
00344     return n;
00345 }
00346 
00347 
00348 WvString encode_hostname_as_DN(WvStringParm hostname)
00349 {
00350     WvString dn("");
00351     
00352     WvStringList fqdnlist;
00353     WvStringList::Iter i(fqdnlist);
00354     
00355     fqdnlist.split(hostname, ".");
00356     for (i.rewind(); i.next(); )
00357         dn.append("dc=%s,", *i);
00358     dn.append("cn=%s", hostname);
00359     
00360     return dn;
00361 }
00362 
00363 
00364 WvString nice_hostname(WvStringParm name)
00365 {
00366     WvString nice;
00367     char *optr, *optr_start;
00368     const char *iptr;
00369     bool last_was_dash;
00370     
00371     nice.setsize(name.len() + 2);
00372 
00373     iptr = name;
00374     optr = optr_start = nice.edit();
00375     if (!isascii(*iptr) || !isalnum(*(const unsigned char *)iptr))
00376         *optr++ = 'x'; // DNS names must start with a letter!
00377     
00378     last_was_dash = false;
00379     for (; *iptr; iptr++)
00380     {
00381         if (!isascii(*iptr))
00382             continue; // skip it entirely
00383         
00384         if (*iptr == '-' || *iptr == '_')
00385         {
00386             if (last_was_dash)
00387                 continue;
00388             last_was_dash = true;
00389             *optr++ = '-';
00390         }
00391         else if (isalnum(*(const unsigned char *)iptr) || *iptr == '.')
00392         {
00393             *optr++ = *iptr;
00394             last_was_dash = false;
00395         }
00396     }
00397     
00398     if (optr > optr_start && !isalnum(*(const unsigned char *)(optr-1)))
00399         *optr++ = 'x'; // must _end_ in a letter/number too!
00400     
00401     *optr++ = 0;
00402     
00403     if (!nice.len())
00404         return "UNKNOWN";
00405     
00406     return nice;
00407 }
00408 
00409 
00410 WvString getfilename(WvStringParm fullname)
00411 {
00412     WvString tmp(fullname);
00413     char *cptr = strrchr(tmp.edit(), '/');
00414     
00415     if (!cptr) // no slash at all
00416         return fullname;
00417     else if (!cptr[1]) // terminating slash
00418     {
00419         *cptr = 0;
00420         return getfilename(tmp);
00421     }
00422     else // no terminating slash
00423         return cptr+1;
00424 }
00425 
00426 
00427 WvString getdirname(WvStringParm fullname)
00428 {
00429     WvString tmp(fullname);
00430     char *cptr = strrchr(tmp.edit(), '/');
00431     
00432     if (!cptr) // no slash at all
00433         return ".";
00434     else if (!cptr[1]) // terminating slash
00435     {
00436         *cptr = 0;
00437         return getdirname(tmp);
00438     }
00439     else // no terminating slash
00440     {
00441         *cptr = 0;
00442         return !tmp ? WvString("/") : tmp;
00443     }
00444 }
00445 
00446 
00447 WvString sizetoa(long long blocks, int blocksize)
00448 {
00449     long long kbytes = blocks * (long long) blocksize / 1000;
00450 
00451     if (kbytes >= 1000*1000*1000)
00452         return WvString("%s.%s TB",
00453                     (unsigned long) (kbytes/(1000*1000*1000)),
00454                     (unsigned long) (kbytes%(1000*1000*1000))/(100*1000*1000));
00455     else if (kbytes >= 1000*1000)
00456         return WvString("%s.%s GB",
00457                     (unsigned long) (kbytes/(1000*1000)),
00458                     (unsigned long) (kbytes % (1000*1000))/(100*1000));
00459     else if (kbytes >= 1000)
00460         return WvString("%s.%s MB",
00461                     (unsigned long) (kbytes/(1000)),
00462                     (unsigned long) (kbytes % (1000))/(100));
00463     else if (kbytes)
00464         return WvString("%s.%s KB",
00465                     (unsigned long) (blocks*blocksize / 1000),
00466                     (unsigned long) ((blocks*blocksize) % 1000)/(100));
00467     else
00468         return WvString("%s bytes", blocks*blocksize);
00469 }
00470 
00471 
00472 WvString strreplace(WvStringParm s, WvStringParm a, WvStringParm b)
00473 {
00474     WvDynBuf buf;
00475     const char *sptr = s, *eptr;
00476     
00477     while ((eptr = strstr(sptr, a)) != NULL)
00478     {
00479         buf.put(sptr, eptr-sptr);
00480         buf.putstr(b);
00481         sptr = eptr + strlen(a);
00482     }
00483     
00484     buf.put(sptr, strlen(sptr));
00485     
00486     return buf.getstr();
00487 }
00488 
00489 WvString undupe(WvStringParm s, char c)
00490 {
00491     WvDynBuf out;
00492 
00493     bool last = false;
00494 
00495     for (int i = 0; s[i] != '\0'; i++)
00496     {
00497         if (s[i] != c)
00498         {
00499             out.putch(s[i]);
00500             last = false;
00501         }
00502         else if (!last)
00503         {
00504             out.putch(c);
00505             last = true;
00506         }
00507     }
00508     
00509     return out.getstr();
00510 }
00511 
00512 
00513 WvString rfc1123_date(time_t t)
00514 {
00515     struct tm *tm = gmtime(&t);
00516     WvString s;
00517 
00518     s.setsize(128);
00519     strftime(s.edit(), 128, "%a, %d %b %Y %H:%M:%S GMT", tm);
00520 
00521     return s;
00522 }
00523 
00524 
00525 int lookup(const char *str, const char * const *table, bool case_sensitive)
00526 {
00527     for (int i = 0; table[i]; ++i)
00528     {
00529         if (case_sensitive)
00530         {
00531             if (strcmp(str, table[i]) != 0)
00532                 continue;
00533         }
00534         else
00535         {
00536             if (strcasecmp(str, table[i]) != 0)
00537                 continue;
00538         }
00539         return i;
00540     }
00541     return -1;
00542 }
00543 
00544 
00545 WvString hostname()
00546 {
00547     int maxlen = 0;
00548     for(;;)
00549     {
00550         maxlen += 80;
00551         char *name = new char[maxlen];
00552         int result = gethostname(name, maxlen);
00553         if (result == 0)
00554         {
00555             WvString hostname(name);
00556             delete [] name;         
00557             return hostname;
00558         }
00559 #ifdef _WIN32
00560         assert(errno == WSAEFAULT);
00561 #else
00562         assert(errno == EINVAL);
00563 #endif
00564     }
00565 }
00566 
00567 
00568 WvString fqdomainname() 
00569 {
00570     struct hostent *myhost;
00571 
00572     myhost = gethostbyname(hostname());
00573     if (myhost)
00574         return myhost->h_name;
00575     else
00576         return WvString::null;
00577 }
00578 
00579 
00580 WvString metriculate(const off_t i)
00581 {
00582     WvString res;
00583     int digits=0;
00584     int digit=0;
00585     long long int j=i;
00586     char *p;
00587 
00588     while (j)
00589     {
00590         digits++;
00591         j/=10;
00592     }
00593 
00594     j=i;
00595     res.setsize(digits + (digits-1)/3 + 1);
00596     p=res.edit()+digits+((digits-1)/3);
00597     *p-- = '\0';
00598 
00599     for (digit=0; digit<digits; digit++)
00600     {
00601         *p-- = '0' + ( j%10 );
00602         if (((digit+1) % 3) == 0)
00603             *p-- = ' ';
00604         j /= 10;
00605     }
00606 
00607     return res;
00608 }

Generated on Sat Mar 13 14:55:16 2004 for WvStreams by doxygen 1.3.6-20040222