r6981: first version of the builtin web server for Samba4
[samba.git] / source / web_server / ejs / 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        "web_server/ejs/miniMpr.h"
33
34 /************************************ Code ************************************/
35 #if !BLD_APPWEB
36 #if !BLD_GOAHEAD_WEBSERVER
37
38 static TALLOC_CTX *mpr_ctx;
39
40 void mprFreeAll(void)
41 {
42         talloc_free(mpr_ctx);
43         mpr_ctx = NULL;
44 }
45
46 void mprSetCtx(TALLOC_CTX *ctx)
47 {
48         talloc_free(mpr_ctx);
49         mpr_ctx = talloc_new(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         /*
171          *      Optionally break into the debugger here
172          */
173         mprLog(0, "ASSERT at %s:%d, %s\n", file, line, cond);
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 __va_copy
334         __va_copy(ap, args);
335 #else
336         ap = args;
337 #endif
338         addBytes = 0;
339         str = src;
340         while (str) {
341                 addBytes += strlen(str) + sepLen;
342                 str = va_arg(ap, const char*);
343         }
344
345         if (existingLen > 0) {
346                 addBytes += sepLen;
347         }
348         required = existingLen + addBytes + 1;
349         if (required >= destMax) {
350                 mprAssert(0);
351                 return MPR_ERR_WONT_FIT;
352         }
353
354         if (alloc) {
355                 if (dest == 0) {
356                         dest = (char*) mprMalloc(required);
357                 } else {
358                         dest = (char*) mprRealloc(dest, required);
359                 }
360         } else {
361                 dest = (char*) *destp;
362         }
363
364         dp = &dest[existingLen];
365         if (delim) {
366                 strcpy(dp, delim);
367                 dp += sepLen;
368         }
369
370         if (addBytes > 0) {
371 #ifdef __va_copy
372                 __va_copy(ap, args);
373 #else
374                 ap = args;
375 #endif
376                 str = src;
377                 while (str) {
378                         strcpy(dp, str);
379                         dp += strlen(str);
380                         str = va_arg(ap, char*);
381                         if (delim && str) {
382                                 strcpy(dp, delim);
383                                 dp += sepLen;
384                         }
385                 }
386         } else if (dest == 0) {
387                 dest = (char*) mprMalloc(1);
388         } 
389         *dp = '\0';
390
391         *destp = dest;
392         mprAssert(dp < &dest[required]);
393         return required - 1;
394 }
395
396 /*****************************************************************************/
397
398 int mprReallocStrcat(char **destp, int destMax, int existingLen, 
399         const char *delim, const char *src,...)
400 {
401         va_list         ap;
402         int                     rc;
403
404         va_start(ap, src);
405         rc = mprCoreStrcat(1, destp, destMax, existingLen, delim, src, ap);
406         va_end(ap);
407         return rc;
408 }
409
410 /*****************************************************************************/
411 /*
412  *      Return the directory portion of a pathname into the users buffer.
413  */
414
415 int mprGetDirName(char *buf, int bufsize, char *path)
416 {
417         char    *cp;
418         int             dlen;
419
420         mprAssert(path);
421         mprAssert(buf);
422         mprAssert(bufsize > 0);
423
424         cp = strrchr(path, '/');
425         if (cp == 0) {
426 #if WIN
427                 cp = strrchr(path, '\\');
428                 if (cp == 0)
429 #endif
430                 {
431                         buf[0] = '\0';
432                         return 0;
433                 }
434         }
435
436         if (cp == path && cp[1] == '\0') {
437                 strcpy(buf, ".");
438                 return 0;
439         }
440
441         dlen = cp - path;
442         if (dlen < bufsize) {
443                 if (dlen == 0) {
444                         dlen++;
445                 }
446                 mprMemcpy(buf, bufsize, path, dlen);
447                 buf[dlen] = '\0';
448                 return 0;
449         }
450         return MPR_ERR_WONT_FIT;
451 }
452
453 /*****************************************************************************/
454
455 int mprStrcpy(char *dest, int destMax, const char *src)
456 {
457         int             len;
458
459         mprAssert(dest);
460         mprAssert(destMax > 0);
461         mprAssert(src);
462
463         len = strlen(src);
464         if (len >= destMax && len > 0) {
465                 mprAssert(0);
466                 return MPR_ERR_WONT_FIT;
467         }
468         if (len > 0) {
469                 memcpy(dest, src, len);
470                 dest[len] = '\0';
471         } else {
472                 *dest = '\0';
473                 len = 0;
474         } 
475         return len;
476 }
477
478 /*****************************************************************************/
479
480 int mprMemcpy(char *dest, int destMax, const char *src, int nbytes)
481 {
482         mprAssert(dest);
483         mprAssert(destMax > nbytes);
484         mprAssert(src);
485         mprAssert(nbytes > 0);
486
487         if (nbytes > destMax) {
488                 mprAssert(0);
489                 return MPR_ERR_WONT_FIT;
490         }
491         if (nbytes > 0) {
492                 memcpy(dest, src, nbytes);
493                 return nbytes;
494         } else {
495                 return 0;
496         }
497 }
498
499 /*****************************************************************************/
500 #else
501 void miniMprDummy() {}
502 #endif // !BLD_APPWEB && !BLD_GOAHEAD_WEBSERVER
503
504 /*
505  * Local variables:
506  * tab-width: 4
507  * c-basic-offset: 4
508  * End:
509  * vim:tw=78
510  * vim600: sw=4 ts=4 fdm=marker
511  * vim<600: sw=4 ts=4
512  */