로그 모듈 -- 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);
}

좋은 웹페이지 즐겨찾기