skalibs

Mirror/fork of https://skarnet.org/software/skalibs/
git clone https://ccx.te2000.cz/git/skalibs
Log | Files | Refs | README | LICENSE

ip6_fmt.c (1608B)


      1 /* ISC license. */
      2 
      3 #include <skalibs/diuint.h>
      4 #include <skalibs/fmtscan.h>
      5 
      6 #define px(c) ((j || (c)) ? (*s++ = fmtscan_asc(c), 1) : 0)
      7 
      8 static inline size_t xfmt16 (char *s, char const *key)
      9 {
     10   size_t j = 0 ;
     11   j += px((unsigned char)key[0] >> 4) ;
     12   j += px((unsigned char)key[0] & 15) ;
     13   j += px((unsigned char)key[1] >> 4) ;
     14   j += px((unsigned char)key[1] & 15) ;
     15   return j ? j : (*s = '0', 1) ;
     16 }
     17 
     18 static inline unsigned int find_colcol (char const *key, unsigned int *pos)
     19 {
     20   diuint z[4] = { DIUINT_ZERO, DIUINT_ZERO, DIUINT_ZERO, DIUINT_ZERO } ;
     21   unsigned int j = 0 ;
     22   unsigned int max = 0 ;
     23   int iszero = 0 ;
     24   unsigned int i = 0 ;
     25   for ( ; i < 8 ; i++)
     26   {
     27     if (key[i<<1] || key[(i<<1)+1])
     28     {
     29       if (iszero)
     30       {
     31         iszero = 0 ;
     32         z[j].right = i - z[j].left ;
     33         if (z[j].right > max) max = z[j].right ;
     34         j++ ;
     35       }
     36     }
     37     else
     38     {
     39       if (!iszero)
     40       {
     41         iszero = 1 ;
     42         z[j].left = i ;
     43       }
     44     }
     45   }
     46   if (iszero)
     47   {
     48     z[j].right = 8 - z[j].left ;
     49     if (z[j].right > max) max = z[j].right ;
     50     j++ ;
     51   }
     52 
     53   if (max >= 2)
     54     for (i = 0 ; i < j ; i++) if (z[i].right == max) return (*pos = z[i].left, max) ;
     55   return 0 ; 
     56 }
     57 
     58 size_t ip6_fmt (char *s, char const *ip6)
     59 {
     60   size_t w = 0 ;
     61   unsigned int pos = 8 ;
     62   unsigned int len = find_colcol(ip6, &pos) ;
     63   unsigned int i = 0 ;
     64   for (; i < 8 ; i++)
     65   {
     66     if (i == pos)
     67     {
     68       if (!i) s[w++] = ':' ;
     69       s[w++] = ':' ;
     70       i += len-1 ;
     71     }
     72     else
     73     {
     74       w += xfmt16(s + w, ip6 + (i<<1)) ;
     75       if (i < 7) s[w++] = ':' ;
     76     }
     77   }
     78   return w ;
     79 }