github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/cmd/rlpdump/main.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // rlpdump is a pretty-printer for RLP data. 18 package main 19 20 import ( 21 "bytes" 22 "encoding/hex" 23 "flag" 24 "fmt" 25 "io" 26 "os" 27 "strings" 28 29 "github.com/atheioschain/go-atheios/rlp" 30 ) 31 32 var ( 33 hexMode = flag.String("hex", "", "dump given hex data") 34 noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably") 35 ) 36 37 func init() { 38 flag.Usage = func() { 39 fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "[-noascii] [-hex <data>] [filename]") 40 flag.PrintDefaults() 41 fmt.Fprintln(os.Stderr, ` 42 Dumps RLP data from the given file in readable form. 43 If the filename is omitted, data is read from stdin.`) 44 } 45 } 46 47 func main() { 48 flag.Parse() 49 50 var r io.Reader 51 switch { 52 case *hexMode != "": 53 data, err := hex.DecodeString(*hexMode) 54 if err != nil { 55 die(err) 56 } 57 r = bytes.NewReader(data) 58 59 case flag.NArg() == 0: 60 r = os.Stdin 61 62 case flag.NArg() == 1: 63 fd, err := os.Open(flag.Arg(0)) 64 if err != nil { 65 die(err) 66 } 67 defer fd.Close() 68 r = fd 69 70 default: 71 fmt.Fprintln(os.Stderr, "Error: too many arguments") 72 flag.Usage() 73 os.Exit(2) 74 } 75 76 s := rlp.NewStream(r, 0) 77 for { 78 if err := dump(s, 0); err != nil { 79 if err != io.EOF { 80 die(err) 81 } 82 break 83 } 84 fmt.Println() 85 } 86 } 87 88 func dump(s *rlp.Stream, depth int) error { 89 kind, size, err := s.Kind() 90 if err != nil { 91 return err 92 } 93 switch kind { 94 case rlp.Byte, rlp.String: 95 str, err := s.Bytes() 96 if err != nil { 97 return err 98 } 99 if len(str) == 0 || !*noASCII && isASCII(str) { 100 fmt.Printf("%s%q", ws(depth), str) 101 } else { 102 fmt.Printf("%s%x", ws(depth), str) 103 } 104 case rlp.List: 105 s.List() 106 defer s.ListEnd() 107 if size == 0 { 108 fmt.Print(ws(depth) + "[]") 109 } else { 110 fmt.Println(ws(depth) + "[") 111 for i := 0; ; i++ { 112 if i > 0 { 113 fmt.Print(",\n") 114 } 115 if err := dump(s, depth+1); err == rlp.EOL { 116 break 117 } else if err != nil { 118 return err 119 } 120 } 121 fmt.Print(ws(depth) + "]") 122 } 123 } 124 return nil 125 } 126 127 func isASCII(b []byte) bool { 128 for _, c := range b { 129 if c < 32 || c > 126 { 130 return false 131 } 132 } 133 return true 134 } 135 136 func ws(n int) string { 137 return strings.Repeat(" ", n) 138 } 139 140 func die(args ...interface{}) { 141 fmt.Fprintln(os.Stderr, args...) 142 os.Exit(1) 143 }