gpt4 book ai didi

定制sprintf,值得吗?

转载 作者:太空宇宙 更新时间:2023-11-04 01:40:29 25 4
gpt4 key购买 nike

下面的代码是从nginx中提取出来的,基本上是重写了sprintf,实际上nginx还重写了一些其他的字符串函数,值得吗?

u_char *
ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args)
{
u_char *p, zero;
int d;
double f, scale;
size_t len, slen;
int64_t i64;
uint64_t ui64;
ngx_msec_t ms;
ngx_uint_t width, sign, hex, max_width, frac_width, n;
ngx_str_t *v;
ngx_variable_value_t *vv;

while (*fmt && buf < last) {

/*
* "buf < last" means that we could copy at least one character:
* the plain character, "%%", "%c", and minus without the checking
*/

if (*fmt == '%') {

i64 = 0;
ui64 = 0;

zero = (u_char) ((*++fmt == '0') ? '0' : ' ');
width = 0;
sign = 1;
hex = 0;
max_width = 0;
frac_width = 0;
slen = (size_t) -1;

while (*fmt >= '0' && *fmt <= '9') {
width = width * 10 + *fmt++ - '0';
}


for ( ;; ) {
switch (*fmt) {

case 'u':
sign = 0;
fmt++;
continue;

case 'm':
max_width = 1;
fmt++;
continue;

case 'X':
hex = 2;
sign = 0;
fmt++;
continue;

case 'x':
hex = 1;
sign = 0;
fmt++;
continue;

case '.':
fmt++;

while (*fmt >= '0' && *fmt <= '9') {
frac_width = frac_width * 10 + *fmt++ - '0';
}

break;

case '*':
slen = va_arg(args, size_t);
fmt++;
continue;

default:
break;
}

break;
}


switch (*fmt) {

case 'V':
v = va_arg(args, ngx_str_t *);

len = ngx_min(((size_t) (last - buf)), v->len);
buf = ngx_cpymem(buf, v->data, len);
fmt++;

continue;

case 'v':
vv = va_arg(args, ngx_variable_value_t *);

len = ngx_min(((size_t) (last - buf)), vv->len);
buf = ngx_cpymem(buf, vv->data, len);
fmt++;

continue;

case 's':
p = va_arg(args, u_char *);

if (slen == (size_t) -1) {
while (*p && buf < last) {
*buf++ = *p++;
}

} else {
len = ngx_min(((size_t) (last - buf)), slen);
buf = ngx_cpymem(buf, p, len);
}

fmt++;

continue;

case 'O':
i64 = (int64_t) va_arg(args, off_t);
sign = 1;
break;

case 'P':
i64 = (int64_t) va_arg(args, ngx_pid_t);
sign = 1;
break;

case 'T':
i64 = (int64_t) va_arg(args, time_t);
sign = 1;
break;

case 'M':
ms = (ngx_msec_t) va_arg(args, ngx_msec_t);
if ((ngx_msec_int_t) ms == -1) {
sign = 1;
i64 = -1;
} else {
sign = 0;
ui64 = (uint64_t) ms;
}
break;

case 'z':
if (sign) {
i64 = (int64_t) va_arg(args, ssize_t);
} else {
ui64 = (uint64_t) va_arg(args, size_t);
}
break;

case 'i':
if (sign) {
i64 = (int64_t) va_arg(args, ngx_int_t);
} else {
ui64 = (uint64_t) va_arg(args, ngx_uint_t);
}

if (max_width) {
width = NGX_INT_T_LEN;
}

break;

case 'd':
if (sign) {
i64 = (int64_t) va_arg(args, int);
} else {
ui64 = (uint64_t) va_arg(args, u_int);
}
break;

case 'l':
if (sign) {
i64 = (int64_t) va_arg(args, long);
} else {
ui64 = (uint64_t) va_arg(args, u_long);
}
break;

case 'D':
if (sign) {
i64 = (int64_t) va_arg(args, int32_t);
} else {
ui64 = (uint64_t) va_arg(args, uint32_t);
}
break;

case 'L':
if (sign) {
i64 = va_arg(args, int64_t);
} else {
ui64 = va_arg(args, uint64_t);
}
break;

case 'A':
if (sign) {
i64 = (int64_t) va_arg(args, ngx_atomic_int_t);
} else {
ui64 = (uint64_t) va_arg(args, ngx_atomic_uint_t);
}

if (max_width) {
width = NGX_ATOMIC_T_LEN;
}

break;

case 'f':
f = va_arg(args, double);

if (f < 0) {
*buf++ = '-';
f = -f;
}

ui64 = (int64_t) f;

buf = ngx_sprintf_num(buf, last, ui64, zero, 0, width);

if (frac_width) {

if (buf < last) {
*buf++ = '.';
}

scale = 1.0;

for (n = frac_width; n; n--) {
scale *= 10.0;
}

/*
* (int64_t) cast is required for msvc6:
* it can not convert uint64_t to double
*/
ui64 = (uint64_t) ((f - (int64_t) ui64) * scale + 0.5);

buf = ngx_sprintf_num(buf, last, ui64, '0', 0, frac_width);
}

fmt++;

continue;

#if !(NGX_WIN32)
case 'r':
i64 = (int64_t) va_arg(args, rlim_t);
sign = 1;
break;
#endif

case 'p':
ui64 = (uintptr_t) va_arg(args, void *);
hex = 2;
sign = 0;
zero = '0';
width = NGX_PTR_SIZE * 2;
break;

case 'c':
d = va_arg(args, int);
*buf++ = (u_char) (d & 0xff);
fmt++;

continue;

case 'Z':
*buf++ = '\0';
fmt++;

continue;

case 'N':
#if (NGX_WIN32)
*buf++ = CR;
#endif
*buf++ = LF;
fmt++;

continue;

case '%':
*buf++ = '%';
fmt++;

continue;

default:
*buf++ = *fmt++;

continue;
}

if (sign) {
if (i64 < 0) {
*buf++ = '-';
ui64 = (uint64_t) -i64;

} else {
ui64 = (uint64_t) i64;
}
}

buf = ngx_sprintf_num(buf, last, ui64, zero, hex, width);

fmt++;

} else {
*buf++ = *fmt++;
}
}

return buf;
}

IMO 写类似的东西只会造成内存浪费,你的想法是什么?

最佳答案

它是否“值得”是主观的——有很多事情需要考虑:

  1. 它比 sprintf 有什么优势?你需要它们吗?
  2. 您是否愿意忍受可能存在的任何缺点?
  3. 您是否充分理解代码以在发现问题时能够修复它?
  4. 它和 sprintf 一样快吗?如果不是,你关心吗?

您可能还想考虑编写一个覆盖函数,添加您需要的任何额外功能,但随后只调用 sprintf,而不是重新实现整个函数。

关于定制sprintf,值得吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6236617/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com