text: /*
   * @Author: jiejie
   * @Github: https://github.com/jiejieTop
   * @Date: 2019-12-25 23:54:19
   * @LastEditTime: 2020-06-17 15:23:09
   * @Description: the code belongs to jiejie, please keep the author insalof_formation and source code according to the license.
   */
  #include "format.h"
  #include "salof_defconfig.h"
  
  #ifdef SALOF_USING_LOG
  
  static int _get_atoi(const char **str)
  {
      int n;
      for (n = 0; is_digit(**str); (*str)++)
          n = n * 10 + **str - '0';
      return n;
  }
  
  static void _buff_put_char(char *buf, unsigned int *pos, unsigned int max, char c)
  {
      if (*pos < max)
          buf[(*pos)] = c;
      (*pos)++;
  }
  
  
  /**
   * Formats an integer number
   *  buf - buffer to print into
   *  len - current position in buffer
   *  maxlen - last valid position in buf
   *  num - number to print
   *  base - it's base
   *  width - how many spaces this should have; padding
   *  flags - above F flags
   */
  static void _salof_format_int(char *buf, unsigned int *len, unsigned int maxlen,
          signed long long num, int base, int width, int flags)
  {
      char nbuf[64], sign = 0;
      char altb[8]; // small buf for sign and #
      int n = num;
      int npad;           // number of pads
      char pchar = ' ';   // padding character
      char *digits = "0123456789ABCDEF";
      char *ldigits = "0123456789abcdef";
      int i, j;
  
      if (base < 2 || base > 16)
          return;
      if (flags & F_SMALL) digits = ldigits;
      if (flags & F_LEFT) flags &= ~F_ZEROPAD;
  
      if ((flags & F_SIGNED) && num < 0) {
          n = -num;
          sign = '-';
      } else if (flags & F_PLUS) {
          sign = '+';
      } else if (flags & F_SPACE)
          sign = ' ';
  
      i = 0;
      do {
          nbuf[i++] = digits[n % base];
          n = n / base;
      } while (n > 0);
     
      j = 0;
      if (sign) altb[j++] = sign;
      if (flags & F_ALTERNATE) {
          if (base == 8 || base == 16) {
              altb[j++] = '0';
              if (base == 16)
                  altb[j++] = (flags & F_SMALL) ? 'x' : 'X';
          }
      }
      altb[j] = 0;
  
      npad = width > i + j ? width - i - j : 0;
  
      if (width > i + j)
          npad = width - i - j;
  
      if (npad > 0 && ((flags & F_LEFT) == 0)) {
          if (flags & F_ZEROPAD) {
              for (j = 0; altb[j]; j++)
                  _buff_put_char(buf, len, maxlen, altb[j]);
              altb[0] = 0;
          }
          while (npad-- > 0)
              _buff_put_char(buf, len, maxlen, (flags & F_ZEROPAD) ? '0' : ' ');
      }
      for (j = 0; altb[j]; j++)
          _buff_put_char(buf, len, maxlen, altb[j]);
  
      while (i-- > 0)
          _buff_put_char(buf, len, maxlen, nbuf[i]);
  
      if (npad > 0 && (flags & F_LEFT))
          while(npad-- > 0)
              _buff_put_char(buf, len, maxlen, pchar);
  }
  
  static void _salof_format_char(char *buf, unsigned int *pos, unsigned int max, char c,
          int width, int flags)
  {
      int npad = 0;
      if (width > 0) npad = width - 1;
      if (npad < 0) npad = 0;
  
      if (npad && ((flags & F_LEFT) == 0))
          while (npad-- > 0)
              _buff_put_char(buf, pos, max, ' ');
  
      _buff_put_char(buf, pos, max, c);
  
      if (npad && (flags & F_LEFT))
          while (npad-- > 0)
              _buff_put_char(buf, pos, max, ' ');
  }
  
  /**
   * strlen()
   */
  static unsigned int _str_len(char *s)
  {
      unsigned int i;
      for (i = 0; *s; i++, s++)
          ;
      return i;
  }
  
  static void _salof_format_str(char *buf, unsigned int *pos, unsigned int max, char *s,
          int width, int flags)
  {
      int npad = 0;
      if (width > 0) npad = width - _str_len(s);
      if (npad < 0) npad = 0;
  
      if (npad && ((flags & F_LEFT) == 0))
          while (npad-- > 0)
              _buff_put_char(buf, pos, max, ' ');
  
      while (*s)
          _buff_put_char(buf, pos, max, *s++);
  
      if (npad && (flags & F_LEFT))
          while (npad-- > 0)
              _buff_put_char(buf, pos, max, ' ');
  }
  
  
  
  
  /***********************************************************************************************************************/
  
  /**
   * Shrinked down, vsnprintf implementation.
   *  This will not handle floating numbers (yet).
   */
  int salof_format_nstr(char *buf, unsigned int size, const char *fmt, va_list ap)
  {
      unsigned int n = 0;
      char c, *s;
      char state = 0;
      signed long long num;
      int base;
      int flags, width, precision, lflags;
  
      if (!buf) size = 0;
  
      for (;;) {
          c = *fmt++;
          if (state == S_DEFAULT) {
              if (c == '%') {
                  state = S_FLAGS;
                  flags = 0;
              } else {
                  _buff_put_char(buf, &n, size, c);
              }
          } else if (state == S_FLAGS) {
              switch (c) {
                  case '#': flags |= F_ALTERNATE; break;
                  case '0': flags |= F_ZEROPAD; break;
                  case '-': flags |= F_LEFT; break;
                  case ' ': flags |= F_SPACE; break;
                  case '+': flags |= F_PLUS; break;
                  case '\'':
                  case 'I' : break; // not yet used
                  default: fmt--; width = 0; state = S_WIDTH;
              }
          } else if (state == S_WIDTH) {
              if (c == '*') {
                  width = va_arg(ap, int);
                  if (width < 0) {
                      width = -width;
                      flags |= F_LEFT;
                  }
              } else if (is_digit(c) && c > '0') {
                  fmt--;
                  width = _get_atoi(&fmt);
              } else {
                  fmt--;
                  precision = -1;
                  state = S_PRECIS;
              }
          } else if (state == S_PRECIS) {
              // Ignored for now, but skip it
              if (c == '.') {
                  if (is_digit(*fmt))
                      precision = _get_atoi(&fmt);
                  else if (*fmt == '*')
                      precision = va_arg(ap, int);
                  precision = precision < 0 ? 0 : precision;
              } else
                  fmt--;
              lflags = 0;
              state = S_LENGTH;
          } else if (state == S_LENGTH) {
              switch(c) {
                  case 'h': lflags = lflags == L_CHAR ? L_SHORT : L_CHAR; break;
                  case 'l': lflags = lflags == L_LONG ? L_LLONG : L_LONG; break;
                  case 'L': lflags = L_DOUBLE; break;
                  default: fmt--; state = S_CONV;
              }
          } else if (state == S_CONV) {
              if (c == 'd' || c == 'i' || c == 'o' || c == 'b' || c == 'u' 
                      || c == 'x' || c == 'X') {
                  if (lflags == L_LONG)
                      num = va_arg(ap, int);
                  else if (lflags & (L_LLONG | L_DOUBLE))
                      num = va_arg(ap, signed long long);
                  else if (c == 'd' || c == 'i')
                      num = va_arg(ap, int);
                  else
                      num = (unsigned int) va_arg(ap, int);
  
                  base = 10;
                  if (c == 'd' || c == 'i') {
                      flags |= F_SIGNED;
                  } else if (c == 'x' || c == 'X') {
                      flags |= c == 'x' ? F_SMALL : 0;
                      base = 16;
                  } else if (c == 'o') {
                      base = 8;
                  } else if (c == 'b') {
                      base = 2;
                  }
                  _salof_format_int(buf, &n, size, num, base, width, flags);
              } else if (c == 'p') {
                  num = (size_t) va_arg(ap, void *);
                  base = 16;
                  flags |= F_SMALL | F_ALTERNATE;
                  _salof_format_int(buf, &n, size, num, base, width, flags);
              } else if (c == 's') {
                  s = va_arg(ap, char *);
                  if (!s)
                      s = "(null)";
                  _salof_format_str(buf, &n, size, s, width, flags);
              } else if (c == 'c') {
                  c = va_arg(ap, int);
                  _salof_format_char(buf, &n, size, c, width, flags);
              } else if (c == '%') {
                  _buff_put_char(buf, &n, size, c);
              } else {
                  _buff_put_char(buf, &n, size, '%');
                  _buff_put_char(buf, &n, size, c);
              }
              state = S_DEFAULT;
          }
          if (c == 0)
              break;
      }
      n--;
      if (n < size)
          buf[n] = 0;
      else if (size > 0)
          buf[size - 1] = 0;
  
      return n;
  }
  
  #endif
  
  
  