faluco@230: #include faluco@230: #include faluco@227: #include "sm_stringutil.h" faluco@227: faluco@227: #define ALT 0x00000001 /* alternate form */ faluco@227: #define HEXPREFIX 0x00000002 /* add 0x or 0X prefix */ faluco@227: #define LADJUST 0x00000004 /* left adjustment */ faluco@227: #define LONGDBL 0x00000008 /* long double */ faluco@227: #define LONGINT 0x00000010 /* long integer */ faluco@227: #define QUADINT 0x00000020 /* quad integer */ faluco@227: #define SHORTINT 0x00000040 /* short integer */ faluco@227: #define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */ faluco@227: #define FPT 0x00000100 /* floating point number */ faluco@227: #define to_digit(c) ((c) - '0') faluco@227: #define is_digit(c) ((unsigned)to_digit(c) <= 9) faluco@227: #define to_char(n) ((n) + '0') faluco@227: faluco@227: //:TODO: fix this macro when we have a debugger faluco@227: faluco@227: #define CHECK_ARGS(n)/* \ faluco@227: if ((arg+n) > args) { \ faluco@227: LogError(amx, AMX_ERR_PARAMS, "String formatted incorrectly - parameter %d (total %d)", arg, args); \ faluco@227: return 0; \ faluco@227: } faluco@227: */ faluco@227: faluco@227: void AddString(char **buf_p, size_t &maxlen, const char *string, int width, int prec) faluco@227: { faluco@227: int size = 0; faluco@227: char *buf; faluco@227: static char nlstr[] = {'(','n','u','l','l',')','\0'}; faluco@227: faluco@227: buf = *buf_p; faluco@227: faluco@227: if (string == NULL) faluco@227: { faluco@227: string = nlstr; faluco@227: prec = -1; faluco@227: } faluco@227: faluco@227: if (prec >= 0) faluco@227: { faluco@227: for (size = 0; size < prec; size++) faluco@227: { faluco@227: if (string[size] == '\0') faluco@227: { faluco@227: break; faluco@227: } faluco@227: } faluco@227: } else { faluco@227: while (string[size++]); faluco@227: size--; faluco@227: } faluco@227: faluco@227: if (size > (int)maxlen) faluco@227: { faluco@227: size = maxlen; faluco@227: } faluco@227: faluco@227: maxlen -= size; faluco@227: width -= size; faluco@227: faluco@227: while (size--) faluco@227: { faluco@227: *buf++ = *string++; faluco@227: } faluco@227: faluco@227: while ((width-- > 0) && maxlen) faluco@227: { faluco@227: *buf++ = ' '; faluco@227: maxlen--; faluco@227: } faluco@227: faluco@227: *buf_p = buf; faluco@227: } faluco@227: faluco@227: void AddFloat(char **buf_p, size_t &maxlen, double fval, int width, int prec) faluco@227: { faluco@227: char text[32]; faluco@227: int digits; faluco@227: double signedVal; faluco@227: char *buf; faluco@227: int val; faluco@227: faluco@227: // get the sign faluco@227: signedVal = fval; faluco@227: if (fval < 0) faluco@227: { faluco@227: fval = -fval; faluco@227: } faluco@227: faluco@227: // write the float number faluco@227: digits = 0; faluco@227: val = (int)fval; faluco@227: do faluco@227: { faluco@227: text[digits++] = '0' + val % 10; faluco@227: val /= 10; faluco@227: } while (val); faluco@227: faluco@227: if (signedVal < 0) faluco@227: { faluco@227: text[digits++] = '-'; faluco@227: } faluco@227: faluco@227: buf = *buf_p; faluco@227: faluco@227: while ((digits < width) && maxlen) faluco@227: { faluco@227: *buf++ = ' '; faluco@227: width--; faluco@227: maxlen--; faluco@227: } faluco@227: faluco@227: while ((digits--) && maxlen) faluco@227: { faluco@227: *buf++ = text[digits]; faluco@227: maxlen--; faluco@227: } faluco@227: faluco@227: *buf_p = buf; faluco@227: faluco@227: if (prec < 0) faluco@227: { faluco@227: prec = 6; faluco@227: } faluco@227: // write the fraction faluco@227: digits = 0; faluco@227: while (digits < prec) faluco@227: { faluco@227: fval -= (int)fval; faluco@227: fval *= 10.0; faluco@227: val = (int)fval; faluco@227: text[digits++] = '0' + val % 10; faluco@227: } faluco@227: faluco@227: if ((digits > 0) && maxlen) faluco@227: { faluco@227: buf = *buf_p; faluco@227: *buf++ = '.'; faluco@227: maxlen--; faluco@227: for (prec = 0; maxlen && (prec < digits); prec++) faluco@227: { faluco@227: *buf++ = text[prec]; faluco@227: maxlen--; faluco@227: } faluco@227: *buf_p = buf; faluco@227: } faluco@227: } faluco@227: faluco@227: void AddUInt(char **buf_p, size_t &maxlen, unsigned int val, int width, int flags) faluco@227: { faluco@227: char text[32]; faluco@227: int digits; faluco@227: char *buf; faluco@227: faluco@227: digits = 0; faluco@227: do faluco@227: { faluco@227: text[digits++] = '0' + val % 10; faluco@227: val /= 10; faluco@227: } while (val); faluco@227: faluco@227: buf = *buf_p; faluco@227: faluco@227: if (!(flags & LADJUST)) faluco@227: { faluco@227: while (digits < width && maxlen) faluco@227: { faluco@227: *buf++ = (flags & ZEROPAD) ? '0' : ' '; faluco@227: width--; faluco@227: maxlen--; faluco@227: } faluco@227: } faluco@227: faluco@227: while (digits-- && maxlen) faluco@227: { faluco@227: *buf++ = text[digits]; faluco@227: width--; faluco@227: maxlen--; faluco@227: } faluco@227: faluco@227: if (flags & LADJUST) faluco@227: { faluco@227: while (width-- && maxlen) faluco@227: { faluco@227: *buf++ = (flags & ZEROPAD) ? '0' : ' '; faluco@227: maxlen--; faluco@227: } faluco@227: } faluco@227: faluco@227: *buf_p = buf; faluco@227: } faluco@227: faluco@227: void AddInt(char **buf_p, size_t &maxlen, int val, int width, int flags) faluco@227: { faluco@227: char text[32]; faluco@227: int digits; faluco@227: int signedVal; faluco@227: char *buf; faluco@227: unsigned int unsignedVal; faluco@227: faluco@227: digits = 0; faluco@227: signedVal = val; faluco@227: if (val < 0) faluco@227: { faluco@227: /* we want the unsigned version */ faluco@227: unsignedVal = abs(val); faluco@227: } else { faluco@227: unsignedVal = val; faluco@227: } faluco@227: do faluco@227: { faluco@227: text[digits++] = '0' + unsignedVal % 10; faluco@227: unsignedVal /= 10; faluco@227: } while (unsignedVal); faluco@227: faluco@227: if (signedVal < 0) faluco@227: { faluco@227: text[digits++] = '-'; faluco@227: } faluco@227: faluco@227: buf = *buf_p; faluco@227: faluco@227: if (!(flags & LADJUST)) faluco@227: { faluco@227: while ((digits < width) && maxlen) faluco@227: { faluco@227: *buf++ = (flags & ZEROPAD) ? '0' : ' '; faluco@227: width--; faluco@227: maxlen--; faluco@227: } faluco@227: } faluco@227: faluco@227: while (digits-- && maxlen) faluco@227: { faluco@227: *buf++ = text[digits]; faluco@227: width--; faluco@227: maxlen--; faluco@227: } faluco@227: faluco@227: if (flags & LADJUST) faluco@227: { faluco@227: while (width-- && maxlen) faluco@227: { faluco@227: *buf++ = (flags & ZEROPAD) ? '0' : ' '; faluco@227: maxlen--; faluco@227: } faluco@227: } faluco@227: faluco@227: *buf_p = buf; faluco@227: } faluco@227: faluco@227: size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param) faluco@227: { faluco@227: int arg; faluco@227: //int args = params[0] / sizeof(cell); //:TODO: wrong, i think params[0] has now the param count not the byte count faluco@227: // either way this is only used when the above macro is fixed, until then not needed faluco@227: char *buf_p; faluco@227: char ch; faluco@227: int flags; faluco@227: int width; faluco@227: int prec; faluco@227: int n; faluco@227: char sign; faluco@227: const char *fmt; faluco@230: size_t llen = maxlen - 1; faluco@227: faluco@227: buf_p = buffer; faluco@227: arg = *param; faluco@227: fmt = format; faluco@227: faluco@227: while (true) faluco@227: { faluco@227: // run through the format string until we hit a '%' or '\0' faluco@227: for (ch = *fmt; llen && ((ch = *fmt) != '\0') && (ch != '%'); fmt++) faluco@227: { faluco@227: *buf_p++ = ch; faluco@227: llen--; faluco@227: } faluco@227: if ((ch == '\0') || (llen <= 0)) faluco@227: { faluco@227: goto done; faluco@227: } faluco@227: faluco@227: // skip over the '%' faluco@227: fmt++; faluco@227: faluco@227: // reset formatting state faluco@227: flags = 0; faluco@227: width = 0; faluco@227: prec = -1; faluco@227: sign = '\0'; faluco@227: faluco@227: rflag: faluco@227: ch = *fmt++; faluco@227: reswitch: faluco@227: switch(ch) faluco@227: { faluco@227: case '-': faluco@227: { faluco@227: flags |= LADJUST; faluco@227: goto rflag; faluco@227: } faluco@227: case '.': faluco@227: { faluco@227: n = 0; faluco@227: while(is_digit((ch = *fmt++))) faluco@227: { faluco@227: n = 10 * n + (ch - '0'); faluco@227: } faluco@227: prec = (n < 0) ? -1 : n; faluco@227: goto reswitch; faluco@227: } faluco@227: case '0': faluco@227: { faluco@227: flags |= ZEROPAD; faluco@227: goto rflag; faluco@227: } faluco@227: case '1': faluco@227: case '2': faluco@227: case '3': faluco@227: case '4': faluco@227: case '5': faluco@227: case '6': faluco@227: case '7': faluco@227: case '8': faluco@227: case '9': faluco@227: { faluco@227: n = 0; faluco@227: do faluco@227: { faluco@227: n = 10 * n + (ch - '0'); faluco@227: ch = *fmt++; faluco@227: } while(is_digit(ch)); faluco@227: width = n; faluco@227: goto reswitch; faluco@227: } faluco@227: case 'c': faluco@227: { faluco@227: CHECK_ARGS(0); faluco@230: if (!llen) faluco@227: { faluco@227: goto done; faluco@227: } faluco@227: char *c; faluco@227: pCtx->LocalToString(params[arg], &c); faluco@227: *buf_p++ = *c; faluco@227: llen--; faluco@227: arg++; faluco@227: break; faluco@227: } faluco@227: case 'd': faluco@227: case 'i': faluco@227: { faluco@227: CHECK_ARGS(0); faluco@227: cell_t *value; faluco@227: pCtx->LocalToPhysAddr(params[arg], &value); faluco@227: AddInt(&buf_p, llen, static_cast(*value), width, flags); faluco@227: arg++; faluco@227: break; faluco@227: } faluco@227: case 'u': faluco@227: { faluco@227: CHECK_ARGS(0); faluco@227: cell_t *value; faluco@227: pCtx->LocalToPhysAddr(params[arg], &value); faluco@227: AddUInt(&buf_p, llen, static_cast(*value), width, flags); faluco@227: arg++; faluco@227: break; faluco@227: } faluco@227: case 'f': faluco@227: { faluco@227: CHECK_ARGS(0); faluco@227: cell_t *value; faluco@227: pCtx->LocalToPhysAddr(params[arg], &value); dvander@233: AddFloat(&buf_p, llen, sp_ctof(*value), width, prec); faluco@227: arg++; faluco@227: break; faluco@227: } faluco@227: case 's': faluco@227: { faluco@227: CHECK_ARGS(0); faluco@227: char *str; faluco@227: pCtx->LocalToString(params[arg], &str); faluco@227: AddString(&buf_p, llen, str, width, prec); faluco@227: arg++; faluco@227: break; faluco@227: } faluco@227: case '%': faluco@227: { faluco@230: if (!llen) faluco@227: { faluco@227: goto done; faluco@227: } faluco@227: *buf_p++ = ch; faluco@227: llen--; faluco@227: break; faluco@227: } faluco@227: case '\0': faluco@227: { faluco@230: if (!llen) faluco@227: { faluco@227: goto done; faluco@227: } faluco@227: *buf_p++ = '%'; faluco@227: llen--; faluco@227: goto done; faluco@227: } faluco@227: default: faluco@227: { faluco@230: if (!llen) faluco@227: { faluco@227: goto done; faluco@227: } faluco@227: *buf_p++ = ch; faluco@227: llen--; faluco@227: break; faluco@227: } faluco@227: } faluco@227: } faluco@227: faluco@227: done: faluco@227: *buf_p = '\0'; faluco@227: *param = arg; faluco@227: return (maxlen - llen); faluco@227: } faluco@230: faluco@230: const char *stristr(const char *str, const char *substr) faluco@230: { faluco@230: if (!*substr) faluco@230: { faluco@230: return ((char *)str); faluco@230: } faluco@230: faluco@230: char *needle = (char *)substr; faluco@230: char *prevloc = (char *)str; faluco@230: char *haystack = (char *)str; faluco@230: faluco@230: while (*haystack) faluco@230: { faluco@230: if (tolower(*haystack) == tolower(*needle)) faluco@230: { faluco@230: haystack++; faluco@230: if (!*++needle) faluco@230: { faluco@230: return prevloc; faluco@230: } faluco@230: } else { faluco@230: haystack = ++prevloc; faluco@230: needle = (char *)substr; faluco@230: } faluco@230: } faluco@230: faluco@230: return NULL; faluco@230: } faluco@230: dvander@233: unsigned int strncopy(char *dest, const char *src, size_t count) faluco@230: { faluco@230: if (!count) faluco@230: { faluco@230: return 0; faluco@230: } faluco@230: faluco@230: char *start = dest; faluco@230: while ((*src) && (--count)) faluco@230: { faluco@230: *dest++ = *src++; faluco@230: } faluco@230: *dest = '\0'; faluco@230: faluco@230: return (dest - start); faluco@230: }