로그 모듈 -- printf 함수 데모 수 동 구현
7679 단어 Linux
전체적인 실현 방향 은 하나의 문자열 과 필요 한 매개 변수 (가 변 매개 변수) 를 전달 하고% 에 대한 처 리 를 통 해 우리 가 필요 로 하 는 유형 을 가 져 와 포맷 문자열 의 조작 ("Hello% s World", "nginx") 을 실현 하 는 것 입 니 다. 주로 기호 유형 이 있 는 지, 그리고 16 진수 변환 과 소수 유지 등 세부 적 인 처리 입 니 다.곰 곰 이 생각해 야 한다.
#include
#include
#include //
#include
#include
#include "ngx_global.h"
#include "ngx_macro.h"
#include "ngx_func.h"
static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero, uintptr_t hexadecimal, uintptr_t width);
// ngx_vslprintf()
u_char *ngx_slprintf(u_char *buf, u_char *last, const char *fmt, ...){
va_list args; //
u_char *p;
va_start(args, fmt); // args
p = ngx_vslprintf(buf, last, fmt, args);
va_end(args); // args
return p;
}
//
// buf: last: fmt: (format)
u_char *ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args){
u_char zero; // 0
uintptr_t width, sign, hex, frac_width, scale, n; //
int64_t i64; // %d
uint64_t ui64; // %ud
u_char *p; // %s
double f; // %f
uint64_t frac; // %.2f %.2f 12.457 frac = 46
// fmt
while(*fmt && buf < last){
if(*fmt == '%'){ //
// ----------------------- ----------------------
zero = (u_char)((*++fmt == '0') ? '0' : ' '); // % 0 0 %5d
width = 0; // ( %5d 5 ) %d %f
sign = 1; // %u 0
hex = 0; // 16 0: 1: , 2: ,
frac_width = 0; // %.2f frac_width=2
i64 = 0; //
ui64 = 0; //
// %
while(*fmt >= '0' && *fmt <= '9'){
width = width * 10 + (*fmt++ - '0');
}
// u x X .
for( ;; ){ // %.
switch(*fmt){
case 'u' : //
sign = 0;
fmt ++;
continue;
case 'X' : // 16
hex = 2;
sign = 0;
fmt ++;
continue;
case 'x' : // 16
hex = 1;
sign = 0;
fmt ++;
continue;
case '.' : //
fmt ++;
while(*fmt >= '0' && *fmt <= '9'){ //
frac_width = frac_width * 10 + (*fmt++ - '0');
}
break;
default :
break;
} // end switch(*fmt)
break;
} // end for(;;)
// % d s p f
switch(*fmt){
case '%' : // %% %
*buf ++ = '%';
fmt ++;
continue; // while(*fmt && buf < last)
case 'd' : //
if(sign){ //
i64 = (int64_t) va_arg(args, int); // va_arg
}
else{ //
ui64 = (uint64_t) va_arg(args, u_int);
}
break; // switch
case 's' : //
p = va_arg(args, u_char *); // p
// p buf
while(*p && buf < last){
*buf ++ = *p ++;
}
fmt ++;
continue; // while(*fmt && buf < last)
case 'P' : // pid_t
i64 = (int64_t) va_arg(args, pid_t);
sign = 1;
break;
case 'f' : //
f = va_arg(args, double);
//
if(f < 0){
*buf++ = '-'; //
f = -f; //
}
ui64 = (int64_t)f;
frac = 0;
//
if(frac_width){
scale = 1;
for(int i=0;i 99
// 99.5 + 0.5 = 100.0 -> 100
if(frac == scale){ //
// frac==scale %2.f 12.999
ui64 ++;
frac = 0; //
}
} // end if(frac_width)
//
buf = ngx_sprintf_num(buf, last, ui64, zero, 0, width); // buf
//
if(frac_width){
if(buf < last) *buf ++ = '.'; //
buf = ngx_sprintf_num(buf, last, frac, '0', 0, frac_width);
}
fmt ++;
continue; // while(*fmt && buf < lase)
//
//
default :
*buf ++ = *fmt ++;
continue;
} // end switch(*fmt)
//
// buf
if(sign){ //
if(i64 < 0){
*buf ++ = '-'; //
ui64 = (uint64_t) -i64; //
}
else ui64 = (uint64_t) i64;
} // end if(sign)
buf = ngx_sprintf_num(buf, last, ui64, zero, hex, width);
fmt ++;
} // end if(*fmt == '%')
// buf
else{
*buf ++ = *fmt ++;
}
} // end while(*fmt && buf < last)
return buf;
}
//
// buf: last: ui64: zero: 0 hex: 16 width: zero
static u_char * ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero, uintptr_t hexadecimal, uintptr_t width){
u_char *p, temp[NGX_INT64_LEN + 1];
size_t len;
uint32_t ui32;
static u_char hex[] = "0123456789abcdef";
static u_char HEX[] = "0123456789ABCDEF";
// p
p = temp + NGX_INT64_LEN;
if(hexadecimal == 0){ // 16
if(ui64 <= (uint64_t) NGX_MAX_UINT32_VALUE){ // 32
ui32 = (uint32_t) ui64; //
while(ui32){
*--p = (ui32 % 10 + '0'); //
ui32 /= 10;
}
} // end if(ui64 <= NGX_MAX_UINT32_VALUE)
else{
while(ui64){
*--p = (ui64 % 10 + '0'); //
ui64 /= 10;
}
}
} // end if(hex == 0)
else if(hexadecimal == 1){ // 16
do{
// 0xf 1111
// ui64 & 0xf 4 uint32_t
*--p = hex[(uint32_t)(ui64 & 0xf)];
}
while(ui64 >>= 4); // 4
} // end else if(hex == 1)
else{
// hex == 1
do{
*--p = HEX[(uint32_t) (ui64 & 0xf)];
}
while(ui64 >>= 4);
} // end else
// p
len = (temp + NGX_INT64_LEN) - p;
if((buf + len) >= last){ //
len = last - buf; //
}
return ngx_cpymem(buf, p, len);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
바이너리 파일cat 또는tail, 터미널 디코딩 시 처리 방법cat으로 바이너리 파일을 보려고 할 때 코드가 엉망이 되어 식은땀이 났다. 웹에서 스크롤된 정보의 처리 방법과alias의 설정을 요약합니다. reset 명령을 사용하여 터미널을 재설정합니다.이렇게 하면 고치지 못하...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.