| author | Borja Ferrer <faluco@alliedmods.net> |
| Mon Jan 01 23:14:20 2007 +0000 (2007-01-01) | |
| changeset 258 | 2637fcf24c2f |
| parent 236 | 123045747879 |
| child 274 | 959c85596341 |
| permissions | -rw-r--r-- |
1 #include <stdlib.h>
2 #include <ctype.h>
3 #include "sm_stringutil.h"
5 #define ALT 0x00000001 /* alternate form */
6 #define HEXPREFIX 0x00000002 /* add 0x or 0X prefix */
7 #define LADJUST 0x00000004 /* left adjustment */
8 #define LONGDBL 0x00000008 /* long double */
9 #define LONGINT 0x00000010 /* long integer */
10 #define QUADINT 0x00000020 /* quad integer */
11 #define SHORTINT 0x00000040 /* short integer */
12 #define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */
13 #define FPT 0x00000100 /* floating point number */
14 #define to_digit(c) ((c) - '0')
15 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
16 #define to_char(n) ((n) + '0')
18 //:TODO: fix this macro when we have a debugger
20 #define CHECK_ARGS(n)/* \
21 if ((arg+n) > args) { \
22 LogError(amx, AMX_ERR_PARAMS, "String formatted incorrectly - parameter %d (total %d)", arg, args); \
23 return 0; \
24 }
25 */
27 void AddString(char **buf_p, size_t &maxlen, const char *string, int width, int prec)
28 {
29 int size = 0;
30 char *buf;
31 static char nlstr[] = {'(','n','u','l','l',')','\0'};
33 buf = *buf_p;
35 if (string == NULL)
36 {
37 string = nlstr;
38 prec = -1;
39 }
41 if (prec >= 0)
42 {
43 for (size = 0; size < prec; size++)
44 {
45 if (string[size] == '\0')
46 {
47 break;
48 }
49 }
50 } else {
51 while (string[size++]);
52 size--;
53 }
55 if (size > (int)maxlen)
56 {
57 size = maxlen;
58 }
60 maxlen -= size;
61 width -= size;
63 while (size--)
64 {
65 *buf++ = *string++;
66 }
68 while ((width-- > 0) && maxlen)
69 {
70 *buf++ = ' ';
71 maxlen--;
72 }
74 *buf_p = buf;
75 }
77 void AddFloat(char **buf_p, size_t &maxlen, double fval, int width, int prec)
78 {
79 char text[32];
80 int digits;
81 double signedVal;
82 char *buf;
83 int val;
85 // get the sign
86 signedVal = fval;
87 if (fval < 0)
88 {
89 fval = -fval;
90 }
92 // write the float number
93 digits = 0;
94 val = (int)fval;
95 do
96 {
97 text[digits++] = '0' + val % 10;
98 val /= 10;
99 } while (val);
101 if (signedVal < 0)
102 {
103 text[digits++] = '-';
104 }
106 buf = *buf_p;
108 while ((digits < width) && maxlen)
109 {
110 *buf++ = ' ';
111 width--;
112 maxlen--;
113 }
115 while ((digits--) && maxlen)
116 {
117 *buf++ = text[digits];
118 maxlen--;
119 }
121 *buf_p = buf;
123 if (prec < 0)
124 {
125 prec = 6;
126 }
127 // write the fraction
128 digits = 0;
129 while (digits < prec)
130 {
131 fval -= (int)fval;
132 fval *= 10.0;
133 val = (int)fval;
134 text[digits++] = '0' + val % 10;
135 }
137 if ((digits > 0) && maxlen)
138 {
139 buf = *buf_p;
140 *buf++ = '.';
141 maxlen--;
142 for (prec = 0; maxlen && (prec < digits); prec++)
143 {
144 *buf++ = text[prec];
145 maxlen--;
146 }
147 *buf_p = buf;
148 }
149 }
151 void AddUInt(char **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
152 {
153 char text[32];
154 int digits;
155 char *buf;
157 digits = 0;
158 do
159 {
160 text[digits++] = '0' + val % 10;
161 val /= 10;
162 } while (val);
164 buf = *buf_p;
166 if (!(flags & LADJUST))
167 {
168 while (digits < width && maxlen)
169 {
170 *buf++ = (flags & ZEROPAD) ? '0' : ' ';
171 width--;
172 maxlen--;
173 }
174 }
176 while (digits-- && maxlen)
177 {
178 *buf++ = text[digits];
179 width--;
180 maxlen--;
181 }
183 if (flags & LADJUST)
184 {
185 while (width-- && maxlen)
186 {
187 *buf++ = (flags & ZEROPAD) ? '0' : ' ';
188 maxlen--;
189 }
190 }
192 *buf_p = buf;
193 }
195 void AddInt(char **buf_p, size_t &maxlen, int val, int width, int flags)
196 {
197 char text[32];
198 int digits;
199 int signedVal;
200 char *buf;
201 unsigned int unsignedVal;
203 digits = 0;
204 signedVal = val;
205 if (val < 0)
206 {
207 /* we want the unsigned version */
208 unsignedVal = abs(val);
209 } else {
210 unsignedVal = val;
211 }
212 do
213 {
214 text[digits++] = '0' + unsignedVal % 10;
215 unsignedVal /= 10;
216 } while (unsignedVal);
218 if (signedVal < 0)
219 {
220 text[digits++] = '-';
221 }
223 buf = *buf_p;
225 if (!(flags & LADJUST))
226 {
227 while ((digits < width) && maxlen)
228 {
229 *buf++ = (flags & ZEROPAD) ? '0' : ' ';
230 width--;
231 maxlen--;
232 }
233 }
235 while (digits-- && maxlen)
236 {
237 *buf++ = text[digits];
238 width--;
239 maxlen--;
240 }
242 if (flags & LADJUST)
243 {
244 while (width-- && maxlen)
245 {
246 *buf++ = (flags & ZEROPAD) ? '0' : ' ';
247 maxlen--;
248 }
249 }
251 *buf_p = buf;
252 }
254 size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param)
255 {
256 int arg;
257 //int args = params[0] / sizeof(cell); //:TODO: wrong, i think params[0] has now the param count not the byte count
258 // either way this is only used when the above macro is fixed, until then not needed
259 char *buf_p;
260 char ch;
261 int flags;
262 int width;
263 int prec;
264 int n;
265 char sign;
266 const char *fmt;
267 size_t llen = maxlen - 1;
269 buf_p = buffer;
270 arg = *param;
271 fmt = format;
273 while (true)
274 {
275 // run through the format string until we hit a '%' or '\0'
276 for (ch = *fmt; llen && ((ch = *fmt) != '\0') && (ch != '%'); fmt++)
277 {
278 *buf_p++ = ch;
279 llen--;
280 }
281 if ((ch == '\0') || (llen <= 0))
282 {
283 goto done;
284 }
286 // skip over the '%'
287 fmt++;
289 // reset formatting state
290 flags = 0;
291 width = 0;
292 prec = -1;
293 sign = '\0';
295 rflag:
296 ch = *fmt++;
297 reswitch:
298 switch(ch)
299 {
300 case '-':
301 {
302 flags |= LADJUST;
303 goto rflag;
304 }
305 case '.':
306 {
307 n = 0;
308 while(is_digit((ch = *fmt++)))
309 {
310 n = 10 * n + (ch - '0');
311 }
312 prec = (n < 0) ? -1 : n;
313 goto reswitch;
314 }
315 case '0':
316 {
317 flags |= ZEROPAD;
318 goto rflag;
319 }
320 case '1':
321 case '2':
322 case '3':
323 case '4':
324 case '5':
325 case '6':
326 case '7':
327 case '8':
328 case '9':
329 {
330 n = 0;
331 do
332 {
333 n = 10 * n + (ch - '0');
334 ch = *fmt++;
335 } while(is_digit(ch));
336 width = n;
337 goto reswitch;
338 }
339 case 'c':
340 {
341 CHECK_ARGS(0);
342 if (!llen)
343 {
344 goto done;
345 }
346 char *c;
347 pCtx->LocalToString(params[arg], &c);
348 *buf_p++ = *c;
349 llen--;
350 arg++;
351 break;
352 }
353 case 'd':
354 case 'i':
355 {
356 CHECK_ARGS(0);
357 cell_t *value;
358 pCtx->LocalToPhysAddr(params[arg], &value);
359 AddInt(&buf_p, llen, static_cast<int>(*value), width, flags);
360 arg++;
361 break;
362 }
363 case 'u':
364 {
365 CHECK_ARGS(0);
366 cell_t *value;
367 pCtx->LocalToPhysAddr(params[arg], &value);
368 AddUInt(&buf_p, llen, static_cast<unsigned int>(*value), width, flags);
369 arg++;
370 break;
371 }
372 case 'f':
373 {
374 CHECK_ARGS(0);
375 cell_t *value;
376 pCtx->LocalToPhysAddr(params[arg], &value);
377 AddFloat(&buf_p, llen, sp_ctof(*value), width, prec);
378 arg++;
379 break;
380 }
381 case 's':
382 {
383 CHECK_ARGS(0);
384 char *str;
385 pCtx->LocalToString(params[arg], &str);
386 AddString(&buf_p, llen, str, width, prec);
387 arg++;
388 break;
389 }
390 case '%':
391 {
392 if (!llen)
393 {
394 goto done;
395 }
396 *buf_p++ = ch;
397 llen--;
398 break;
399 }
400 case '\0':
401 {
402 if (!llen)
403 {
404 goto done;
405 }
406 *buf_p++ = '%';
407 llen--;
408 goto done;
409 }
410 default:
411 {
412 if (!llen)
413 {
414 goto done;
415 }
416 *buf_p++ = ch;
417 llen--;
418 break;
419 }
420 }
421 }
423 done:
424 *buf_p = '\0';
425 *param = arg;
426 return (maxlen - llen - 1);
427 }
429 const char *stristr(const char *str, const char *substr)
430 {
431 if (!*substr)
432 {
433 return ((char *)str);
434 }
436 char *needle = (char *)substr;
437 char *prevloc = (char *)str;
438 char *haystack = (char *)str;
440 while (*haystack)
441 {
442 if (tolower(*haystack) == tolower(*needle))
443 {
444 haystack++;
445 if (!*++needle)
446 {
447 return prevloc;
448 }
449 } else {
450 haystack = ++prevloc;
451 needle = (char *)substr;
452 }
453 }
455 return NULL;
456 }
458 unsigned int strncopy(char *dest, const char *src, size_t count)
459 {
460 if (!count)
461 {
462 return 0;
463 }
465 char *start = dest;
466 while ((*src) && (--count))
467 {
468 *dest++ = *src++;
469 }
470 *dest = '\0';
472 return (dest - start);
473 }