github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/cmd/rlpdump/main.go (about)

     1  /*
     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  /**
    18   * @authors
    19   * 	Felix Lange <felix@ethdev.com>
    20   */
    21  
    22  // rlpdump is a pretty-printer for RLP data.
    23  package main
    24  
    25  import (
    26  	"bytes"
    27  	"encoding/hex"
    28  	"flag"
    29  	"fmt"
    30  	"io"
    31  	"os"
    32  	"strings"
    33  
    34  	"github.com/jonasnick/go-ethereum/rlp"
    35  )
    36  
    37  var (
    38  	hexMode = flag.String("hex", "", "dump given hex data")
    39  	noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably")
    40  )
    41  
    42  func init() {
    43  	flag.Usage = func() {
    44  		fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "[-noascii] [-hex <data>] [filename]")
    45  		flag.PrintDefaults()
    46  		fmt.Fprintln(os.Stderr, `
    47  Dumps RLP data from the given file in readable form.
    48  If the filename is omitted, data is read from stdin.`)
    49  	}
    50  }
    51  
    52  func main() {
    53  	flag.Parse()
    54  
    55  	var r io.Reader
    56  	switch {
    57  	case *hexMode != "":
    58  		data, err := hex.DecodeString(*hexMode)
    59  		if err != nil {
    60  			die(err)
    61  		}
    62  		r = bytes.NewReader(data)
    63  
    64  	case flag.NArg() == 0:
    65  		r = os.Stdin
    66  
    67  	case flag.NArg() == 1:
    68  		fd, err := os.Open(flag.Arg(0))
    69  		if err != nil {
    70  			die(err)
    71  		}
    72  		defer fd.Close()
    73  		r = fd
    74  
    75  	default:
    76  		fmt.Fprintln(os.Stderr, "Error: too many arguments")
    77  		flag.Usage()
    78  		os.Exit(2)
    79  	}
    80  
    81  	s := rlp.NewStream(r)
    82  	for {
    83  		if err := dump(s, 0); err != nil {
    84  			if err != io.EOF {
    85  				die(err)
    86  			}
    87  			break
    88  		}
    89  		fmt.Println()
    90  	}
    91  }
    92  
    93  func dump(s *rlp.Stream, depth int) error {
    94  	kind, size, err := s.Kind()
    95  	if err != nil {
    96  		return err
    97  	}
    98  	switch kind {
    99  	case rlp.Byte, rlp.String:
   100  		str, err := s.Bytes()
   101  		if err != nil {
   102  			return err
   103  		}
   104  		if len(str) == 0 || !*noASCII && isASCII(str) {
   105  			fmt.Printf("%s%q", ws(depth), str)
   106  		} else {
   107  			fmt.Printf("%s%x", ws(depth), str)
   108  		}
   109  	case rlp.List:
   110  		s.List()
   111  		defer s.ListEnd()
   112  		if size == 0 {
   113  			fmt.Print(ws(depth) + "[]")
   114  		} else {
   115  			fmt.Println(ws(depth) + "[")
   116  			for i := 0; ; i++ {
   117  				if i > 0 {
   118  					fmt.Print(",\n")
   119  				}
   120  				if err := dump(s, depth+1); err == rlp.EOL {
   121  					break
   122  				} else if err != nil {
   123  					return err
   124  				}
   125  			}
   126  			fmt.Print(ws(depth) + "]")
   127  		}
   128  	}
   129  	return nil
   130  }
   131  
   132  func isASCII(b []byte) bool {
   133  	for _, c := range b {
   134  		if c < 32 || c > 126 {
   135  			return false
   136  		}
   137  	}
   138  	return true
   139  }
   140  
   141  func ws(n int) string {
   142  	return strings.Repeat("  ", n)
   143  }
   144  
   145  func die(args ...interface{}) {
   146  	fmt.Fprintln(os.Stderr, args...)
   147  	os.Exit(1)
   148  }