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 Tue Oct 5 01:09:19 2004 for WvStreams by doxygen 1.3.7