srcs/toolbox/misc.c

00001 /* 
00002  * Copyright (c) 2005-2012 by KoanLogic s.r.l. - All rights reserved.  
00003  */
00004 
00005 #include <u/libu_conf.h>
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <stdio.h>
00011 #include <time.h>
00012 #include <errno.h>
00013 #include <signal.h>
00014 #include <ctype.h>
00015 #include <fcntl.h>
00016 #include <unistd.h>
00017 #include <sys/types.h>
00018 
00019 #include <toolbox/misc.h>
00020 #include <toolbox/carpal.h>
00021 #include <toolbox/memory.h>
00022 
00041 inline int u_isblank (int c)
00042 {
00043     return c == ' ' || c == '\t';
00044 }
00045 
00056 inline int u_isblank_str (const char *s)
00057 {
00058     for ( ; *s; ++s)
00059     {
00060         if (!u_isblank(*s))
00061             return 0;
00062     }
00063 
00064     return 1;
00065 }
00066 
00078 inline int u_isnl (int c)
00079 {
00080     return c == '\n' || c == '\r';
00081 }
00082 
00095 int u_data_is_bin (char *data, size_t sz)
00096 {
00097     size_t i;
00098 
00099     for (i = 0; i < sz; i++)
00100     {
00101         if (!isascii(data[i]))
00102             return 1;
00103     }
00104 
00105     return 0;
00106 }
00107 
00118 void u_trim (char *s)
00119 {
00120     char *p;
00121 
00122     nop_return_if (s == NULL, );
00123 
00124     /* trim trailing blanks */
00125     p = s + strlen(s) - 1;
00126     while (s < p && u_isblank(*p))
00127         --p;
00128     p[1] = '\0';
00129 
00130     /* trim leading blanks */
00131     p = s;
00132     while (*p && u_isblank(*p))
00133         ++p;
00134 
00135     if (p > s)
00136         memmove(s, p, 1 + strlen(p));
00137 
00138     return;
00139 }
00140 
00154 char *u_strndup (const char *s, size_t len)
00155 {
00156     char *cp;
00157 
00158     /* check bounds */
00159     dbg_return_if (len > strlen(s), NULL);
00160 
00161     /* make room for the substring + \0 */
00162     dbg_return_sif ((cp = u_malloc(len + 1)) == NULL, NULL);
00163 
00164     memcpy(cp, s, len);
00165     cp[len] = '\0';
00166 
00167     return cp;
00168 }
00169 
00183 char *u_strdup (const char *s)
00184 {
00185     return u_strndup(s, strlen(s));
00186 }
00187 
00203 inline int u_strlcpy(char *dst, const char *src, size_t size)
00204 {
00205     return (strlcpy(dst, src, size) >= size ? ~0 : 0);
00206 }
00207 
00223 inline int u_strlcat(char *dst, const char *src, size_t size)
00224 {
00225     return (strlcat(dst, src, size) >= size ? ~0 : 0);
00226 }
00227 
00266 int u_strtok (const char *s, const char *delim, char ***ptv, size_t *pnelems)
00267 {
00268     enum { TV_NSLOTS_DFLT = 10, TV_NSLOTS_INCR = 10 };
00269     char **ap, **tv = NULL, **ntv = NULL;
00270     size_t nelems, tv_slots = TV_NSLOTS_DFLT;
00271     char *p, *sdup = NULL;
00272 
00273     dbg_return_if (s == NULL, ~0);
00274     dbg_return_if (delim == NULL, ~0);
00275     dbg_return_if (ptv == NULL, ~0);
00276     dbg_return_if (pnelems == NULL, ~0);
00277     
00278     sdup = u_strdup(s);
00279     dbg_err_if (sdup == NULL);
00280 
00281     p = sdup;
00282     ap = tv;
00283     nelems = 0;
00284 
00285 expand:
00286     ntv = u_realloc(tv, tv_slots * sizeof(char *));
00287     dbg_err_sif (ntv == NULL);
00288 
00289     /* recalc 'ap' in case realloc has changed the base pointer */
00290     if (ntv != tv)
00291         ap = ntv + (ap - tv);
00292 
00293     tv = ntv;
00294 
00295     for (; (*ap = strsep(&p, delim)) != NULL; )
00296     {
00297         /* skip empty field */
00298         if (**ap == '\0')
00299             continue;
00300 
00301         ++nelems;
00302 
00303         /* when we reach the last slot, request new slots */
00304         if (++ap == &tv[tv_slots - 1])
00305         {
00306             tv_slots += TV_NSLOTS_INCR;
00307             goto expand;
00308         }
00309     }
00310 
00311     /* save the dup'd string on the last slot */
00312     *ap = sdup;
00313 
00314     /* copy out */
00315     *ptv = tv;
00316     *pnelems = nelems;
00317 
00318     return 0;
00319 err:
00320     U_FREE(sdup);
00321     U_FREE(tv);
00322     return ~0;
00323 }
00324 
00335 void u_strtok_cleanup (char **tv, size_t nelems)
00336 {
00337     if (tv)
00338     {
00339         U_FREE(tv[nelems]);
00340         u_free(tv);
00341     }
00342 
00343     return;
00344 }
00345 
00359 int u_snprintf (char *str, size_t size, const char *fmt, ...)
00360 {
00361     int wr;
00362     va_list ap;
00363 
00364     va_start(ap, fmt);
00365     wr = vsnprintf(str, size, fmt, ap);
00366     va_end(ap);
00367 
00368     dbg_err_sif (wr < 0);               /* output error */
00369     dbg_err_if (size <= (size_t) wr);   /* overflow */
00370 
00371     /* was: "dbg_err_if (wr >= (int) size);" bad cast ? */
00372 
00373     return 0;
00374 err:
00375     return ~0;
00376 }
00377 
00392 int u_path_snprintf (char *buf, size_t sz, char sep, const char *fmt, ...)
00393 {
00394     va_list ap;
00395     int wr, i, len;
00396 
00397     va_start(ap, fmt);
00398     wr = vsnprintf(buf, sz, fmt, ap);
00399     va_end(ap);
00400 
00401     dbg_err_sif (wr < 0);
00402     dbg_err_if (sz <= (size_t) wr);
00403 
00404     /* remove multiple consecutive '/' */
00405     for (len = i = strlen(buf); i > 0; --i)
00406     {
00407         if (buf[i] == sep && buf[i - 1] == sep)
00408         {
00409             memmove(buf + i, buf + i + 1, len - i);
00410             len--;
00411         }
00412     }
00413 
00414     return 0;
00415 err:
00416     return ~0;
00417 }
00418 
00430 int u_savepid (const char *pf)
00431 {
00432     FILE *pfp = NULL;
00433 
00434     dbg_return_if (pf == NULL, ~0);
00435 
00436     dbg_err_sif ((pfp = fopen(pf, "w")) == NULL);
00437     dbg_err_sif (fprintf(pfp, "%ld\n", (long) getpid()) == 0);
00438     fclose(pfp);
00439 
00440     return 0;
00441 err:
00442     U_FCLOSE(pfp);
00443     return ~0;
00444 }
00445 
00457 void *u_memdup (const void *src, size_t size)
00458 {
00459     void *p;
00460 
00461     dbg_return_sif ((p = u_malloc(size)) == NULL, NULL);
00462 
00463     memcpy(p, src, size);
00464 
00465     return p;
00466 }
00467 
00480 inline void u_use_unused_args (char *dummy, ...)
00481 {
00482     dummy = 0;
00483     return;
00484 }
00485 
00486 
00500 int u_data_dump (char *data, size_t sz, const char *file)
00501 {
00502     FILE *fp = NULL;
00503 
00504     dbg_err_sif ((fp = fopen(file, "w")) == NULL); 
00505     dbg_err_sif (fwrite(data, sz, 1, fp) < 1);
00506     fclose(fp);
00507 
00508     return 0;
00509 err:
00510     U_FCLOSE(fp); 
00511     return ~0;
00512 }
00513 
00526 int u_load_file (const char *path, size_t sz_max, char **pbuf, size_t *psz)
00527 {   
00528     FILE *fp = NULL;
00529     char *buf = NULL;
00530     size_t sz; 
00531     struct stat sb;
00532     
00533     dbg_return_if (path == NULL, ~0);
00534     dbg_return_if (pbuf == NULL, ~0);
00535     dbg_return_if (psz == NULL, ~0);
00536     
00537     dbg_err_sifm ((fp = fopen(path, "r")) == NULL, "%s", path);
00538     dbg_err_sifm (fstat(fileno(fp), &sb) == -1, "%s", path); 
00539     sz = sb.st_size;
00540     dbg_err_ifm (sz_max > 0 && sz > sz_max, 
00541             "file too big (%zu vs %zu bytes)", sz, sz_max);
00542     dbg_err_sif ((buf = u_zalloc(sz)) == NULL);
00543     dbg_err_sifm (fread(buf, sz, 1, fp) != 1, "%s", path);
00544     
00545     U_FCLOSE(fp);
00546     
00547     *pbuf = buf;
00548     *psz = sz;
00549     
00550     return 0;
00551 err:
00552     U_FCLOSE(fp);
00553     U_FREE(buf);
00554     return ~0;
00555 }
00556 
00581 int u_io (iof_t f, int sd, void *buf, size_t l, ssize_t *n, int *eof)
00582 {
00583 #define SET_PPTR(pptr, val) do {if ((pptr)) *(pptr) = (val);} while (0);
00584     ssize_t nret;
00585     size_t nleft = l;
00586     char *p = buf;
00587 
00588     SET_PPTR(n, 0);
00589     SET_PPTR(eof, 0);
00590 
00591     while (nleft > 0) 
00592     {
00593         if ((nret = (f) (sd, p, nleft)) == -1)
00594         {
00595             if (errno == EINTR)
00596                 continue;
00597             else
00598             {
00599                 dbg_strerror(errno);
00600                 goto end;
00601             }
00602         }
00603 
00604         /* test EOF */
00605         if (nret == 0)
00606         {
00607             SET_PPTR(eof, 1);
00608             goto end;
00609         }
00610         
00611         nleft -= nret;
00612         p += nret;
00613     }
00614 
00615 end:
00616     SET_PPTR(n, l - nleft);
00617     return nleft ? ~0 : 0;
00618 #undef SET_PPTR
00619 }
00620 
00635 ssize_t u_read (int fd, void *buf, size_t size)
00636 {
00637     int eof = 0;
00638     ssize_t nw = 0;
00639 
00640     if (u_io((iof_t) read, fd, buf, size, &nw, &eof))
00641     {
00642         if (eof)
00643             return nw; /* may be zero */
00644         else
00645             return -1;
00646     }
00647 
00648     return nw;
00649 }
00650 
00665 ssize_t u_write (int fd, void *buf, size_t size)
00666 {
00667     if (u_io((iof_t) write, fd, buf, size, NULL, NULL))
00668         return -1;
00669 
00670     return size;
00671 }
00672 
00683 int u_sleep(unsigned int secs)
00684 {
00685 #ifdef OS_WIN
00686     Sleep(secs * 1000);
00687 #else
00688     int sleep_for, c;
00689 
00690     for (sleep_for = secs; sleep_for > 0; sleep_for = c)
00691     {
00692         if ((c = sleep(sleep_for)) == 0)
00693             break;
00694         else if (errno != EINTR)
00695             return -1; /* should never happen */
00696     }
00697 #endif
00698     return 0;
00699 }
00700 
00716 int u_atol (const char *nptr, long *pl)
00717 {
00718     char *endptr;
00719     long tmp, saved_errno = errno;
00720 
00721     dbg_return_if (nptr == NULL, ~0);
00722     dbg_return_if (pl == NULL, ~0);
00723  
00724     tmp = strtol(nptr, &endptr, 10);
00725     
00726     dbg_err_sif (tmp == 0 && errno == EINVAL);
00727     dbg_err_sif ((tmp == LONG_MIN || tmp == LONG_MAX) && errno == ERANGE);
00728 
00729     /* check if no valid digit string was supplied
00730      * glibc does not handle this as an explicit error (would return
00731      * 0 with errno unset) */
00732     dbg_err_ifm (nptr == endptr, "invalid base10 string: %s", nptr);
00733 
00734     *pl = tmp;
00735     
00736     errno = saved_errno;
00737     return 0;
00738 err:
00739     errno = saved_errno;
00740     return ~0;
00741 }
00742 
00758 int u_atoi (const char *nptr, int *pi)
00759 {
00760     long int tmp;
00761 
00762     dbg_err_if (u_atol(nptr, &tmp));
00763 
00764     /* check overflows/underflows when int bits are less than long bits */
00765 #if (INT_MAX < LONG_MAX) 
00766     dbg_err_if (tmp > INT_MAX);
00767 #endif
00768 #if (INT_MIN > LONG_MIN)
00769     dbg_err_if (tmp < INT_MIN);
00770 #endif
00771         
00772     *pi = (int) tmp;
00773     
00774     return 0;
00775 err:
00776     return ~0;
00777 }
00778 
00779 #ifdef HAVE_STRTOUMAX
00780 
00795 int u_atoumax (const char *nptr, uintmax_t *pumax)
00796 {
00797     uintmax_t tmp; 
00798     int saved_errno = errno;
00799 
00800     dbg_return_if (nptr == NULL, ~0);
00801     dbg_return_if (pumax == NULL, ~0);
00802  
00803     tmp = strtoumax(nptr, (char **) NULL, 10);
00804     
00805     dbg_err_if (tmp == 0 && errno == EINVAL);
00806     dbg_err_if (tmp == UINTMAX_MAX && errno == ERANGE);
00807         
00808     *pumax = tmp;
00809     
00810     errno = saved_errno;
00811     return 0;
00812 err:
00813     errno = saved_errno;
00814     return ~0;
00815 }
00816 #endif  /* HAVE_STRTOUMAX */
00817 
00836 int u_atof (const char *nptr, double *pd)
00837 {
00838 #ifdef HAVE_STRTOD
00839     double tmp;
00840     char *endptr;
00841     int saved_errno = errno;
00842 
00843     dbg_return_if (nptr == NULL, ~0);
00844     dbg_return_if (pd == NULL, ~0);
00845 
00846     /* Reset errno. */
00847     errno = 0;  
00848  
00849     /* Try conversion. */
00850     tmp = strtod(nptr, &endptr);
00851     
00852     /* No conversion performed */
00853     dbg_err_if (tmp == 0 && nptr == endptr);
00854 
00855     /* Overflow/underflow conditions.
00856      * 'tmp' can be 0 or [+-]HUGE_VAL, but we're not interested in 
00857      * distinguishing. */
00858     dbg_err_sif (errno == ERANGE);
00859 
00860     *pd = tmp;
00861  
00862     errno = saved_errno;
00863     return 0;
00864 err:
00865     errno = saved_errno;
00866     return ~0;
00867 #else
00868     /* Fall back to old plain atof(3). */
00869     dbg_return_if (nptr == NULL, ~0);
00870     dbg_return_if (pd == NULL, ~0);
00871 
00872     *pd = atof(nptr);
00873 
00874     return 0;
00875 #endif  /* HAVE_STRTOD */
00876 }
00877 
00895 int u_tokenize (char *wlist, const char *delim, char **tokv, size_t tokv_sz)
00896 {
00897     char **ap;
00898 
00899     dbg_return_if (wlist == NULL, ~0);
00900     dbg_return_if (delim == NULL, ~0);
00901     dbg_return_if (tokv == NULL, ~0);
00902     dbg_return_if (tokv_sz == 0, ~0);
00903 
00904     ap = tokv;
00905 
00906     for ( ; (*ap = strsep(&wlist, delim)) != NULL; )
00907     {
00908         /* skip empty field */
00909         if (**ap == '\0')
00910             continue;
00911 
00912         /* check bounds */
00913         if (++ap >= &tokv[tokv_sz - 1])
00914             break;
00915     }
00916 
00917     /* put an explicit stopper to tokv */
00918     *ap = NULL;
00919 
00920     return 0;
00921 }
00922 
00937 char *u_sstrncpy (char *dst, const char *src, size_t size)
00938 {
00939     dst[size] = '\0';
00940     return strncpy(dst, src, size);
00941 }
00942 

←Products
© 2005-2012 - KoanLogic S.r.l. - All rights reserved