added atcprintf
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40232
This commit is contained in:
parent
5e75d0928c
commit
6e7e89e9cf
425
core/sm_stringutil.cpp
Normal file
425
core/sm_stringutil.cpp
Normal file
@ -0,0 +1,425 @@
|
||||
#include "sm_stringutil.h"
|
||||
|
||||
#define ALT 0x00000001 /* alternate form */
|
||||
#define HEXPREFIX 0x00000002 /* add 0x or 0X prefix */
|
||||
#define LADJUST 0x00000004 /* left adjustment */
|
||||
#define LONGDBL 0x00000008 /* long double */
|
||||
#define LONGINT 0x00000010 /* long integer */
|
||||
#define QUADINT 0x00000020 /* quad integer */
|
||||
#define SHORTINT 0x00000040 /* short integer */
|
||||
#define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */
|
||||
#define FPT 0x00000100 /* floating point number */
|
||||
#define to_digit(c) ((c) - '0')
|
||||
#define is_digit(c) ((unsigned)to_digit(c) <= 9)
|
||||
#define to_char(n) ((n) + '0')
|
||||
|
||||
//:TODO: fix this macro when we have a debugger
|
||||
|
||||
#define CHECK_ARGS(n)/* \
|
||||
if ((arg+n) > args) { \
|
||||
LogError(amx, AMX_ERR_PARAMS, "String formatted incorrectly - parameter %d (total %d)", arg, args); \
|
||||
return 0; \
|
||||
}
|
||||
*/
|
||||
|
||||
void AddString(char **buf_p, size_t &maxlen, const char *string, int width, int prec)
|
||||
{
|
||||
int size = 0;
|
||||
char *buf;
|
||||
static char nlstr[] = {'(','n','u','l','l',')','\0'};
|
||||
|
||||
buf = *buf_p;
|
||||
|
||||
if (string == NULL)
|
||||
{
|
||||
string = nlstr;
|
||||
prec = -1;
|
||||
}
|
||||
|
||||
if (prec >= 0)
|
||||
{
|
||||
for (size = 0; size < prec; size++)
|
||||
{
|
||||
if (string[size] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (string[size++]);
|
||||
size--;
|
||||
}
|
||||
|
||||
if (size > (int)maxlen)
|
||||
{
|
||||
size = maxlen;
|
||||
}
|
||||
|
||||
maxlen -= size;
|
||||
width -= size;
|
||||
|
||||
while (size--)
|
||||
{
|
||||
*buf++ = *string++;
|
||||
}
|
||||
|
||||
while ((width-- > 0) && maxlen)
|
||||
{
|
||||
*buf++ = ' ';
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
*buf_p = buf;
|
||||
}
|
||||
|
||||
void AddFloat(char **buf_p, size_t &maxlen, double fval, int width, int prec)
|
||||
{
|
||||
char text[32];
|
||||
int digits;
|
||||
double signedVal;
|
||||
char *buf;
|
||||
int val;
|
||||
|
||||
// get the sign
|
||||
signedVal = fval;
|
||||
if (fval < 0)
|
||||
{
|
||||
fval = -fval;
|
||||
}
|
||||
|
||||
// write the float number
|
||||
digits = 0;
|
||||
val = (int)fval;
|
||||
do
|
||||
{
|
||||
text[digits++] = '0' + val % 10;
|
||||
val /= 10;
|
||||
} while (val);
|
||||
|
||||
if (signedVal < 0)
|
||||
{
|
||||
text[digits++] = '-';
|
||||
}
|
||||
|
||||
buf = *buf_p;
|
||||
|
||||
while ((digits < width) && maxlen)
|
||||
{
|
||||
*buf++ = ' ';
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
while ((digits--) && maxlen)
|
||||
{
|
||||
*buf++ = text[digits];
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
*buf_p = buf;
|
||||
|
||||
if (prec < 0)
|
||||
{
|
||||
prec = 6;
|
||||
}
|
||||
// write the fraction
|
||||
digits = 0;
|
||||
while (digits < prec)
|
||||
{
|
||||
fval -= (int)fval;
|
||||
fval *= 10.0;
|
||||
val = (int)fval;
|
||||
text[digits++] = '0' + val % 10;
|
||||
}
|
||||
|
||||
if ((digits > 0) && maxlen)
|
||||
{
|
||||
buf = *buf_p;
|
||||
*buf++ = '.';
|
||||
maxlen--;
|
||||
for (prec = 0; maxlen && (prec < digits); prec++)
|
||||
{
|
||||
*buf++ = text[prec];
|
||||
maxlen--;
|
||||
}
|
||||
*buf_p = buf;
|
||||
}
|
||||
}
|
||||
|
||||
void AddUInt(char **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
|
||||
{
|
||||
char text[32];
|
||||
int digits;
|
||||
char *buf;
|
||||
|
||||
digits = 0;
|
||||
do
|
||||
{
|
||||
text[digits++] = '0' + val % 10;
|
||||
val /= 10;
|
||||
} while (val);
|
||||
|
||||
buf = *buf_p;
|
||||
|
||||
if (!(flags & LADJUST))
|
||||
{
|
||||
while (digits < width && maxlen)
|
||||
{
|
||||
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
while (digits-- && maxlen)
|
||||
{
|
||||
*buf++ = text[digits];
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
if (flags & LADJUST)
|
||||
{
|
||||
while (width-- && maxlen)
|
||||
{
|
||||
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
*buf_p = buf;
|
||||
}
|
||||
|
||||
void AddInt(char **buf_p, size_t &maxlen, int val, int width, int flags)
|
||||
{
|
||||
char text[32];
|
||||
int digits;
|
||||
int signedVal;
|
||||
char *buf;
|
||||
unsigned int unsignedVal;
|
||||
|
||||
digits = 0;
|
||||
signedVal = val;
|
||||
if (val < 0)
|
||||
{
|
||||
/* we want the unsigned version */
|
||||
unsignedVal = abs(val);
|
||||
} else {
|
||||
unsignedVal = val;
|
||||
}
|
||||
do
|
||||
{
|
||||
text[digits++] = '0' + unsignedVal % 10;
|
||||
unsignedVal /= 10;
|
||||
} while (unsignedVal);
|
||||
|
||||
if (signedVal < 0)
|
||||
{
|
||||
text[digits++] = '-';
|
||||
}
|
||||
|
||||
buf = *buf_p;
|
||||
|
||||
if (!(flags & LADJUST))
|
||||
{
|
||||
while ((digits < width) && maxlen)
|
||||
{
|
||||
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
while (digits-- && maxlen)
|
||||
{
|
||||
*buf++ = text[digits];
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
if (flags & LADJUST)
|
||||
{
|
||||
while (width-- && maxlen)
|
||||
{
|
||||
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
*buf_p = buf;
|
||||
}
|
||||
|
||||
size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param)
|
||||
{
|
||||
int arg;
|
||||
//int args = params[0] / sizeof(cell); //:TODO: wrong, i think params[0] has now the param count not the byte count
|
||||
// either way this is only used when the above macro is fixed, until then not needed
|
||||
char *buf_p;
|
||||
char ch;
|
||||
int flags;
|
||||
int width;
|
||||
int prec;
|
||||
int n;
|
||||
char sign;
|
||||
const char *fmt;
|
||||
size_t llen = maxlen;
|
||||
|
||||
buf_p = buffer;
|
||||
arg = *param;
|
||||
fmt = format;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// run through the format string until we hit a '%' or '\0'
|
||||
for (ch = *fmt; llen && ((ch = *fmt) != '\0') && (ch != '%'); fmt++)
|
||||
{
|
||||
*buf_p++ = ch;
|
||||
llen--;
|
||||
}
|
||||
if ((ch == '\0') || (llen <= 0))
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
|
||||
// skip over the '%'
|
||||
fmt++;
|
||||
|
||||
// reset formatting state
|
||||
flags = 0;
|
||||
width = 0;
|
||||
prec = -1;
|
||||
sign = '\0';
|
||||
|
||||
rflag:
|
||||
ch = *fmt++;
|
||||
reswitch:
|
||||
switch(ch)
|
||||
{
|
||||
case '-':
|
||||
{
|
||||
flags |= LADJUST;
|
||||
goto rflag;
|
||||
}
|
||||
case '.':
|
||||
{
|
||||
n = 0;
|
||||
while(is_digit((ch = *fmt++)))
|
||||
{
|
||||
n = 10 * n + (ch - '0');
|
||||
}
|
||||
prec = (n < 0) ? -1 : n;
|
||||
goto reswitch;
|
||||
}
|
||||
case '0':
|
||||
{
|
||||
flags |= ZEROPAD;
|
||||
goto rflag;
|
||||
}
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
{
|
||||
n = 0;
|
||||
do
|
||||
{
|
||||
n = 10 * n + (ch - '0');
|
||||
ch = *fmt++;
|
||||
} while(is_digit(ch));
|
||||
width = n;
|
||||
goto reswitch;
|
||||
}
|
||||
case 'c':
|
||||
{
|
||||
CHECK_ARGS(0);
|
||||
if (llen <= 1)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
char *c;
|
||||
pCtx->LocalToString(params[arg], &c);
|
||||
*buf_p++ = *c;
|
||||
llen--;
|
||||
arg++;
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
case 'i':
|
||||
{
|
||||
CHECK_ARGS(0);
|
||||
cell_t *value;
|
||||
pCtx->LocalToPhysAddr(params[arg], &value);
|
||||
AddInt(&buf_p, llen, static_cast<int>(*value), width, flags);
|
||||
arg++;
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
{
|
||||
CHECK_ARGS(0);
|
||||
cell_t *value;
|
||||
pCtx->LocalToPhysAddr(params[arg], &value);
|
||||
AddUInt(&buf_p, llen, static_cast<unsigned int>(*value), width, flags);
|
||||
arg++;
|
||||
break;
|
||||
}
|
||||
case 'f':
|
||||
{
|
||||
CHECK_ARGS(0);
|
||||
cell_t *value;
|
||||
pCtx->LocalToPhysAddr(params[arg], &value);
|
||||
AddFloat(&buf_p, llen, ctof(*value), width, prec);
|
||||
arg++;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
{
|
||||
CHECK_ARGS(0);
|
||||
char *str;
|
||||
pCtx->LocalToString(params[arg], &str);
|
||||
AddString(&buf_p, llen, str, width, prec);
|
||||
arg++;
|
||||
break;
|
||||
}
|
||||
case '%':
|
||||
{
|
||||
if (llen <= 1)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
*buf_p++ = ch;
|
||||
llen--;
|
||||
break;
|
||||
}
|
||||
case '\0':
|
||||
{
|
||||
if (llen <= 1)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
*buf_p++ = '%';
|
||||
llen--;
|
||||
goto done;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (llen <= 1)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
*buf_p++ = ch;
|
||||
llen--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
*buf_p = '\0';
|
||||
*param = arg;
|
||||
return (maxlen - llen);
|
||||
}
|
12
core/sm_stringutil.h
Normal file
12
core/sm_stringutil.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_STRINGUTIL_H_
|
||||
#define _INCLUDE_SOURCEMOD_STRINGUTIL_H_
|
||||
|
||||
#include <math.h>
|
||||
#include "sp_vm_api.h"
|
||||
#include "sp_vm_typeutil.h"
|
||||
|
||||
using namespace SourcePawn;
|
||||
|
||||
size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param);
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_STRINGUTIL_H_
|
Loading…
Reference in New Issue
Block a user