util/Properties.c

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------------
00002 Name:      Properties.c
00003 Project:   xmlBlaster.org
00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
00005 Comment:   A tiny helper to encapsulate command line and environment properties
00006 Author:    "Marcel Ruff" <xmlBlaster@marcelruff.info>
00007 Compile:   gcc -DPropertiesMain -D_ENABLE_STACK_TRACE_ -rdynamic -export-dynamic -Wall -pedantic -g -D_REENTRANT -I.. -o PropertiesMain Properties.c
00008 See:       http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.c.socket.html
00009 -----------------------------------------------------------------------------*/
00010 
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <string.h>
00014 /*#include <errno.h>*/
00015 /*#include <sys/types.h>*/
00016 #include "helper.h"
00017 #include "Properties.h"
00018 
00019 static const char *getString(Properties *props, const char *key, const char *defaultValue);
00020 static bool getBool(Properties *props, const char *key, bool defaultValue);
00021 static int getInt(Properties *props, const char *key, int defaultValue);
00022 static long getLong(Properties *props, const char *key, long defaultValue);
00023 static int64_t getInt64(Properties *props, const char *key, int64_t defaultValue);
00024 
00035 Properties *createProperties(int argc, const char* const* argv) {
00036    int iarg;
00037    Properties *props = (Properties *)calloc(1, sizeof(Properties));
00038    props->argc = 0;
00039    props->argv = 0;
00040    props->execName = (argv != 0) ? argv[0] : __FILE__;
00041    props->getString = getString;
00042    props->getBool = getBool;
00043    props->getInt = getInt;
00044    props->getLong = getLong;
00045    props->getInt64 = getInt64;
00046 
00047    if (argc > 1) {
00048       /* strip the executable name and the dash '-' */
00049       props->argc = argc-1;
00050       props->argv = (char **)calloc(props->argc, sizeof(char *));
00051       for (iarg=1; iarg < argc; iarg++) {
00052          if (argv[iarg] == 0 || strlen(argv[iarg]) == 0)
00053             props->argv[iarg-1] = (char *)argv[iarg];
00054          else if ((iarg % 2) == 1 && *argv[iarg] == '-')
00055             props->argv[iarg-1] = (char *)argv[iarg]+1;
00056          else
00057             props->argv[iarg-1] = (char *)argv[iarg];
00058       }
00059    }
00060    return props;
00061 }
00062 
00063 void freeProperties(Properties *props)
00064 {
00065    if (props == 0) return;
00066 
00067    if (props->argc > 0) {
00068       free(props->argv);
00069       props->argc = 0;
00070       props->argv = 0;
00071    }
00072    free(props);
00073 }
00074 
00078 void dumpProperties(Properties *props)
00079 {
00080    int iarg;
00081    if (props == 0) return;
00082 
00083    for (iarg=0; iarg < props->argc-1; iarg++) {
00084       printf("#%d, %s=%s\n", iarg, props->argv[iarg], props->argv[iarg+1]);
00085       iarg++;
00086    }
00087 }
00088 
00092 static const char *getString(Properties *props, const char *key, const char *defaultValue)
00093 {
00094    int iarg;
00095 
00096    if (key == 0) return defaultValue;
00097 
00098    for (iarg=0; iarg < props->argc-1; iarg++) {
00099       if (strcmp(props->argv[iarg], key) == 0)
00100          return props->argv[++iarg];
00101    }
00102    
00103 /*
00104 WIN32
00105    char *pValue;
00106    size_t len;
00107    errno_t err = _dupenv_s( &pValue, &len, "pathext" );
00108    // returns 0 if not found!
00109    if ( err ) return -1;
00110    printf( "pathext = %s\n", pValue );
00111    free( pValue );
00112    err = _dupenv_s( &pValue, &len, "nonexistentvariable" );
00113    if ( err ) return -1;
00114    printf( "nonexistentvariable = %s\n", pValue );
00115    free( pValue ); // It's OK to call free with NULL
00116 
00117    // not thread save as putenv could change
00118    errno_t getenv_s(size_t *pReturnValue, char* buffer, size_t sizeInBytes, const char *varname);
00119 
00120 
00121 UNIX: int getenv_r(const char *name, char *buf, size_t len);
00122    returns -1 if not found
00123 */
00124 #if !defined(WINCE) /* Where is the getenv() for Windows CE? */
00125    {
00126       const char *p = getenv(key);
00127       if (p != 0) return p;
00128    }
00129 #endif
00130 
00131    return defaultValue;
00132 }
00133 
00134 static bool getBool(Properties *props, const char *key, bool defaultValue)
00135 {
00136    const char *valP = getString(props, key, 0);
00137    if (valP != 0) {
00138       if (!strcmp(valP, "false") || !strcmp(valP, "FALSE") || !strcmp(valP, "0"))
00139          return false;
00140       else
00141          return true;
00142    }
00143    return defaultValue;
00144 }
00145 
00146 static int getInt(Properties *props, const char *key, int defaultValue)
00147 {
00148    return (int)getLong(props, key, defaultValue);
00149 }
00150 
00151 static long getLong(Properties *props, const char *key, long defaultValue)
00152 {
00153    const char *valP = getString(props, key, 0);
00154    if (valP != 0) {
00155       long val;
00156       if (strToLong(&val, valP) == true)
00157          return val;
00158    }
00159    return defaultValue;
00160 }
00161 
00162 static int64_t getInt64(Properties *props, const char *key, int64_t defaultValue)
00163 {
00164    const char *valP = getString(props, key, 0);
00165    if (valP != 0) {
00166       int64_t val;
00167       if (strToInt64(&val, valP) == true)
00168          return val;
00169    }
00170    return defaultValue;
00171 }
00172 
00173 #ifdef PropertiesMain /* compile a standalone test program */
00174 
00175 Dll_Export bool strToInt64(int64_t *val, const char * const str) {
00176    if (str == 0 || val == 0) return false;
00177    return (SSCANF(str, PRINTF_PREFIX_INT64_T, val) == 1) ? true : false;
00178 }
00179 
00186 int main(int argc, char** argv)
00187 {
00188    Properties *props = createProperties(argc, (const char* const*)argv);
00189    printf("MY_SETTING=%s\n", props->getString(props, "MY_SETTING", "DUMMY"));
00190    printf("logLevel=%s\n", props->getString(props, "logLevel", "DUMMY"));
00191    printf("isPersistent=%d\n", props->getBool(props, "isPersistent", false));
00192    printf("isDurable=%d\n", props->getBool(props, "isDurable", true));
00193    printf("numTests=%d\n", props->getInt(props, "numTests", -1));
00194    printf("timeout=%ld\n", props->getLong(props, "timeout", -1l));
00195    printf("timeout="PRINTF_PREFIX_INT64_T"\n", props->getInt64(props, "lonLong", -1LL)); /* "%I64d", "%ld", "%lld" */
00196    freeProperties(props);
00197    return 0;
00198 }
00199 #endif /* #ifdef PropertiesMain */
00200