amuz.es/src/infra/goutils@v0.1.3/misc/dumper.go (about)

     1  package misc
     2  
     3  import "bytes"
     4  
     5  import (
     6  	"fmt"
     7  	"unicode/utf8"
     8  	"golang.org/x/text/width"
     9  )
    10  
    11  func HexDump(by []byte) string {
    12  	n := len(by)
    13  	rowcount := 0
    14  	stop := (n / 16) * 16
    15  	k := 0
    16  	buf := &bytes.Buffer{}
    17  
    18  	for i := 0; i <= stop; i += 16 {
    19  		k++
    20  		if i+16 < n {
    21  			rowcount = 16
    22  		} else {
    23  			rowcount = min(k*16, n) % 16
    24  		}
    25  
    26  		fmt.Fprintf(buf, "%08x ", i)
    27  		for j := 0; j < rowcount; j++ {
    28  			if j%8 == 0 {
    29  				fmt.Fprintf(buf, " %02x ", by[i+j])
    30  			} else {
    31  				fmt.Fprintf(buf, "%02x ", by[i+j])
    32  			}
    33  
    34  		}
    35  
    36  		for j := rowcount; j < 16; j++ {
    37  			if j%8 == 0 {
    38  				fmt.Fprintf(buf, "    ")
    39  			} else {
    40  				fmt.Fprintf(buf, "   ")
    41  			}
    42  		}
    43  		buf.WriteRune('|')
    44  		viewString(by[i:(i + rowcount)], buf)
    45  		buf.WriteRune('|')
    46  		buf.WriteRune('\n')
    47  		buf.WriteRune('\r')
    48  	}
    49  	return buf.String()
    50  }
    51  
    52  func max(a, b int) int {
    53  	if a > b {
    54  		return a
    55  	}
    56  	return b
    57  }
    58  func min(a, b int) int {
    59  	if a < b {
    60  		return a
    61  	}
    62  	return b
    63  }
    64  func GuessUnicodeWidth(char rune) (realSize int) {
    65  	prop := width.LookupRune(char)
    66  	switch prop.Kind() {
    67  	case width.EastAsianFullwidth:
    68  		fallthrough
    69  	case width.EastAsianWide:
    70  		realSize = 2
    71  	case width.EastAsianHalfwidth:
    72  		fallthrough
    73  	case width.EastAsianNarrow:
    74  		realSize = 2
    75  	case width.EastAsianAmbiguous:
    76  		fallthrough
    77  	case width.Neutral:
    78  		fallthrough
    79  	default:
    80  		realSize = 1
    81  	}
    82  	return
    83  }
    84  
    85  func FillUnicodeWidth(byteLength int, char rune) int {
    86  	fillWidth := GuessUnicodeWidth(char)
    87  	return max(0, byteLength-fillWidth)
    88  }
    89  func viewString(b []byte, buf *bytes.Buffer) {
    90  	for {
    91  		if r, size := utf8.DecodeRune(b); size == 0 {
    92  			return
    93  		} else if r == utf8.RuneError {
    94  			for i := 0; i < size; i++ {
    95  				buf.WriteRune('_')
    96  			}
    97  			b = b[size:]
    98  		} else if r < 32 {
    99  			for i := 0; i < size; i++ {
   100  				buf.WriteRune('.')
   101  			}
   102  			b = b[size:]
   103  		} else {
   104  			buf.WriteRune(r)
   105  			pad := FillUnicodeWidth(size, r)
   106  			for i := 0; i < pad; i++ {
   107  				buf.WriteRune('.')
   108  			}
   109  			b = b[size:]
   110  		}
   111  	}
   112  }