1 /*----------------------------------------------------------------------------
2 Name: Properties.c
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Comment: A tiny helper to encapsulate command line and environment properties
6 Author: "Marcel Ruff" <xmlBlaster@marcelruff.info>
7 Compile: gcc -DPropertiesMain -D_ENABLE_STACK_TRACE_ -rdynamic -export-dynamic -Wall -pedantic -g -D_REENTRANT -I.. -o PropertiesMain Properties.c
8 See: http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.c.socket.html
9 -----------------------------------------------------------------------------*/
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 /*#include <errno.h>*/
15 /*#include <sys/types.h>*/
16 #include "helper.h"
17 #include "Properties.h"
18
19 static const char *getString(Properties *props, const char *key, const char *defaultValue);
20 static bool getBool(Properties *props, const char *key, bool defaultValue);
21 static int getInt(Properties *props, const char *key, int defaultValue);
22 static long getLong(Properties *props, const char *key, long defaultValue);
23 static int64_t getInt64(Properties *props, const char *key, int64_t defaultValue);
24 static double getDouble(Properties *props, const char *key, double defaultValue);
25
26 /**
27 * Create an instance of a property struct.
28 * NOTE: Our properties point on the passed argv memory, so you should
29 * not free the original argv memory.
30 * @param argc The number of command line args
31 * @param argv The command line arguments, argv[0] is expected to be the
32 * name of the process, argv[1] should start with '-' and
33 * argv[2] is the value of the argv[1] key ...
34 * argv can be NULL if argc == 0
35 */
36 Properties *createProperties(int argc, const char* const* argv) {
37 int iarg;
38 Properties *props = (Properties *)calloc(1, sizeof(Properties));
39 props->argc = 0;
40 props->argv = 0;
41 props->execName = (argv != 0) ? argv[0] : __FILE__;
42 props->getString = getString;
43 props->getBool = getBool;
44 props->getInt = getInt;
45 props->getLong = getLong;
46 props->getInt64 = getInt64;
47 props->getDouble = getDouble;
48
49 if (argc > 1) {
50 /* strip the executable name and the dash '-' */
51 props->argc = argc-1;
52 props->argv = (char **)calloc((size_t)props->argc, sizeof(char *));
53 for (iarg=1; iarg < argc; iarg++) {
54 if (argv[iarg] == 0 || strlen(argv[iarg]) == 0)
55 props->argv[iarg-1] = (char *)argv[iarg];
56 else if ((iarg % 2) == 1 && *argv[iarg] == '-')
57 props->argv[iarg-1] = (char *)argv[iarg]+1;
58 else
59 props->argv[iarg-1] = (char *)argv[iarg];
60 }
61 }
62 return props;
63 }
64
65 void freeProperties(Properties *props)
66 {
67 if (props == 0) return;
68
69 if (props->argc > 0) {
70 free(props->argv);
71 props->argc = 0;
72 props->argv = 0;
73 }
74 free(props);
75 }
76
77 /**
78 * See header Properties.h for documentation
79 */
80 void dumpProperties(Properties *props)
81 {
82 int iarg;
83 if (props == 0) return;
84
85 for (iarg=0; iarg < props->argc-1; iarg++) {
86 printf("#%d, %s=%s\n", iarg, props->argv[iarg], props->argv[iarg+1]);
87 iarg++;
88 }
89 }
90
91 /**
92 * See header Properties.h for documentation
93 */
94 static const char *getString(Properties *props, const char *key, const char *defaultValue)
95 {
96 int iarg;
97
98 if (props == 0 || key == 0) return defaultValue;
99
100 for (iarg=0; iarg < props->argc-1; iarg++) {
101 if (strcmp(props->argv[iarg], key) == 0)
102 return props->argv[++iarg];
103 }
104
105 /*
106 WIN32
107 char *pValue;
108 size_t len;
109 errno_t err = _dupenv_s( &pValue, &len, "pathext" );
110 // returns 0 if not found!
111 if ( err ) return -1;
112 printf( "pathext = %s\n", pValue );
113 free( pValue );
114 err = _dupenv_s( &pValue, &len, "nonexistentvariable" );
115 if ( err ) return -1;
116 printf( "nonexistentvariable = %s\n", pValue );
117 free( pValue ); // It's OK to call free with NULL
118
119 // not thread save as putenv could change
120 errno_t getenv_s(size_t *pReturnValue, char* buffer, size_t sizeInBytes, const char *varname);
121
122
123 UNIX: int getenv_r(const char *name, char *buf, size_t len);
124 returns -1 if not found
125 */
126 #if !defined(WINCE) /* Where is the getenv() for Windows CE? */
127 {
128 const char *p = getenv(key);
129 if (p != 0) return p;
130 }
131 #endif
132
133 return defaultValue;
134 }
135
136 static bool getBool(Properties *props, const char *key, bool defaultValue)
137 {
138 const char *valP = getString(props, key, 0);
139 if (valP != 0) {
140 if (!strcmp(valP, "false") || !strcmp(valP, "FALSE") || !strcmp(valP, "0"))
141 return false;
142 else
143 return true;
144 }
145 return defaultValue;
146 }
147
148 static int getInt(Properties *props, const char *key, int defaultValue)
149 {
150 return (int)getLong(props, key, defaultValue);
151 }
152
153 static long getLong(Properties *props, const char *key, long defaultValue)
154 {
155 const char *valP = getString(props, key, 0);
156 if (valP != 0) {
157 long val;
158 if (strToLong(&val, valP) == true)
159 return val;
160 }
161 return defaultValue;
162 }
163
164 static int64_t getInt64(Properties *props, const char *key, int64_t defaultValue)
165 {
166 const char *valP = getString(props, key, 0);
167 if (valP != 0) {
168 int64_t val;
169 if (strToInt64(&val, valP) == true)
170 return val;
171 }
172 return defaultValue;
173 }
174
175 static double getDouble(Properties *props, const char *key, double defaultValue)
176 {
177 const char *valP = getString(props, key, 0);
178 if (valP != 0) {
179 double val;
180 if (sscanf(valP, "%lf", &val) == 1)
181 return val;
182 }
183 return defaultValue;
184 }
185
186 #ifdef PropertiesMain /* compile a standalone test program */
187
188 Dll_Export bool strToInt64(int64_t *val, const char * const str) {
189 if (str == 0 || val == 0) return false;
190 return (SSCANF(str, PRINTF_PREFIX_INT64_T, val) == 1) ? true : false;
191 }
192
193 /**
194 * icc -DPropertiesMain -Wall -g -I.. -o PropertiesMain Properties.c
195 * Invoke:
196 * export MY_SETTING="Hello World"
197 * PropertiesMain -logLevel TRACE -numTests 10 -timeout -999 -isPersistent true -isDurable false
198 */
199 int main(int argc, char** argv)
200 {
201 Properties *props = createProperties(argc, (const char* const*)argv);
202 printf("MY_SETTING=%s\n", props->getString(props, "MY_SETTING", "DUMMY"));
203 printf("logLevel=%s\n", props->getString(props, "logLevel", "DUMMY"));
204 printf("isPersistent=%d\n", props->getBool(props, "isPersistent", false));
205 printf("isDurable=%d\n", props->getBool(props, "isDurable", true));
206 printf("numTests=%d\n", props->getInt(props, "numTests", -1));
207 printf("timeout=%ld\n", props->getLong(props, "timeout", -1l));
208 printf("timeout="PRINTF_PREFIX_INT64_T"\n", props->getInt64(props, "lonLong", -1LL)); /* "%I64d", "%ld", "%lld" */
209 freeProperties(props);
210 return 0;
211 }
212 #endif /* #ifdef PropertiesMain */
syntax highlighted by Code2HTML, v. 0.9.1