Main Page | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

vbuf.c

Go to the documentation of this file.
00001 
00002 #include <ctype.h>
00003 #include <errno.h>
00004 #include <iconv.h>
00005 #include <limits.h>
00006 #include <signal.h>
00007 #include <stdarg.h>
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 
00012 #include "define.h"
00013 #include "vbuf.h"
00014 
00015 #ifdef WITH_DMALLOC
00016 #include <dmalloc.h>
00017 #endif
00018 
00019 #define STUPID_CR "\r\n"
00020 #define ASSERT(x,...) { if( !(x) ) DIE(( __VA_ARGS__)); }
00021 
00022 
00023 int skip_nl(char *s)
00024 {
00025     if (s[0] == '\n')
00026         return 1;
00027     if (s[0] == '\r' && s[1] == '\n')
00028         return 2;
00029     if (s[0] == '\0')
00030         return 0;
00031     return -1;
00032 }
00033 
00034 
00035 int find_nl(vstr * vs)
00036 {
00037     char *nextr, *nextn;
00038 
00039     nextr = memchr(vs->b, '\r', vs->dlen);
00040     nextn = memchr(vs->b, '\n', vs->dlen);
00041 
00042     //case 1: UNIX, we find \n first
00043     if (nextn && (nextr == NULL || nextr > nextn)) {
00044         return nextn - vs->b;
00045     }
00046     //case 2: DOS, we find \r\n
00047     if (NULL != nextr && NULL != nextn && 1 == (char *) nextn - (char *) nextr) {
00048         return nextr - vs->b;
00049     }
00050     //case 3: we find nothing
00051 
00052     return -1;
00053 }
00054 
00055 
00056 //  UTF8 <-> UTF16 <-> ISO8859 Character set conversion functions and (ack) their globals
00057 
00058 //TODO: the following should not be
00059 char *wwbuf = NULL;
00060 size_t nwwbuf = 0;
00061 static int unicode_up = 0;
00062 iconv_t i16to8, i8to16, i8859_1to8, i8toi8859_1;
00063 
00064 
00065 void unicode_init()
00066 {
00067     char *wipe = "";
00068     char dump[4];
00069 
00070     if (unicode_up)
00071         unicode_close();
00072 
00073     if ((iconv_t) - 1 == (i16to8 = iconv_open("UTF-8", "UTF-16LE"))) {
00074         fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-16LE to UTF-8.\n");
00075         exit(1);
00076     }
00077 
00078     if ((iconv_t) - 1 == (i8to16 = iconv_open("UTF-16LE", "UTF-8"))) {
00079         fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to UTF-16LE.\n");
00080         exit(2);
00081     }
00082     //iconv will prefix output with an FF FE (utf-16 start seq), the following dumps that.
00083     memset(dump, 'x', 4);
00084     ASSERT(0 == utf8to16(wipe, 1, dump, 4), "unicode_init(): attempt to dump FF FE failed.");
00085 
00086     if ((iconv_t) - 1 == (i8859_1to8 = iconv_open("UTF-8", "ISO_8859-1"))) {
00087         fprintf(stderr, "doexport(): Couldn't open iconv descriptor for ASCII to UTF-8.\n");
00088         exit(1);
00089     }
00090 
00091     if ((iconv_t) - 1 == (i8toi8859_1 = iconv_open("ISO_8859-1", "UTF-8"))) {
00092         fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to ASCII.\n");
00093         exit(1);
00094     }
00095 
00096     unicode_up = 1;
00097 }
00098 
00099 
00100 void unicode_close()
00101 {
00102     unicode_up = 0;
00103     iconv_close(i8to16);
00104     iconv_close(i16to8);
00105     iconv_close(i8859_1to8);
00106     iconv_close(i8toi8859_1);
00107 }
00108 
00109 
00110 int utf16_is_terminated(char *str, int length)
00111 {
00112     VSTR_STATIC(errbuf, 100);
00113     int len = -1;
00114     int i;
00115     for (i = 0; i < length; i += 2) {
00116         if (str[i] == 0 && str[i + 1] == 0) {
00117             len = i;
00118         }
00119     }
00120 
00121     if (-1 == len) {
00122         vshexdump(errbuf, str, 0, length, 1);
00123         WARN(("String is not zero terminated (probably broken data from registry) %s.", errbuf->b));
00124     }
00125 
00126     return (-1 == len) ? 0 : 1;
00127 }
00128 
00129 
00130 int vb_utf16to8(vbuf * dest, char *buf, int len)
00131 {
00132     size_t inbytesleft = len;
00133     char *inbuf = buf;
00134     size_t icresult = (size_t)-1;
00135     VBUF_STATIC(dumpster, 100);
00136 
00137     size_t outbytesleft = 0;
00138     char *outbuf = NULL;
00139 
00140     ASSERT(unicode_up, "vb_utf16to8() called before unicode started.");
00141 
00142     if (2 > dest->blen)
00143         vbresize(dest, 2);
00144     dest->dlen = 0;
00145 
00146     //Bad Things can happen if a non-zero-terminated utf16 string comes through here
00147     if (!utf16_is_terminated(buf, len))
00148         return -1;
00149 
00150     do {
00151         outbytesleft = dest->blen - dest->dlen;
00152         outbuf = dest->b + dest->dlen;
00153         icresult = iconv(i16to8, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
00154         dest->dlen = outbuf - dest->b;
00155         vbgrow(dest, inbytesleft);
00156     } while ((size_t)-1 == icresult && E2BIG == errno);
00157 
00158     if (0 != vb_utf8to16T(dumpster, dest->b, dest->dlen))
00159         DIE(("Reverse conversion failed."));
00160 
00161     if (icresult == (size_t)-1) {
00162         //TODO: error
00163         //ERR_UNIX( errno, "vb_utf16to8():iconv failure: %s", strerror( errno ) );
00164         unicode_init();
00165         return -1;
00166         /*
00167            fprintf(stderr, "  attempted to convert:\n");
00168            hexdump( (char*)cin, 0, inlen, 1 );
00169            fprintf(stderr, "  result:\n");
00170            hexdump( (char*)bout->b, 0, bout->dlen, 1 );
00171            fprintf(stderr, "  MyDirtyOut:\n");
00172            for( i=0; i<inlen; i++) {
00173            if( inbuf[i] != '\0' ) fprintf(stderr, "%c", inbuf[i] );
00174            }
00175 
00176            fprintf( stderr, "\n" );
00177            raise( SIGSEGV );
00178            exit(1);
00179          */
00180     }
00181 
00182     if (icresult) {
00183         //ERR_UNIX( EILSEQ, "Uhhhh...vb_utf16to8() returning icresult == %d", icresult );
00184         return -1;
00185     }
00186     return icresult;
00187 }
00188 
00189 
00190 int utf8to16(char *inbuf_o, int iblen, char *outbuf_o, int oblen)       // iblen, oblen: bytes including \0
00191 {
00192     //TODO: this is *only* used to dump the utf16 preamble now...
00193     //TODO: This (and 8to16) are the most horrible things I have ever seen...
00194     size_t inbytesleft = 0;
00195     size_t outbytesleft = oblen;
00196     char *inbuf = inbuf_o;
00197     char *outbuf = outbuf_o;
00198     size_t icresult = (size_t)-1;
00199     char *stend;
00200 
00201     stend = memchr(inbuf_o, '\0', iblen);
00202     ASSERT(NULL != stend, "utf8to16(): in string not zero terminated.");
00203     inbytesleft = (stend - inbuf_o + 1 < iblen) ? stend - inbuf_o + 1 : iblen;
00204     icresult = iconv(i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
00205 
00206     if (icresult == (size_t)-1) {
00207         DIE(("iconv failure(%d): %s\n", errno, strerror(errno)));
00208     }
00209     if (icresult > (size_t)INT_MAX) {
00210         return (-1);
00211     }
00212     return (int) icresult;
00213 }
00214 
00215 
00216 int vb_utf8to16T(vbuf * bout, char *cin, int inlen)
00217 {
00218     //TODO: This (and 8to16) are the most horrible things I have ever seen...
00219     size_t inbytesleft = inlen;
00220     char *inbuf = cin;
00221     //int rlen = -1, tlen;
00222     size_t icresult = (size_t)-1;
00223     size_t outbytesleft = 0;
00224     char *outbuf = NULL;
00225 
00226     if (2 > bout->blen)
00227         vbresize(bout, 2);
00228     bout->dlen = 0;
00229 
00230     do {
00231         outbytesleft = bout->blen - bout->dlen;
00232         outbuf = bout->b + bout->dlen;
00233         icresult = iconv(i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
00234         bout->dlen = outbuf - bout->b;
00235         vbgrow(bout, 20);
00236     } while ((size_t)-1 == icresult && E2BIG == errno);
00237 
00238     if (icresult == (size_t)-1) {
00239         WARN(("iconv failure: %s", strerror(errno)));
00240         unicode_init();
00241         return -1;
00242     }
00243     if (icresult > (size_t) INT_MAX) {
00244         return (-1);
00245     }
00246     return icresult;
00247 }
00248 
00249 
00250 /* Quick and dirty UNICODE to std. ascii */
00251 void cheap_uni2ascii(char *src, char *dest, int l)
00252 {
00253 
00254     for (; l > 0; l -= 2) {
00255         *dest = *src;
00256         dest++;
00257         src += 2;
00258     }
00259     *dest = 0;
00260 }
00261 
00262 
00263 /* Quick and dirty ascii to unicode */
00264 void cheap_ascii2uni(char *src, char *dest, int l)
00265 {
00266     for (; l > 0; l--) {
00267         *dest++ = *src++;
00268         *dest++ = 0;
00269 
00270     }
00271 }
00272 
00273 
00274 vbuf *vballoc(size_t len)
00275 {
00276     struct varbuf *result = malloc(sizeof(struct varbuf));
00277     if (result) {
00278         result->dlen = 0;
00279         result->blen = 0;
00280         result->buf = NULL;
00281         vbresize(result, len);
00282     }
00283     else DIE(("malloc() failure"));
00284     return result;
00285 }
00286 
00287 
00288 void vbcheck(vbuf * vb)
00289 {
00290     ASSERT(vb->b >= vb->buf, "vbcheck(): data not inside buffer");
00291     ASSERT((size_t)(vb->b - vb->buf) <= vb->blen, "vbcheck(): vb->b outside of buffer range.");
00292     ASSERT(vb->dlen <= vb->blen, "vbcheck(): data length > buffer length.");
00293     ASSERT(vb->blen < 1024 * 1024, "vbcheck(): blen is a bit large...hmmm.");
00294 }
00295 
00296 
00297 void vbfree(vbuf * vb)
00298 {
00299     free(vb->buf);
00300     free(vb);
00301 }
00302 
00303 
00304 void vbclear(struct varbuf *vb) // ditch the data, keep the buffer
00305 {
00306     vbresize(vb, 0);
00307 }
00308 
00309 
00310 void vbresize(struct varbuf *vb, size_t len)    // DESTRUCTIVELY grow or shrink buffer
00311 {
00312     vb->dlen = 0;
00313 
00314     if (vb->blen >= len) {
00315         vb->b = vb->buf;
00316         return;
00317     }
00318 
00319     vb->buf  = realloc(vb->buf, len);
00320     vb->b    = vb->buf;
00321     vb->blen = len;
00322 }
00323 
00324 
00325 size_t vbavail(vbuf * vb)
00326 {
00327     return vb->blen  - vb->dlen - (size_t)(vb->b - vb->buf);
00328 }
00329 
00330 
00331 //void vbdump( vbuf *vb ) // TODO: to stdout?  Yuck
00332 //{
00333 //      printf("vb dump-------------\n");
00334 //        printf("dlen: %d\n", vb->dlen );
00335 //      printf("blen: %d\n", vb->blen );
00336 //      printf("b - buf: %d\n", vb->b - vb->buf );
00337 //      printf("buf:\n");
00338 //      hexdump( vb->buf, 0, vb->blen, 1 );
00339 //      printf("b:\n");
00340 //      hexdump( vb->b, 0, vb->dlen, 1 );
00341 //      printf("^^^^^^^^^^^^^^^^^^^^\n");
00342 //}
00343 
00344 
00345 void vbgrow(struct varbuf *vb, size_t len)      // out: vbavail(vb) >= len, data are preserved
00346 {
00347     if (0 == len)
00348         return;
00349 
00350     if (0 == vb->blen) {
00351         vbresize(vb, len);
00352         return;
00353     }
00354 
00355     if (vb->dlen + len > vb->blen) {
00356         if (vb->dlen + len < vb->blen * 1.5)
00357             len = vb->blen * 1.5;
00358         char *nb = malloc(vb->blen + len);
00359         if (!nb) DIE(("malloc() failure"));
00360         vb->blen = vb->blen + len;
00361         memcpy(nb, vb->b, vb->dlen);
00362 
00363         free(vb->buf);
00364         vb->buf = nb;
00365         vb->b = vb->buf;
00366     } else {
00367         if (vb->b != vb->buf)
00368             memcpy(vb->buf, vb->b, vb->dlen);
00369     }
00370 
00371     vb->b = vb->buf;
00372 
00373     ASSERT(vbavail(vb) >= len, "vbgrow(): I have failed in my mission.");
00374 }
00375 
00376 
00377 void vbset(vbuf * vb, void *b, size_t len)      // set vbuf b size=len, resize if necessary, relen = how much to over-allocate
00378 {
00379     vbresize(vb, len);
00380 
00381     memcpy(vb->b, b, len);
00382     vb->dlen = len;
00383 }
00384 
00385 
00386 void vsskipws(vstr * vs)
00387 {
00388     char *p = vs->b;
00389     while ((size_t)(p - vs->b) < vs->dlen && isspace(p[0]))
00390         p++;
00391 
00392     vbskip((vbuf *) vs, p - vs->b);
00393 }
00394 
00395 
00396 // append len bytes of b to vbuf, resize if necessary
00397 void vbappend(struct varbuf *vb, void *b, size_t len)
00398 {
00399     if (0 == vb->dlen) {
00400         vbset(vb, b, len);
00401         return;
00402     }
00403     vbgrow(vb, len);
00404     memcpy(vb->b + vb->dlen, b, len);
00405     vb->dlen += len;
00406 }
00407 
00408 
00409 // dumps the first skip bytes from vbuf
00410 void vbskip(struct varbuf *vb, size_t skip)
00411 {
00412     ASSERT(skip <= vb->dlen, "vbskip(): Attempt to seek past end of buffer.");
00413     vb->b += skip;
00414     vb->dlen -= skip;
00415 }
00416 
00417 
00418 // overwrite vbdest with vbsrc
00419 void vboverwrite(struct varbuf *vbdest, struct varbuf *vbsrc)
00420 {
00421     vbresize(vbdest, vbsrc->blen);
00422     memcpy(vbdest->b, vbsrc->b, vbsrc->dlen);
00423     vbdest->blen = vbsrc->blen;
00424     vbdest->dlen = vbsrc->dlen;
00425 }
00426 
00427 
00428 vstr *vsalloc(size_t len)
00429 {
00430     vstr *result = (vstr *) vballoc(len + 1);
00431     vsset(result, "");
00432     return result;
00433 }
00434 
00435 
00436 char *vsstr(vstr * vs)
00437 {
00438     return vs->b;
00439 }
00440 
00441 
00442 size_t vslen(vstr * vs)
00443 {
00444     return strlen(vsstr(vs));
00445 }
00446 
00447 
00448 void vsfree(vstr * vs)
00449 {
00450     vbfree((vbuf *) vs);
00451 }
00452 
00453 
00454 void vscharcat(vstr * vb, int ch)
00455 {
00456     vbgrow((vbuf *) vb, 1);
00457     vb->b[vb->dlen - 1] = ch;
00458     vb->b[vb->dlen] = '\0';
00459     vb->dlen++;
00460 }
00461 
00462 
00463 // prependappend string str to vbuf, vbuf must already contain a valid string
00464 void vsnprepend(vstr * vb, char *str, size_t len)
00465 {
00466     ASSERT(vb->b[vb->dlen - 1] == '\0', "vsncat(): attempt to append string to non-string.");
00467     size_t sl = strlen(str);
00468     size_t n = (sl < len) ? sl : len;
00469     vbgrow((vbuf *) vb, n + 1);
00470     memmove(vb->b + n, vb->b, vb->dlen - 1);
00471     memcpy(vb->b, str, n);
00472     vb->dlen += n;
00473     vb->b[vb->dlen - 1] = '\0';
00474 }
00475 
00476 
00477 // len < dlen-1 -> skip len chars, else DIE
00478 void vsskip(vstr * vs, size_t len)
00479 {
00480     ASSERT(len < vs->dlen - 1, "Attempt to skip past end of string");
00481     vbskip((vbuf *) vs, len);
00482 }
00483 
00484 
00485 // in: vb->b == "stuff\nmore_stuff"; out: vb->b == "more_stuff"
00486 int vsskipline(vstr * vs)
00487 {
00488     int nloff = find_nl(vs);
00489     int nll   = skip_nl(vs->b + nloff);
00490 
00491     if (nloff < 0) {
00492         //TODO: error
00493         printf("vb_skipline(): there seems to be no newline here.\n");
00494         return -1;
00495     }
00496     if (nll < 0) {
00497         //TODO: error
00498         printf("vb_skipline(): there seems to be no newline here...except there should be. :P\n");
00499         return -1;
00500     }
00501 
00502     memmove(vs->b, vs->b + nloff + nll, vs->dlen - nloff - nll);
00503 
00504     vs->dlen -= nloff + nll;
00505 
00506     return 0;
00507 }
00508 
00509 
00510 int vscatprintf(vstr * vs, char *fmt, ...)
00511 {
00512     int size;
00513     va_list ap;
00514 
00515     /* Guess we need no more than 100 bytes. */
00516     //vsresize( vb, 100 );
00517     if (!vs->b || vs->dlen == 0) {
00518         vsset(vs, "");
00519     }
00520 
00521     while (1) {
00522         /* Try to print in the allocated space. */
00523         va_start(ap, fmt);
00524         size = vsnprintf(vs->b + vs->dlen - 1, vs->blen - vs->dlen, fmt, ap);
00525         va_end(ap);
00526 
00527         /* If that worked, return the string. */
00528         if ((size > -1) && ((size_t)size < vs->blen - vs->dlen)) {
00529             vs->dlen += size;
00530             return size;
00531         }
00532         /* Else try again with more space. */
00533         if (size >= 0)          /* glibc 2.1 */
00534             vbgrow((vbuf *) vs, size + 1);      /* precisely what is needed */
00535         else                    /* glibc 2.0 */
00536             vbgrow((vbuf *) vs, vs->blen);
00537     }
00538 }
00539 
00540 
00541 //  returns the last character stored in a vstr
00542 int vslast(vstr * vs)
00543 {
00544     if (vs->dlen < 1)
00545         return -1;
00546     if (vs->b[vs->dlen - 1] != '\0')
00547         return -1;
00548     if (vs->dlen == 1)
00549         return '\0';
00550     return vs->b[vs->dlen - 2];
00551 }
00552 
00553 
00554 //  print over vb
00555 void vs_printf(vstr * vs, char *fmt, ...)
00556 {
00557     int size;
00558     va_list ap;
00559 
00560     /* Guess we need no more than 100 bytes. */
00561     vbresize((vbuf *) vs, 100);
00562 
00563     while (1) {
00564         /* Try to print in the allocated space. */
00565         va_start(ap, fmt);
00566         size = vsnprintf(vs->b, vs->blen, fmt, ap);
00567         va_end(ap);
00568 
00569         /* If that worked, return the string. */
00570         if ((size > -1) && ((size_t)size < vs->blen)) {
00571             vs->dlen = size + 1;
00572             return;
00573         }
00574         /* Else try again with more space. */
00575         if (size >= 0)          /* glibc 2.1 */
00576             vbresize((vbuf *) vs, size + 1);    /* precisely what is needed */
00577         else                    /* glibc 2.0 */
00578             vbresize((vbuf *) vs, vs->blen * 2);
00579     }
00580 }
00581 
00582 
00583 // printf append to vs
00584 void vs_printfa(vstr * vs, char *fmt, ...)
00585 {
00586     int size;
00587     va_list ap;
00588 
00589     if (vs->blen - vs->dlen < 50)
00590         vbgrow((vbuf *) vs, 100);
00591 
00592     while (1) {
00593         /* Try to print in the allocated space. */
00594         va_start(ap, fmt);
00595         size = vsnprintf(vs->b + vs->dlen - 1, vs->blen - vs->dlen + 1, fmt, ap);
00596         va_end(ap);
00597 
00598         /* If that worked, return the string. */
00599         if ((size > -1) && ((size_t)size < vs->blen)) {
00600             vs->dlen += size;
00601             return;
00602         }
00603         /* Else try again with more space. */
00604         if (size >= 0)          /* glibc 2.1 */
00605             vbgrow((vbuf *) vs, size + 1 - vs->dlen);   /* precisely what is needed */
00606         else                    /* glibc 2.0 */
00607             vbgrow((vbuf *) vs, size);
00608     }
00609 }
00610 
00611 
00612 void vshexdump(vstr * vs, char *b, size_t start, size_t stop, int ascii)
00613 {
00614     char c;
00615     int diff, i;
00616 
00617     while (start < stop) {
00618         diff = stop - start;
00619         if (diff > 16)
00620             diff = 16;
00621 
00622         vs_printfa(vs, ":%08X  ", start);
00623 
00624         for (i = 0; i < diff; i++) {
00625             if (8 == i)
00626                 vs_printfa(vs, " ");
00627             vs_printfa(vs, "%02X ", (unsigned char) *(b + start + i));
00628         }
00629         if (ascii) {
00630             for (i = diff; i < 16; i++)
00631                 vs_printfa(vs, "   ");
00632             for (i = 0; i < diff; i++) {
00633                 c = *(b + start + i);
00634                 vs_printfa(vs, "%c", isprint(c) ? c : '.');
00635             }
00636         }
00637         vs_printfa(vs, "\n");
00638         start += 16;
00639     }
00640 }
00641 
00642 
00643 void vsset(vstr * vs, char *s)  // Store string s in vs
00644 {
00645     vsnset(vs, s, strlen(s));
00646 }
00647 
00648 
00649 void vsnset(vstr * vs, char *s, size_t n)       // Store string s in vs
00650 {
00651     vbresize((vbuf *) vs, n + 1);
00652     memcpy(vs->b, s, n);
00653     vs->b[n] = '\0';
00654     vs->dlen = n + 1;
00655 }
00656 
00657 
00658 void vsgrow(vstr * vs, size_t len)      // grow buffer by len bytes, data are preserved
00659 {
00660     vbgrow((vbuf *) vs, len);
00661 }
00662 
00663 
00664 size_t vsavail(vstr * vs)
00665 {
00666     return vbavail((vbuf *) vs);
00667 }
00668 
00669 
00670 void vsnset16(vstr * vs, char *s, size_t len)   // Like vbstrnset, but for UTF16
00671 {
00672     vbresize((vbuf *) vs, len + 1);
00673     memcpy(vs->b, s, len);
00674 
00675     vs->b[len] = '\0';
00676     vs->dlen = len + 1;
00677     vs->b[len] = '\0';
00678 }
00679 
00680 
00681 void vscat(vstr * vs, char *str)
00682 {
00683     vsncat(vs, str, strlen(str));
00684 }
00685 
00686 
00687 int vscmp(vstr * vs, char *str)
00688 {
00689     return strcmp(vs->b, str);
00690 }
00691 
00692 
00693 void vsncat(vstr * vs, char *str, size_t len)   // append string str to vstr, vstr must already contain a valid string
00694 {
00695     ASSERT(vs->b[vs->dlen - 1] == '\0', "vsncat(): attempt to append string to non-string.");
00696     size_t sl = strlen(str);
00697     size_t n = (sl < len) ? sl : len;
00698     //string append
00699     vbgrow((vbuf *) vs, n + 1);
00700     memcpy(vs->b + vs->dlen - 1, str, n);
00701     vs->dlen += n;
00702     vs->b[vs->dlen - 1] = '\0';
00703 }
00704 
00705 
00706 void vstrunc(vstr * v, size_t off) // Drop chars [off..dlen]
00707 {
00708     if (off >= v->dlen - 1)
00709         return;                 //nothing to do
00710     v->b[off] = '\0';
00711     v->dlen = off + 1;
00712 }
00713 
00714 

Generated on Thu Dec 11 11:58:49 2008 for 'LibPst' by  doxygen 1.3.9.1