| author | Borja Ferrer <faluco@alliedmods.net> |
| Fri Jan 12 23:56:02 2007 +0000 (2007-01-12) | |
| changeset 288 | d89bf250dac4 |
| parent 276 | 065d151c41b2 |
| child 351 | 7c219cde57e7 |
| permissions | -rw-r--r-- |
1 #include <stdlib.h>
2 #include <ctype.h>
3 #include <stdarg.h>
4 #include "sm_stringutil.h"
5 #include "CLogger.h"
7 #define LADJUST 0x00000004 /* left adjustment */
8 #define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */
9 #define to_digit(c) ((c) - '0')
10 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
12 #define CHECK_ARGS(x) \
13 if ((arg+x) > args) { \
14 g_Logger.LogError("String formatted incorrectly - parameter %d (total %d)", arg, args); \
15 return 0; \
16 }
18 //:TODO: review this code before we choose a license
20 void AddString(char **buf_p, size_t &maxlen, const char *string, int width, int prec)
21 {
22 int size = 0;
23 char *buf;
24 static char nlstr[] = {'(','n','u','l','l',')','\0'};
26 buf = *buf_p;
28 if (string == NULL)
29 {
30 string = nlstr;
31 prec = -1;
32 }
34 if (prec >= 0)
35 {
36 for (size = 0; size < prec; size++)
37 {
38 if (string[size] == '\0')
39 {
40 break;
41 }
42 }
43 } else {
44 while (string[size++]);
45 size--;
46 }
48 if (size > (int)maxlen)
49 {
50 size = maxlen;
51 }
53 maxlen -= size;
54 width -= size;
56 while (size--)
57 {
58 *buf++ = *string++;
59 }
61 while ((width-- > 0) && maxlen)
62 {
63 *buf++ = ' ';
64 maxlen--;
65 }
67 *buf_p = buf;
68 }
70 void AddFloat(char **buf_p, size_t &maxlen, double fval, int width, int prec)
71 {
72 char text[32];
73 int digits;
74 double signedVal;
75 char *buf;
76 int val;
78 // get the sign
79 signedVal = fval;
80 if (fval < 0)
81 {
82 fval = -fval;
83 }
85 // write the float number
86 digits = 0;
87 val = (int)fval;
88 do
89 {
90 text[digits++] = '0' + val % 10;
91 val /= 10;
92 } while (val);
94 if (signedVal < 0)
95 {
96 text[digits++] = '-';
97 }
99 buf = *buf_p;
101 while ((digits < width) && maxlen)
102 {
103 *buf++ = ' ';
104 width--;
105 maxlen--;
106 }
108 while ((digits--) && maxlen)
109 {
110 *buf++ = text[digits];
111 maxlen--;
112 }
114 *buf_p = buf;
116 if (prec < 0)
117 {
118 prec = 6;
119 }
120 // write the fraction
121 digits = 0;
122 while (digits < prec)
123 {
124 fval -= (int)fval;
125 fval *= 10.0;
126 val = (int)fval;
127 text[digits++] = '0' + val % 10;
128 }
130 if ((digits > 0) && maxlen)
131 {
132 buf = *buf_p;
133 *buf++ = '.';
134 maxlen--;
135 for (prec = 0; maxlen && (prec < digits); prec++)
136 {
137 *buf++ = text[prec];
138 maxlen--;
139 }
140 *buf_p = buf;
141 }
142 }
144 void AddUInt(char **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
145 {
146 char text[32];
147 int digits;
148 char *buf;
150 digits = 0;
151 do
152 {
153 text[digits++] = '0' + val % 10;
154 val /= 10;
155 } while (val);
157 buf = *buf_p;
159 if (!(flags & LADJUST))
160 {
161 while (digits < width && maxlen)
162 {
163 *buf++ = (flags & ZEROPAD) ? '0' : ' ';
164 width--;
165 maxlen--;
166 }
167 }
169 while (digits-- && maxlen)
170 {
171 *buf++ = text[digits];
172 width--;
173 maxlen--;
174 }
176 if (flags & LADJUST)
177 {
178 while (width-- && maxlen)
179 {
180 *buf++ = (flags & ZEROPAD) ? '0' : ' ';
181 maxlen--;
182 }
183 }
185 *buf_p = buf;
186 }
188 void AddInt(char **buf_p, size_t &maxlen, int val, int width, int flags)
189 {
190 char text[32];
191 int digits;
192 int signedVal;
193 char *buf;
194 unsigned int unsignedVal;
196 digits = 0;
197 signedVal = val;
198 if (val < 0)
199 {
200 /* we want the unsigned version */
201 unsignedVal = abs(val);
202 } else {
203 unsignedVal = val;
204 }
205 do
206 {
207 text[digits++] = '0' + unsignedVal % 10;
208 unsignedVal /= 10;
209 } while (unsignedVal);
211 if (signedVal < 0)
212 {
213 text[digits++] = '-';
214 }
216 buf = *buf_p;
218 if (!(flags & LADJUST))
219 {
220 while ((digits < width) && maxlen)
221 {
222 *buf++ = (flags & ZEROPAD) ? '0' : ' ';
223 width--;
224 maxlen--;
225 }
226 }
228 while (digits-- && maxlen)
229 {
230 *buf++ = text[digits];
231 width--;
232 maxlen--;
233 }
235 if (flags & LADJUST)
236 {
237 while (width-- && maxlen)
238 {
239 *buf++ = (flags & ZEROPAD) ? '0' : ' ';
240 maxlen--;
241 }
242 }
244 *buf_p = buf;
245 }
247 size_t gnprintf(char *buffer, size_t maxlen, const char *format, void **args)
248 {
249 if (!buffer || !maxlen)
250 {
251 return 0;
252 }
254 int arg = 0;
255 char *buf_p;
256 char ch;
257 int flags;
258 int width;
259 int prec;
260 int n;
261 char sign;
262 const char *fmt;
263 size_t llen = maxlen - 1;
265 buf_p = buffer;
266 fmt = format;
268 while (true)
269 {
270 // run through the format string until we hit a '%' or '\0'
271 for (ch = *fmt; llen && ((ch = *fmt) != '\0') && (ch != '%'); fmt++)
272 {
273 *buf_p++ = ch;
274 llen--;
275 }
276 if ((ch == '\0') || (llen <= 0))
277 {
278 goto done;
279 }
281 // skip over the '%'
282 fmt++;
284 // reset formatting state
285 flags = 0;
286 width = 0;
287 prec = -1;
288 sign = '\0';
290 rflag:
291 ch = *fmt++;
292 reswitch:
293 switch(ch)
294 {
295 case '-':
296 {
297 flags |= LADJUST;
298 goto rflag;
299 }
300 case '.':
301 {
302 n = 0;
303 while(is_digit((ch = *fmt++)))
304 {
305 n = 10 * n + (ch - '0');
306 }
307 prec = (n < 0) ? -1 : n;
308 goto reswitch;
309 }
310 case '0':
311 {
312 flags |= ZEROPAD;
313 goto rflag;
314 }
315 case '1':
316 case '2':
317 case '3':
318 case '4':
319 case '5':
320 case '6':
321 case '7':
322 case '8':
323 case '9':
324 {
325 n = 0;
326 do
327 {
328 n = 10 * n + (ch - '0');
329 ch = *fmt++;
330 } while(is_digit(ch));
331 width = n;
332 goto reswitch;
333 }
334 case 'c':
335 {
336 if (!llen)
337 {
338 goto done;
339 }
340 char *c = (char *)args[arg];
341 *buf_p++ = *c;
342 llen--;
343 arg++;
344 break;
345 }
346 case 'd':
347 case 'i':
348 {
349 int *value = (int *)args[arg];
350 AddInt(&buf_p, llen, *value, width, flags);
351 arg++;
352 break;
353 }
354 case 'u':
355 {
356 unsigned int *value = (unsigned int *)args[arg];
357 AddUInt(&buf_p, llen, *value, width, flags);
358 arg++;
359 break;
360 }
361 case 'f':
362 {
363 float *value = (float *)args[arg];
364 AddFloat(&buf_p, llen, *value, width, prec);
365 arg++;
366 break;
367 }
368 case 's':
369 {
370 const char *str = (const char *)args[arg];
371 AddString(&buf_p, llen, str, width, prec);
372 arg++;
373 break;
374 }
375 case '%':
376 {
377 if (!llen)
378 {
379 goto done;
380 }
381 *buf_p++ = ch;
382 llen--;
383 break;
384 }
385 case '\0':
386 {
387 if (!llen)
388 {
389 goto done;
390 }
391 *buf_p++ = '%';
392 llen--;
393 goto done;
394 }
395 default:
396 {
397 if (!llen)
398 {
399 goto done;
400 }
401 *buf_p++ = ch;
402 llen--;
403 break;
404 }
405 }
406 }
408 done:
409 *buf_p = '\0';
411 return (maxlen - llen - 1);
412 }
414 size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param)
415 {
416 if (!buffer || !maxlen)
417 {
418 return 0;
419 }
421 int arg;
422 int args = params[0];
423 char *buf_p;
424 char ch;
425 int flags;
426 int width;
427 int prec;
428 int n;
429 char sign;
430 const char *fmt;
431 size_t llen = maxlen - 1;
433 buf_p = buffer;
434 arg = *param;
435 fmt = format;
437 while (true)
438 {
439 // run through the format string until we hit a '%' or '\0'
440 for (ch = *fmt; llen && ((ch = *fmt) != '\0') && (ch != '%'); fmt++)
441 {
442 *buf_p++ = ch;
443 llen--;
444 }
445 if ((ch == '\0') || (llen <= 0))
446 {
447 goto done;
448 }
450 // skip over the '%'
451 fmt++;
453 // reset formatting state
454 flags = 0;
455 width = 0;
456 prec = -1;
457 sign = '\0';
459 rflag:
460 ch = *fmt++;
461 reswitch:
462 switch(ch)
463 {
464 case '-':
465 {
466 flags |= LADJUST;
467 goto rflag;
468 }
469 case '.':
470 {
471 n = 0;
472 while(is_digit((ch = *fmt++)))
473 {
474 n = 10 * n + (ch - '0');
475 }
476 prec = (n < 0) ? -1 : n;
477 goto reswitch;
478 }
479 case '0':
480 {
481 flags |= ZEROPAD;
482 goto rflag;
483 }
484 case '1':
485 case '2':
486 case '3':
487 case '4':
488 case '5':
489 case '6':
490 case '7':
491 case '8':
492 case '9':
493 {
494 n = 0;
495 do
496 {
497 n = 10 * n + (ch - '0');
498 ch = *fmt++;
499 } while(is_digit(ch));
500 width = n;
501 goto reswitch;
502 }
503 case 'c':
504 {
505 CHECK_ARGS(0);
506 if (!llen)
507 {
508 goto done;
509 }
510 char *c;
511 pCtx->LocalToString(params[arg], &c);
512 *buf_p++ = *c;
513 llen--;
514 arg++;
515 break;
516 }
517 case 'd':
518 case 'i':
519 {
520 CHECK_ARGS(0);
521 cell_t *value;
522 pCtx->LocalToPhysAddr(params[arg], &value);
523 AddInt(&buf_p, llen, static_cast<int>(*value), width, flags);
524 arg++;
525 break;
526 }
527 case 'u':
528 {
529 CHECK_ARGS(0);
530 cell_t *value;
531 pCtx->LocalToPhysAddr(params[arg], &value);
532 AddUInt(&buf_p, llen, static_cast<unsigned int>(*value), width, flags);
533 arg++;
534 break;
535 }
536 case 'f':
537 {
538 CHECK_ARGS(0);
539 cell_t *value;
540 pCtx->LocalToPhysAddr(params[arg], &value);
541 AddFloat(&buf_p, llen, sp_ctof(*value), width, prec);
542 arg++;
543 break;
544 }
545 case 's':
546 {
547 CHECK_ARGS(0);
548 char *str;
549 pCtx->LocalToString(params[arg], &str);
550 AddString(&buf_p, llen, str, width, prec);
551 arg++;
552 break;
553 }
554 case '%':
555 {
556 if (!llen)
557 {
558 goto done;
559 }
560 *buf_p++ = ch;
561 llen--;
562 break;
563 }
564 case '\0':
565 {
566 if (!llen)
567 {
568 goto done;
569 }
570 *buf_p++ = '%';
571 llen--;
572 goto done;
573 }
574 default:
575 {
576 if (!llen)
577 {
578 goto done;
579 }
580 *buf_p++ = ch;
581 llen--;
582 break;
583 }
584 }
585 }
587 done:
588 *buf_p = '\0';
589 *param = arg;
590 return (maxlen - llen - 1);
591 }
593 const char *stristr(const char *str, const char *substr)
594 {
595 if (!*substr)
596 {
597 return ((char *)str);
598 }
600 char *needle = (char *)substr;
601 char *prevloc = (char *)str;
602 char *haystack = (char *)str;
604 while (*haystack)
605 {
606 if (tolower(*haystack) == tolower(*needle))
607 {
608 haystack++;
609 if (!*++needle)
610 {
611 return prevloc;
612 }
613 } else {
614 haystack = ++prevloc;
615 needle = (char *)substr;
616 }
617 }
619 return NULL;
620 }
622 unsigned int strncopy(char *dest, const char *src, size_t count)
623 {
624 if (!count)
625 {
626 return 0;
627 }
629 char *start = dest;
630 while ((*src) && (--count))
631 {
632 *dest++ = *src++;
633 }
634 *dest = '\0';
636 return (dest - start);
637 }
639 size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
640 {
641 va_list ap;
642 va_start(ap, fmt);
643 size_t len = vsnprintf(buffer, maxlength, fmt, ap);
644 va_end(ap);
646 return (len >= maxlength) ? (maxlength - 1) : len;
647 }