util/helper.c

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------------
00002 Name:      xmlBlaster/src/c/util/helper.c
00003 Project:   xmlBlaster.org
00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
00005 Comment:   Contains helper functions for string and message manipulation
00006            Generic helper code, used by Queue implementation and xmlBlaster client code
00007            Don't add any queue specific or xmlBlaster client specific code!
00008 Compile:   gcc -Wall -g -o helper helper.c -DHELPER_UTIL_MAIN -I..
00009 Testsuite: xmlBlaster/testsuite/src/c/TestUtil.c
00010 Author:    "Marcel Ruff" <xmlBlaster@marcelruff.info>
00011 -----------------------------------------------------------------------------*/
00012 
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <stdarg.h>
00016 #include <string.h>
00017 #include <ctype.h>
00018 #include <assert.h>
00019 #include <time.h>
00020 #include "helper.h"
00021 
00022 #ifdef _ENABLE_STACK_TRACE_
00023 # include <execinfo.h>
00024 #endif
00025 
00026 #ifdef _WINDOWS
00027 #  if defined(WINCE)
00028      /* time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds */
00029 #    if !defined(PTW32_TIMESPEC_TO_FILETIME_OFFSET)
00030 #       define PTW32_TIMESPEC_TO_FILETIME_OFFSET \
00031           ( ((LONGLONG) 27111902 << 32) + (LONGLONG) 3577643008 )
00032 #    endif
00033 #  else
00034 #    include <sys/timeb.h>
00035 #  endif
00036 #  include <Winsock2.h>       /* Sleep() */
00037 #  if XB_USE_PTHREADS
00038 #    include <pthreads/pthread.h> /* Our pthreads.h: For logging output of thread ID, for Windows and WinCE downloaded from http://sources.redhat.com/pthreads-win32 */
00039 #  endif
00040 #else
00041 #  include <unistd.h>         /* sleep(), only used in main */
00042 #  include <errno.h>          /* errno */
00043 #  include <sys/time.h>       /* sleep with select(), gettimeofday() */
00044 #  include <sys/types.h>      /* sleep with select() */
00045 #  if XB_USE_PTHREADS
00046 #    include <pthread.h>      /* The original pthreads.h from the OS */
00047 #  endif
00048 #endif
00049 
00050 
00051 #define  MICRO_SECS_PER_SECOND 1000000
00052 #define  NANO_SECS_PER_SECOND MICRO_SECS_PER_SECOND * 1000
00053 
00054 static const char *LOG_TEXT[] = { "NOLOG", "ERROR", "WARN", "INFO", "CALL", "TIME", "TRACE", "DUMP", "PLAIN" };
00055 static const int numLOG_TEXT = 9; /* sizeof(LOG_TEXT) returns 36 which is not what we want */
00056 
00057 #define ESC "\033[0m"; /* Reset color to original values */
00058 #define BOLD "\033[1m"
00059 
00060 #define RED_BLACK "\033[31;40m"
00061 #define GREEN_BLACK "\033[32;40m"
00062 #define YELLOW_BLACK "\033[33;40m"
00063 #define BLUE_BLACK "\033[34;40m"
00064 #define PINK_BLACK "\033[35;40m"
00065 #define LTGREEN_BLACK "\033[36;40m"
00066 #define WHITE_BLACK "\033[37;40m"
00067 
00068 #define WHITE_RED "\033[37;41m"
00069 #define BLACK_RED "\033[30;41m"
00070 #define BLACK_GREEN "\033[40;42m"
00071 #define BLACK_PINK "\033[40;45m"
00072 #define BLACK_LTGREEN "\033[40;46m"
00073 
00074 /* To support colored logging output in xterminals */
00075 static const char *LOG_TEXT_ESCAPE[] = {
00076        "NOLOG",
00077         "\033[31;40mERROR\033[0m",
00078         "\033[33;40mWARN\033[0m",
00079         "\033[32;40mINFO\033[0m",
00080         "\033[34;40mCALL\033[0m",
00081         "\033[36;40mTIME\033[0m",
00082         "\033[37;40mTRACE\033[0m",
00083         "\033[35;40mDUMP\033[0m",
00084         "\033[37;40mPLAIN\033[0m"
00085         };
00086 
00087 static int vsnprintf0(char *s, size_t size, const char *format, va_list ap);
00088 
00094 Dll_Export char *getStackTrace(int maxNumOfLines)
00095 {
00096 #ifdef _ENABLE_STACK_TRACE_
00097    int i;
00098    void** arr = (void **)calloc(maxNumOfLines, sizeof(void *));
00099    if (arr == 0) return (char *)0;
00100    {
00101       /*
00102       > +Currently, the function name and offset can only be obtained on systems
00103       > +that use the ELF binary format for programs and libraries.
00104       Perhaps a reference to the addr2line program can be added here.  It
00105       can be used to retrieve symbols even if the -rdynamic flag wasn't
00106       passed to the linker, and it should work on non-ELF targets as well.
00107       o  Under linux, gcc interprets it by setting the 
00108          "-export-dynamic" option for ld, which has that effect, according
00109          to the linux ld manpage.
00110 
00111       o Under IRIX it's ignored, and the program's happy as a clam.
00112 
00113       o Under SunOS-4.1, gcc interprets it by setting the -dc -dp
00114          options for ld, which again forces the allocation of the symbol
00115          table in the code produced (see ld(1) on a Sun).
00116       */
00117       int bt = backtrace(arr, maxNumOfLines);
00118       char** list = (char **)backtrace_symbols(arr, bt); /* malloc the return pointer, the entries don't need to be freed */
00119       char *ret = strcpyAlloc("");
00120       for (i=0; i<bt; i++) {
00121          if (list[i] != NULL) {
00122             strcatAlloc(&ret, list[i]);
00123             strcatAlloc(&ret, "\n");
00124          }
00125       }
00126       free(list);
00127       free(arr);
00128       if (strlen(ret) < 1) {
00129          strcatAlloc(&ret, ""); /* Creation of stackTrace failed */
00130       }
00131       return ret;
00132    }
00133 #else
00134    if (maxNumOfLines > 0)      /* to make the compiler happy */
00135       return strcpyAlloc("");
00136    return strcpyAlloc(""); /* No stack trace provided in this system */
00137 #endif
00138 }
00139 
00140 #ifndef XMLBLASTER_SLEEP_FALLBACK 
00141 #  define  XMLBLASTER_SLEEP_FALLBACK 0 /* Initialize to make icc happy */
00142 #endif
00143 #ifndef XMLBLASTER_SLEEP_NANO
00144 #  define XMLBLASTER_SLEEP_NANO 0
00145 #endif 
00146 
00150 Dll_Export void sleepMillis(long millisecs)
00151 {
00152 #ifdef _WINDOWS
00153    Sleep(millisecs);
00154 #elif XMLBLASTER_SLEEP_FALLBACK /* rounded to seconds */
00155    if (millisecs < 1000)
00156       millisecs = 1000;
00157    sleep(millisecs/1000);
00158 #elif XMLBLASTER_SLEEP_NANO
00159    TODO:
00160    int nanosleep(const struct timespec *rqtp,  struct  timespec *rmtp);
00161    struct timespec
00162    {
00163             time_t  tv_sec;         /* seconds */
00164             long    tv_nsec;        /* nanoseconds */
00165    };
00166    /*
00167    usleep()  deprecated
00168    */
00169    /*
00170    #include <time.h>
00171    void Sleep(clock_t wait)
00172    {
00173           clock_t goal;
00174           goal = wait * (CLOCKS_PER_SEC / 1000);
00175           while( goal >=  clock())
00176                   ;
00177    }
00178    */   
00179 #else
00180    fd_set dummy;
00181    struct timeval toWait;
00182    int ret;
00183 
00184    FD_ZERO(&dummy);
00185    toWait.tv_sec = millisecs / 1000;
00186    toWait.tv_usec = (millisecs % 1000) * 1000;
00187 
00188    ret = select(0, &dummy, NULL, NULL, &toWait);
00189    if (ret == -1) {
00190       printf("[helper.c] ERROR: sleepMillis(%ld) returned errnor %d", millisecs, errno);
00191    }
00192 #endif
00193 }
00194 
00199 Dll_Export int64_t getTimestamp() {
00200    struct timespec abstime;
00201    int64_t timestamp;
00202    static int64_t lastNanos=0;
00203 
00204    getAbsoluteTime(0L, &abstime);
00205    
00206    timestamp = (int64_t)abstime.tv_sec * NANO_SECS_PER_SECOND;
00207    timestamp += abstime.tv_nsec;
00208    if (timestamp <= lastNanos) {
00209       timestamp = lastNanos + 1;
00210    }
00211    lastNanos = timestamp;
00212    return timestamp;
00213 }
00214 
00215 
00216 #include <wchar.h>
00224 Dll_Export char **convertWcsArgv(wchar_t **argv_wcs, int argc) {
00225    int i;
00226    char **argv = (char **)malloc(argc*sizeof(char*));
00227    for (i=0; i<argc; i++) {
00228       int sizeInBytes = 4*(int)wcslen(argv_wcs[i]);
00229       argv[i] = (char *)malloc(sizeInBytes*sizeof(char));
00230 #     if _MSC_VER >= 1400 && !defined(WINCE)
00231        {
00232          size_t pReturnValue;
00233          /*errno_t err = */
00234          wcstombs_s(&pReturnValue, argv[i], sizeInBytes, argv_wcs[i], _TRUNCATE);
00235        }
00236 #     else
00237          wcstombs(argv[i], argv_wcs[i], sizeInBytes);
00238 #     endif
00239      /*printf("%s ", argv[i]);*/
00240    }
00241    return argv;
00242 }
00243 
00249 Dll_Export void freeArgv(char **argv, int argc) {
00250    int i;
00251    if (argv == 0) return;
00252    for (i=0; i<argc; i++) {
00253       free(argv[i]);
00254    }
00255    free(argv);
00256 }
00257 
00266 Dll_Export bool getAbsoluteTime(long relativeTimeFromNow, struct timespec *abstime)
00267 {
00268 # if defined(WINCE)
00269    /* Copied from pthreads_win32: thank you! */
00270    FILETIME ft;
00271    SYSTEMTIME st;
00272    GetSystemTime(&st);
00273    SystemTimeToFileTime(&st, &ft);
00274    /*
00275     * GetSystemTimeAsFileTime(&ft); would be faster,
00276     * but it does not exist on WinCE
00277     */
00278      /*
00279       * -------------------------------------------------------------------
00280       * converts FILETIME (as set by GetSystemTimeAsFileTime), where the time is
00281       * expressed in 100 nanoseconds from Jan 1, 1601,
00282       * into struct timespec
00283       * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
00284       * -------------------------------------------------------------------
00285       */
00286    abstime->tv_sec =
00287     (int) ((*(LONGLONG *) &ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
00288    abstime->tv_nsec =
00289     (int) ((*(LONGLONG *) &ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET -
00290             ((LONGLONG) abstime->tv_sec * (LONGLONG) 10000000)) * 100);
00291 
00292    if (relativeTimeFromNow > 0) {
00293       abstime->tv_sec += relativeTimeFromNow / 1000;
00294       abstime->tv_nsec += (relativeTimeFromNow % 1000) * 1000 * 1000;
00295    }
00296    if (abstime->tv_nsec >= NANO_SECS_PER_SECOND) {
00297       abstime->tv_nsec -= NANO_SECS_PER_SECOND;
00298       abstime->tv_sec += 1;
00299    }
00300    return true;
00301 
00302 # elif defined(_WINDOWS)
00303    struct _timeb tm;
00304 #  if _MSC_VER >= 1400  /* _WINDOWS: 1200->VC++6.0, 1310->VC++7.1 (2003), 1400->VC++8.0 (2005) */
00305       errno_t err = _ftime_s(&tm);
00306       if (err) return false;
00307 #  else
00308       (void) _ftime(&tm);
00309 #  endif
00310 
00311    abstime->tv_sec = (long)tm.time;
00312    abstime->tv_nsec = tm.millitm * 1000 * 1000; /* TODO !!! How to get the more precise current time on Win? */
00313 
00314    if (relativeTimeFromNow > 0) {
00315       abstime->tv_sec += relativeTimeFromNow / 1000;
00316       abstime->tv_nsec += (relativeTimeFromNow % 1000) * 1000 * 1000;
00317    }
00318    if (abstime->tv_nsec >= NANO_SECS_PER_SECOND) {
00319       abstime->tv_nsec -= NANO_SECS_PER_SECOND;
00320       abstime->tv_sec += 1;
00321    }
00322    return true;
00323 # else /* LINUX, __sun */
00324    struct timeval tv;
00325 
00326    memset(abstime, 0, sizeof(struct timespec));
00327 
00328    gettimeofday(&tv, 0);
00329    abstime->tv_sec = tv.tv_sec;
00330    abstime->tv_nsec = tv.tv_usec * 1000;  /* microseconds to nanoseconds */
00331 
00332    if (relativeTimeFromNow > 0) {
00333       abstime->tv_sec += relativeTimeFromNow / 1000;
00334       abstime->tv_nsec += (relativeTimeFromNow % 1000) * 1000 * 1000;
00335    }
00336    if (abstime->tv_nsec >= NANO_SECS_PER_SECOND) {
00337       abstime->tv_nsec -= NANO_SECS_PER_SECOND;
00338       abstime->tv_sec += 1;
00339    }
00340    return true;
00341 # endif
00342 # ifdef MORE_REALTIME
00343    clock_gettime(CLOCK_REALTIME, abstime);
00344 
00345    if (relativeTimeFromNow > 0) {
00346       abstime->tv_sec += relativeTimeFromNow / 1000;
00347       abstime->tv_nsec += (relativeTimeFromNow % 1000) * 1000 * 1000;
00348    }
00349    if (abstime->tv_nsec >= NANO_SECS_PER_SECOND) {
00350       abstime->tv_nsec -= NANO_SECS_PER_SECOND;
00351       abstime->tv_sec += 1;
00352    }
00353    return true;
00354 # endif
00355 }
00356 
00363 Dll_Export char *strcpyAlloc(const char *src)
00364 {
00365    char *dest;
00366    size_t len;
00367    if (src == 0) return (char *)0;
00368    len = strlen(src) + 1;
00369    dest = (char *)malloc(len*sizeof(char));
00370    if (dest == 0) return 0;
00371    strncpy0(dest, src, len);
00372    return dest;
00373 }
00374 
00379 Dll_Export char *strcatAlloc(char **dest, const char *src)
00380 {
00381    size_t len;
00382    assert(dest != 0);
00383    if (src == 0) return (char *)0;
00384    len = strlen(src)+strlen(*dest)+1;
00385    (*dest) = (char *)realloc(*dest, len*sizeof(char));
00386    if ((*dest) == 0) return 0;
00387    strncat0((*dest), src, len);
00388    return (*dest);
00389 }
00390 
00396 Dll_Export char *strcpyRealloc(char **dest, const char *src)
00397 {
00398    if (*dest != 0)
00399       free(*dest);
00400    *dest = strcpyAlloc(src);
00401    return *dest;
00402 }
00403 
00410 Dll_Export char *strFromBlobAlloc(const char *blob, const size_t len)
00411 {
00412    char *dest;
00413    size_t i;
00414    if (blob == 0 || len < 1) {
00415       dest = (char *)malloc(1*sizeof(char));
00416       if (dest == 0) return 0;
00417       *dest = 0;
00418       return dest;
00419    }
00420 
00421    dest = (char *)malloc((len+1)*sizeof(char));
00422    if (dest == 0) return 0;
00423    for (i=0; i<len; i++) {
00424       dest[i] = (char)blob[i];
00425    }
00426    dest[len] = '\0';
00427    return dest;
00428 }
00429 
00430 
00437 Dll_Export void xb_strerror(char *errnoStr, size_t sizeInBytes, int errnum) {
00438    snprintf0(errnoStr, sizeInBytes, "%d", errnum); /* default if string lookup fails */
00439 #  if defined(WINCE)
00440 #  elif _MSC_VER >= 1400
00441       strerror_s(errnoStr, sizeInBytes, errnum);  
00442 #  elif defined(_LINUX)
00443       strerror_r(errnum, errnoStr, sizeInBytes-1); /* glibc > 2. returns a char*, but should return an int */
00444 #  else
00445       {
00446          char *p = strerror(errnum);
00447          strncpy0(errnoStr, p, sizeInBytes);
00448       }
00449 #  endif
00450 }
00451 
00452 
00461 Dll_Export char *strncpy0(char * const to, const char * const from, const size_t maxLen)
00462 {
00463 #  if defined(WINCE)
00464       char *ret=strncpy(to, from, maxLen-1);
00465       *(to+maxLen-1) = '\0';
00466       return ret;
00467 #  elif _MSC_VER >= 1400
00468 /* errno_t strncpy_s(
00469    char *strDest,
00470    size_t sizeInBytes,
00471    const char *strSource,
00472    size_t count
00473 ); */
00474       errno_t ee = strncpy_s(to, maxLen, from, _TRUNCATE); /*maxLen);*/
00475       return to;
00476 #  else /* MAC OSX calls it strlcpy() */
00477       char *ret=strncpy(to, from, maxLen-1);
00478       *(to+maxLen-1) = '\0';
00479       return ret;
00480 #  endif
00481 }
00482 
00483 
00491 Dll_Export char *strncat0(char * const to, const char * const from, const size_t max)
00492 {
00493 #  if _MSC_VER >= 1400 && !defined(WINCE)
00494       /* buffersize of 'to' in bytes */ 
00495       size_t bufferSizeInBytes = strlen(to) + max;
00496       errno_t ee = strncat_s(to, bufferSizeInBytes, from, _TRUNCATE);
00497       return to;
00498 #  else /* MAC OSX calls it strlcat() */
00499       int oldLen = strlen(to);
00500       char *ret=strncat(to, from, max-1);
00501       *(to+oldLen+max-1) = '\0';
00502       return ret;
00503 #  endif
00504 }
00505 
00506 int vsnprintf0(char *s, size_t size, const char *format, va_list ap) {
00507 #  if _MSC_VER >= 1400 && !defined(WINCE)
00508       errno_t err = vsnprintf_s(s, size, _TRUNCATE, format, ap);
00509       if ( err == STRUNCATE ) {
00510          printf("truncation occurred %s!\n", format);
00511          return 0;
00512       }
00513       return err;
00514 #  elif defined(_WINDOWS)
00515       return _vsnprintf(s, size, format, ap);
00516 #  else
00517       return vsnprintf(s, size, format, ap);
00518 #  endif
00519 }
00520 
00524 Dll_Export int snprintf0(char *buffer, size_t sizeOfBuffer, const char *format, ...) {
00525    int ret;
00526    va_list ap;
00527    va_start (ap, format);
00528    ret = vsnprintf0(
00529          buffer,
00530          sizeOfBuffer,
00531          format,
00532          ap);
00533    va_end (ap);
00534    return ret;
00535 }
00536 
00540 Dll_Export void trim(char *s)
00541 {
00542    size_t first=0;
00543    size_t len;
00544    int i;
00545    
00546    if (s == (char *)0) return;
00547 
00548    len = strlen((char *) s);
00549 
00550    {  /* find beginning of text */
00551       while (first<len) {
00552          if (!isspace((unsigned char)s[first]))
00553             break;
00554          first++;
00555       }
00556    }
00557 
00558    if (first>=len) {
00559       *s = '\0';
00560       return;
00561    }
00562    else
00563       memmove((char *) s, (char *) s+first, strlen(s+first)+1); /* including '\0' */
00564 
00565    for (i=(int)strlen((char *) s)-1; i >= 0; i--)
00566       if (!isspace((unsigned char)s[i])) {
00567          s[i+1] = '\0';
00568          return;
00569       }
00570    if (i<0) *s = '\0';
00571 }
00572 
00576 Dll_Export void trimStart(char *s)
00577 {
00578    size_t first=0;
00579    size_t len;
00580    
00581    if (s == (char *)0) return;
00582 
00583    len = strlen((char *) s);
00584 
00585    {  /* find beginning of text */
00586       while (first<len) {
00587          if (!isspace((unsigned char)s[first]))
00588             break;
00589          first++;
00590       }
00591    }
00592 
00593    if (first>=len) {
00594       *s = '\0';
00595       return;
00596    }
00597    else
00598       memmove((char *) s, (char *) s+first, strlen(s+first)+1); /* including '\0' */
00599 }
00600 
00604 Dll_Export void trimEnd(char *s)
00605 {
00606    int i;
00607    for (i=(int)strlen((char *) s)-1; i >= 0; i--)
00608       if (!isspace((unsigned char)s[i])) {
00609          s[i+1] = '\0';
00610          return;
00611       }
00612    if (i<0) *s = '\0';
00613 }
00614 
00623 Dll_Export char *toReadableDump(char *data, size_t len)
00624 {
00625    char *readable;
00626    size_t i;
00627    if (data == 0) {
00628       return (char *)0;
00629    }
00630    readable = (char *)malloc((len+1) * sizeof(char));
00631    if (readable == (char *)0) return (char *)0;
00632    for (i=0; i<len; i++) {
00633       if (data[i] == '\0')
00634          readable[i] = '*';
00635       else
00636          readable[i] = data[i];
00637    }
00638    readable[len] = '\0';
00639    return readable;
00640 }
00641 
00642 #if defined(XB_USE_PTHREADS)
00643 
00648 long get_pthread_id(pthread_t t)
00649 {
00650 #  ifdef _WINDOWS
00651    return (long)t.p; /* typedef ptw32_handle_t pthread_t; with struct {void*p; unsigned int x;} */
00652 #  else
00653    return (long)t;
00654 #  endif
00655 }
00656 #endif
00657 
00663 Dll_Export void getCurrentTimeStr(char *timeStr, int bufSize) {
00664 #  if defined(WINCE)
00665       /*http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcekernl/html/_wcesdk_win32_systemtime_str.asp*/
00666       SYSTEMTIME st;
00667       GetSystemTime(&st);
00668       snprintf0(timeStr, bufSize, "%hd:%hd:%hd\n", st.wHour, st.wMinute, st.wSecond);
00669       /*wDay, wMilliseconds etc. */
00670 #  elif _MSC_VER >= 1400
00671       /*__time64_t timer;
00672       _time64(&timer);*/
00673       time_t t1; /* unsigned long */
00674       (void) time(&t1); /* in seconds since the Epoch. 1970 */
00675       ctime_s(timeStr, bufSize-1, &t1);
00676 #  elif defined(_WINDOWS)
00677       time_t t1; /* unsigned long */
00678       (void) time(&t1);
00679       strncpy0(timeStr, ctime(&t1), bufSize);
00680 #  elif defined(__sun)
00681       time_t t1; /* unsigned long */
00682       (void) time(&t1);
00683       ctime_r(&t1, (char *)timeStr, bufSize-1);
00684 #  else
00685       time_t t1; /* unsigned long */
00686       (void) time(&t1);
00687       ctime_r(&t1, (char *)timeStr);
00688 #  endif
00689    *(timeStr + strlen(timeStr) - 1) = '\0'; /* strip \n */
00690 }
00691 
00710 Dll_Export void xmlBlasterDefaultLogging(void *logUserP, XMLBLASTER_LOG_LEVEL currLevel,
00711                               XMLBLASTER_LOG_LEVEL level,
00712                               const char *location, const char *fmt, ...)
00713 {
00714    /* Guess, we need no more than 200 bytes. */
00715    int n, size = 200;
00716    char *p = 0;
00717    va_list ap;
00718    char *stackTrace = 0;
00719 #  ifdef _WINDOWS
00720    const char * const * logText = LOG_TEXT;
00721 #  else
00722    const char * const * logText = LOG_TEXT_ESCAPE;
00723 #  endif
00724    if (logUserP) {}  /* To avoid "logUserP was never referenced" compiler warning */
00725 
00726    if (level > currLevel) {
00727       return;
00728    }
00729    if ((p = (char *)malloc (size)) == NULL)
00730       return;
00731 
00732    if (level <= XMLBLASTER_LOG_ERROR) {
00733       stackTrace = getStackTrace(10);
00734    }
00735 
00736    for (;;) {
00737       /* Try to print in the allocated space. */
00738       va_start(ap, fmt);
00739       n = vsnprintf0(p, size, fmt, ap);
00740       va_end(ap);
00741       /* If that worked, print the string to console. */
00742       if (n > -1 && n < size) {
00743        enum { SIZE=128 };
00744          char timeStr[SIZE];
00745          getCurrentTimeStr(timeStr, SIZE);
00746 #        if XB_USE_PTHREADS
00747             printf("[%s %s %s thread0x%lx] %s %s\n", timeStr, logText[level], location,
00748                                     get_pthread_id(pthread_self()), p,
00749                                     (stackTrace != 0) ? stackTrace : "");
00750 #        else
00751             printf("[%s %s %s] %s %s\n", timeStr, logText[level], location, p,
00752                                     (stackTrace != 0) ? stackTrace : "");
00753 #        endif
00754          free(p);
00755          free(stackTrace);
00756          return;
00757       }
00758       /* Else try again with more space. */
00759       if (n > -1)    /* glibc 2.1 */
00760          size = n+1; /* precisely what is needed */
00761       else           /* glibc 2.0 */
00762          size *= 2;  /* twice the old size */
00763       if ((p = (char *)realloc (p, size)) == NULL) {
00764          free(stackTrace);
00765          return;
00766       }
00767    }
00768 }
00769 
00776 Dll_Export XMLBLASTER_LOG_LEVEL parseLogLevel(const char *logLevelStr)
00777 {
00778    int i;
00779    int len = numLOG_TEXT;
00780    if (logLevelStr == 0 || *logLevelStr == '\0' ) {
00781       return XMLBLASTER_LOG_WARN;
00782    }
00783    for (i=0; i<len; i++) {
00784 #     ifdef _WINDOWS
00785       if (!strcmp(LOG_TEXT[i], logLevelStr)) {
00786 #     else
00787       if (!strcasecmp(LOG_TEXT[i], logLevelStr)) {
00788 #     endif
00789          return (XMLBLASTER_LOG_LEVEL)i;
00790       }
00791    }
00792    if (strToInt(&i, logLevelStr) == 1)
00793       return (XMLBLASTER_LOG_LEVEL)i;
00794    return XMLBLASTER_LOG_WARN;
00795 }
00796 
00800 Dll_Export const char *getLogLevelStr(XMLBLASTER_LOG_LEVEL logLevel)
00801 {
00802    return LOG_TEXT[logLevel];
00803 }
00804 
00811 Dll_Export _INLINE_FUNC bool doLog(XMLBLASTER_LOG_LEVEL currLevel, XMLBLASTER_LOG_LEVEL level)
00812 {
00813    return (currLevel <= level) ? true : false;
00814 }
00815 
00822 Dll_Export void embedException(ExceptionStruct *exception, const char *newErrorCode, const char *newMessage, const ExceptionStruct *embed)
00823 {
00824    char embedStr[EXCEPTIONSTRUCT_MESSAGE_LEN];
00825    char newErrorCodeTmp[EXCEPTIONSTRUCT_ERRORCODE_LEN];
00826    char message[EXCEPTIONSTRUCT_MESSAGE_LEN];
00827 
00828    strncpy0(newErrorCodeTmp, newErrorCode, EXCEPTIONSTRUCT_ERRORCODE_LEN); /* Make temporary copy in case the memory overlaps */
00829    if (*embed->errorCode != 0) {
00830       SNPRINTF(message, EXCEPTIONSTRUCT_MESSAGE_LEN, "%s {Root cause: %s}", newMessage, getExceptionStr(embedStr, EXCEPTIONSTRUCT_MESSAGE_LEN, embed));
00831    }
00832    else {
00833       SNPRINTF(message, EXCEPTIONSTRUCT_MESSAGE_LEN, "%s", newMessage);
00834    }
00835    strncpy0(exception->message, message, EXCEPTIONSTRUCT_MESSAGE_LEN);
00836    strncpy0(exception->errorCode, newErrorCodeTmp, EXCEPTIONSTRUCT_ERRORCODE_LEN);
00837 }
00838 
00843 Dll_Export void initializeExceptionStruct(ExceptionStruct *exception)
00844 {
00845    exception->remote = false;
00846    *exception->errorCode = (char)0;
00847    *exception->message = (char)0;
00848 }
00849 
00861 Dll_Export const char *getExceptionStr(char *out, int outSize, const ExceptionStruct *exception)
00862 {
00863    SNPRINTF(out, outSize, "[%s] %s", exception->errorCode, exception->message);
00864    return out;
00865 }
00866 
00874 Dll_Export const char* int64ToStr(char * const buf, int64_t val)
00875 {
00876    if (buf == 0) return 0;
00877    *buf = 0;
00878    /* SNPRINTF(buf, INT64_STRLEN_MAX, "%lld", val);  The normal sprintf should be safe enough */
00879    snprintf0(buf, INT64_STRLEN_MAX, PRINTF_PREFIX_INT64_T, val);  /* Returns number of written chars */
00880    return buf;
00881 }
00882 
00891 Dll_Export bool strToInt64(int64_t *val, const char * const str)
00892 {
00893    if (str == 0 || val == 0) return false;
00894    /*str[INT64_STRLEN_MAX-1] = 0; sscanf should be safe enough to handle overflow */
00895         /* %lld on UNIX, %I64d on Windows */
00896 #  if _MSC_VER >= 1400 && !defined(WINCE)
00897    return (sscanf_s(str, PRINTF_PREFIX_INT64_T, val) == 1) ? true : false;
00898 #  else
00899    return (sscanf(str, PRINTF_PREFIX_INT64_T, val) == 1) ? true : false;
00900 #  endif
00901 }
00902 
00903 Dll_Export bool strToLong(long *val, const char * const str)
00904 {
00905    if (str == 0 || val == 0) return false;
00906    {
00907       int64_t tmp;
00908       bool ret = strToInt64(&tmp, str);
00909       if (ret == false) return false;
00910       *val = (long)tmp;
00911       return true;
00912    }
00913 }
00914 
00915 Dll_Export bool strToInt(int *val, const char * const str)
00916 {
00917    if (str == 0 || val == 0) return false;
00918    {
00919       int64_t tmp;
00920       bool ret = strToInt64(&tmp, str);
00921       if (ret == false) return false;
00922       *val = (int)tmp;
00923       return true;
00924    }
00925 }
00926 
00927 Dll_Export bool strToULong(unsigned long *val, const char * const str)
00928 {
00929    if (str == 0 || val == 0) return false;
00930 #  if _MSC_VER >= 1400 && !defined(WINCE)
00931    return (sscanf_s(str, "%lu", val) == 1) ? true : false;
00932 #  else
00933    return (sscanf(str, "%lu", val) == 1) ? true : false;
00934 #  endif
00935 }
00936 
00937 
00945 Dll_Export BlobHolder *blobcpyAlloc(BlobHolder *blob, const char *data, size_t dataLen)
00946 {
00947    if (blob == 0) {
00948       blob = (BlobHolder *)calloc(1, sizeof(BlobHolder));
00949       if (blob == 0) return blob;
00950    }
00951    blob->dataLen = dataLen;
00952    blob->data = (char *)malloc((dataLen+1)*sizeof(char));
00953    if (blob->data == 0) {
00954       free(blob);
00955       return (BlobHolder *)0;
00956    }
00957    *(blob->data + dataLen) = 0;
00958    memcpy(blob->data, data, dataLen);
00959    return blob;
00960 }
00961 
00967 Dll_Export BlobHolder *freeBlobHolderContent(BlobHolder *blob)
00968 {
00969    if (blob == 0) return 0;
00970    if (blob->data != 0) {
00971       free(blob->data);
00972       blob->data = 0;
00973       blob->dataLen = 0;
00974    }
00975    return blob;
00976 }
00977 
00984 Dll_Export char *blobDump(BlobHolder *blob)
00985 {
00986    return toReadableDump(blob->data, blob->dataLen);
00987 }
00988 
00989 Dll_Export void freeBlobDump(char *blobDump)
00990 {
00991    free(blobDump);
00992 }
00993 
00994 # ifdef HELPER_UTIL_MAIN
00995 /* 
00996  * gcc -g -Wall -DHELPER_UTIL_MAIN=1 -I../../ -o helper helper.c -I../
00997  */
00998 int main()
00999 {
01000    const long millisecs = 500;
01001    const int currLevel = 3;
01002    const char *location = __FILE__;
01003    const char *p = "OOOO";
01004    int i = 3;
01005    xmlBlasterDefaultLogging(0, currLevel, XMLBLASTER_LOG_WARN, location, "%s i=%d\n", p, i);
01006 
01007    printf("Sleeping now for %ld millis\n", millisecs);
01008    sleepMillis(millisecs);
01009    printf("Waiking up after %ld millis\n", millisecs);
01010 
01011    {
01012       const char *ptr = "     28316";
01013       char tr[20];
01014       strncpy0(tr, ptr, 20);
01015       trim(tr);
01016       printf("Before '%s' after '%s'\n", ptr, tr);
01017    }
01018    {
01019       const char *ptr = "     28316  ";
01020       char tr[20];
01021       strncpy0(tr, ptr, 20);
01022       trim(tr);
01023       printf("Before '%s' after '%s'\n", ptr, tr);
01024    }
01025    {
01026       ExceptionStruct ex;
01027       strncpy0(ex.errorCode, "Original.cause", EXCEPTIONSTRUCT_ERRORCODE_LEN);
01028       strncpy0(ex.message, "Original message", EXCEPTIONSTRUCT_MESSAGE_LEN);
01029       embedException(&ex, "new.cause", "new message", &ex);
01030       printf("errorCode=%s message=%s\n", ex.errorCode, ex.message);
01031    }
01032    return 0;
01033 }
01034 # endif