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 }