f4c219fe4c79b75c308e80c60089c6987323497e
[samba.git] / source / lib / appweb / mpr / miniMpr.c
1 /*
2  *      @file   miniMpr.cpp
3  *      @brief  Mini Mbedthis Portable Runtime (MPR)
4  *      @copy   default
5  *      
6  *      Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved.
7  *      
8  *      This software is distributed under commercial and open source licenses.
9  *      You may use the GPL open source license described below or you may acquire 
10  *      a commercial license from Mbedthis Software. You agree to be fully bound 
11  *      by the terms of either license. Consult the LICENSE.TXT distributed with 
12  *      this software for full details.
13  *      
14  *      This software is open source; you can redistribute it and/or modify it 
15  *      under the terms of the GNU General Public License as published by the 
16  *      Free Software Foundation; either version 2 of the License, or (at your 
17  *      option) any later version. See the GNU General Public License for more 
18  *      details at: http://www.mbedthis.com/downloads/gplLicense.html
19  *      
20  *      This program is distributed WITHOUT ANY WARRANTY; without even the 
21  *      implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
22  *      
23  *      This GPL license does NOT permit incorporating this software into 
24  *      proprietary programs. If you are unable to comply with the GPL, you must
25  *      acquire a commercial license to use this software. Commercial licenses 
26  *      for this software and support services are available from Mbedthis 
27  *      Software at http://www.mbedthis.com 
28  *      
29  *      @end
30  */
31
32 #include        "miniMpr.h"
33
34 /************************************ Code ************************************/
35 #if !BLD_APPWEB
36 #if !BLD_GOAHEAD_WEBSERVER
37
38 static void *mpr_ctx;
39
40 /* set the memory context to be used for all ejs variables */
41 void mprSetCtx(TALLOC_CTX *ctx)
42 {
43         mpr_ctx = ctx;
44 }
45
46 /* return the memory context being used for all ejs variables */
47 void *mprMemCtx(void)
48 {
49         return mpr_ctx;
50 }
51
52 void mprFree(void *ptr)
53 {
54         talloc_free(ptr);
55 }
56
57 void *mprMalloc(uint size)
58 {
59         return talloc_size(mpr_ctx, size);
60 }
61
62 /******************************************************************************/
63
64 void *mprRealloc(void *ptr, uint size)
65 {
66         return talloc_realloc_size(mpr_ctx, ptr, size);
67 }
68
69 /******************************************************************************/
70
71 char *mprStrdup(const char *str)
72 {
73         if (str == 0) {
74                 str = "";
75         }
76         return talloc_strdup(mpr_ctx, str);
77 }
78
79 /*****************************************************************************/
80
81 int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...)
82 {
83         va_list args;
84         char    *buf;
85         int             count;
86
87         va_start(args, fmt);
88         buf = mprMalloc(maxSize + 1);
89         count = mtVsprintf(buf, maxSize, fmt, args);
90         *msgbuf = buf;
91         va_end(args);
92         return count;
93 }
94
95 /*****************************************************************************/
96
97 int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, va_list args)
98 {
99         char    *buf;
100         int             count;
101
102         buf = mprMalloc(maxSize + 1);
103         count = mtVsprintf(buf, maxSize, fmt, args);
104         *msgbuf = buf;
105         return count;
106 }
107
108
109 /*****************************************************************************/
110 /*
111  *      Format a number as a string. FUTURE -- reverse args to be standard.
112  *              ie. mprItoa(char *userBuf, int bufsize, int value);
113  */
114
115 char *mprItoa(int value, char *buf, int width)
116 {
117         char    numBuf[16];
118         char    *cp, *dp, *endp;
119         int             negative;
120
121         cp = &numBuf[sizeof(numBuf)];
122         *--cp = '\0';
123
124         if (value < 0) {
125                 negative = 1;
126                 value = -value;
127                 width--;
128         } else {
129                 negative = 0;
130         }
131
132         do {
133                 *--cp = '0' + (value % 10);
134                 value /= 10;
135         } while (value > 0);
136
137         if (negative) {
138                 *--cp = '-';
139         }
140
141         dp = buf;
142         endp = &buf[width];
143         while (dp < endp && *cp) {
144                 *dp++ = *cp++;
145         }
146         *dp++ = '\0';
147         return buf;
148 }
149
150 /*****************************************************************************/
151
152 void mprLog(int level, const char *fmt, ...)
153 {
154         va_list args;
155         char    *buf;
156
157         if (DEBUGLVL(level)) {
158                 va_start(args, fmt);
159                 mprAllocVsprintf(&buf, MPR_MAX_STRING, fmt, args);
160                 va_end(args);
161                 DEBUG(level, ("mprLog: %s", buf));
162                 mprFree(buf);
163         }
164 }
165
166 /*****************************************************************************/
167
168 void mprBreakpoint(const char *file, int line, const char *cond)
169 {
170         char *buf;
171         mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", 
172                                         file, line, cond);
173         ejs_exception(buf);
174 }
175
176 #endif /* !BLD_GOAHEAD_WEBSERVER */
177 /*****************************************************************************/
178 /*
179  *      Create a general growable array structure
180  */
181
182 MprArray *mprCreateArray()
183 {
184         MprArray        *array;
185         int                     size;
186
187         array = (MprArray*) mprMalloc(sizeof(MprArray));
188         if (array == 0) {
189                 return 0;
190         }
191         memset(array, 0, sizeof(MprArray));
192
193         size = MPR_ARRAY_INCR * sizeof(void*);
194         array->handles = (void**) mprMalloc(size);
195         if (array->handles == 0) {
196                 mprFree(array);
197                 return 0;
198         }
199         memset(array->handles, 0, size);
200         array->max = MPR_ARRAY_INCR;
201         array->used = 0;
202         return array;
203 }
204
205 /*****************************************************************************/
206 /*
207  *      Dispose of the array. Callers responsibility to dispose of handle entries.
208  */
209
210 void mprDestroyArray(MprArray *array)
211 {
212         mprAssert(array);
213         mprAssert(array->max >= 0);
214         mprAssert(array->used >= 0);
215
216         mprFree(array->handles);
217         mprFree(array);
218 }
219
220 /*****************************************************************************/
221 /*
222  *      Add an item to the array
223  */
224
225 int mprAddToArray(MprArray *array, void *item)
226 {
227         int             memsize, idx, len;
228
229         mprAssert(array);
230         mprAssert(array->max >= 0);
231         mprAssert(array->used >= 0);
232
233         if (array->used < array->max) {
234                 idx = array->used++;
235                 mprAssert(idx >= 0 && idx < array->max);
236                 mprAssert(array->handles[idx] == 0);
237                 array->handles[idx] = item;
238                 return idx;
239         }
240
241         for (idx = array->used; idx < array->max; idx++) {
242                 if (array->handles[idx] == 0) {
243                         array->used++;
244                         mprAssert(array->handles[idx] == 0);
245                         array->handles[idx] = item;
246                         return idx;
247                 }
248         }
249
250         len = array->max + MPR_ARRAY_INCR;
251         memsize = len * sizeof(void*);
252         array->handles = (void**) mprRealloc((void*) array->handles, memsize);
253         if (array->handles == NULL) {
254                 return -1;
255         }
256         memset(&array->handles[array->max], 0, sizeof(void*) * MPR_ARRAY_INCR);
257         array->max = len;
258         array->used++;
259
260         mprAssert(idx >= 0 && idx < array->max);
261         mprAssert(array->handles[idx] == 0);
262
263         array->handles[idx] = item;
264         return idx;
265 }
266
267 /*****************************************************************************/
268 /*
269  *      Remove from the array
270  */
271
272 int mprRemoveFromArray(MprArray *array, int idx)
273 {
274         mprAssert(array);
275         mprAssert(array->max > 0);
276         mprAssert(idx >= 0 && idx < array->max);
277         mprAssert(array->handles[idx] != 0);
278         mprAssert(array->used > 0);
279
280         array->handles[idx] = 0;
281         return --array->used;
282 }
283
284 /*****************************************************************************/
285 /*
286  *      Thread-safe wrapping of strtok. Note "str" is modifed as per strtok()
287  */
288
289 char *mprStrTok(char *str, const char *delim, char **tok)
290 {
291         char    *start, *end;
292         int             i;
293
294         start = str ? str : *tok;
295
296         if (start == 0) {
297                 return 0;
298         }
299         
300         i = strspn(start, delim);
301         start += i;
302         if (*start == '\0') {
303                 *tok = 0;
304                 return 0;
305         }
306         end = strpbrk(start, delim);
307         if (end) {
308                 *end++ = '\0';
309                 i = strspn(end, delim);
310                 end += i;
311         }
312         *tok = end;
313         return start;
314 }
315
316 /*****************************************************************************/
317
318 static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, 
319         const char *delim, const char *src, va_list args)
320 {
321         va_list         ap;
322         char            *dest, *dp;
323         const char *str;
324         int                     sepLen, addBytes, required;
325
326         mprAssert(destp);
327         mprAssert(destMax > 0);
328         mprAssert(src);
329
330         dest = *destp;
331         sepLen = (delim) ? strlen(delim) : 0;
332
333 #ifdef HAVE_VA_COPY
334         va_copy(ap, args);
335 #elif HAVE___VA_COPY
336         __va_copy(ap, args);
337 #else
338         ap = args;
339 #endif
340         addBytes = 0;
341         str = src;
342         while (str) {
343                 addBytes += strlen(str) + sepLen;
344                 str = va_arg(ap, const char*);
345         }
346         va_end(ap);
347
348         if (existingLen > 0) {
349                 addBytes += sepLen;
350         }
351         required = existingLen + addBytes + 1;
352         if (required >= destMax) {
353                 mprAssert(0);
354                 return MPR_ERR_WONT_FIT;
355         }
356
357         if (alloc) {
358                 if (dest == 0) {
359                         dest = (char*) mprMalloc(required);
360                 } else {
361                         dest = (char*) mprRealloc(dest, required);
362                 }
363         } else {
364                 dest = (char*) *destp;
365         }
366
367         dp = &dest[existingLen];
368         if (delim) {
369                 strcpy(dp, delim);
370                 dp += sepLen;
371         }
372
373         if (addBytes > 0) {
374 #ifdef HAVE_VA_COPY
375                 va_copy(ap, args);
376 #elif HAVE___VA_COPY
377                 __va_copy(ap, args);
378 #else
379                 ap = args;
380 #endif
381                 str = src;
382                 while (str) {
383                         strcpy(dp, str);
384                         dp += strlen(str);
385                         str = va_arg(ap, char*);
386                         if (delim && str) {
387                                 strcpy(dp, delim);
388                                 dp += sepLen;
389                         }
390                 }
391                 va_end(ap);
392         } else if (dest == 0) {
393                 dest = (char*) mprMalloc(1);
394         } 
395         *dp = '\0';
396
397         *destp = dest;
398         mprAssert(dp < &dest[required]);
399         return required - 1;
400 }
401
402 /*****************************************************************************/
403
404 int mprReallocStrcat(char **destp, int destMax, int existingLen, 
405         const char *delim, const char *src,...)
406 {
407         va_list         ap;
408         int                     rc;
409
410         va_start(ap, src);
411         rc = mprCoreStrcat(1, destp, destMax, existingLen, delim, src, ap);
412         va_end(ap);
413         return rc;
414 }
415
416 /*****************************************************************************/
417 /*
418  *      Return the directory portion of a pathname into the users buffer.
419  */
420
421 int mprGetDirName(char *buf, int bufsize, char *path)
422 {
423         char    *cp;
424         int             dlen;
425
426         mprAssert(path);
427         mprAssert(buf);
428         mprAssert(bufsize > 0);
429
430         cp = strrchr(path, '/');
431         if (cp == 0) {
432 #if WIN
433                 cp = strrchr(path, '\\');
434                 if (cp == 0)
435 #endif
436                 {
437                         buf[0] = '\0';
438                         return 0;
439                 }
440         }
441
442         if (cp == path && cp[1] == '\0') {
443                 strcpy(buf, ".");
444                 return 0;
445         }
446
447         dlen = cp - path;
448         if (dlen < bufsize) {
449                 if (dlen == 0) {
450                         dlen++;
451                 }
452                 mprMemcpy(buf, bufsize, path, dlen);
453                 buf[dlen] = '\0';
454                 return 0;
455         }
456         return MPR_ERR_WONT_FIT;
457 }
458
459 /*****************************************************************************/
460
461 int mprStrcpy(char *dest, int destMax, const char *src)
462 {
463         int             len;
464
465         mprAssert(dest);
466         mprAssert(destMax > 0);
467         mprAssert(src);
468
469         len = strlen(src);
470         if (len >= destMax && len > 0) {
471                 mprAssert(0);
472                 return MPR_ERR_WONT_FIT;
473         }
474         if (len > 0) {
475                 memcpy(dest, src, len);
476                 dest[len] = '\0';
477         } else {
478                 *dest = '\0';
479                 len = 0;
480         } 
481         return len;
482 }
483
484 /*****************************************************************************/
485
486 int mprMemcpy(char *dest, int destMax, const char *src, int nbytes)
487 {
488         mprAssert(dest);
489         mprAssert(destMax > nbytes);
490         mprAssert(src);
491         mprAssert(nbytes > 0);
492
493         if (nbytes > destMax) {
494                 mprAssert(0);
495                 return MPR_ERR_WONT_FIT;
496         }
497         if (nbytes > 0) {
498                 memcpy(dest, src, nbytes);
499                 return nbytes;
500         } else {
501                 return 0;
502         }
503 }
504
505 /*****************************************************************************/
506 #else
507 void miniMprDummy() {}
508 #endif // !BLD_APPWEB && !BLD_GOAHEAD_WEBSERVER
509
510 /*
511  * Local variables:
512  * tab-width: 4
513  * c-basic-offset: 4
514  * End:
515  * vim:tw=78
516  * vim600: sw=4 ts=4 fdm=marker
517  * vim<600: sw=4 ts=4
518  */