OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [encoding/] [hex/] [hex.go] - Rev 747

Compare with Previous | Blame | View Log

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package hex implements hexadecimal encoding and decoding.
package hex

import (
        "bytes"
        "errors"
        "fmt"
        "io"
)

const hextable = "0123456789abcdef"

// EncodedLen returns the length of an encoding of n source bytes.
func EncodedLen(n int) int { return n * 2 }

// Encode encodes src into EncodedLen(len(src))
// bytes of dst.  As a convenience, it returns the number
// of bytes written to dst, but this value is always EncodedLen(len(src)).
// Encode implements hexadecimal encoding.
func Encode(dst, src []byte) int {
        for i, v := range src {
                dst[i*2] = hextable[v>>4]
                dst[i*2+1] = hextable[v&0x0f]
        }

        return len(src) * 2
}

// ErrLength results from decoding an odd length slice.
var ErrLength = errors.New("encoding/hex: odd length hex string")

// InvalidByteError values describe errors resulting from an invalid byte in a hex string.
type InvalidByteError byte

func (e InvalidByteError) Error() string {
        return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e))
}

func DecodedLen(x int) int { return x / 2 }

// Decode decodes src into DecodedLen(len(src)) bytes, returning the actual
// number of bytes written to dst.
//
// If Decode encounters invalid input, it returns an error describing the failure.
func Decode(dst, src []byte) (int, error) {
        if len(src)%2 == 1 {
                return 0, ErrLength
        }

        for i := 0; i < len(src)/2; i++ {
                a, ok := fromHexChar(src[i*2])
                if !ok {
                        return 0, InvalidByteError(src[i*2])
                }
                b, ok := fromHexChar(src[i*2+1])
                if !ok {
                        return 0, InvalidByteError(src[i*2+1])
                }
                dst[i] = (a << 4) | b
        }

        return len(src) / 2, nil
}

// fromHexChar converts a hex character into its value and a success flag.
func fromHexChar(c byte) (byte, bool) {
        switch {
        case '0' <= c && c <= '9':
                return c - '0', true
        case 'a' <= c && c <= 'f':
                return c - 'a' + 10, true
        case 'A' <= c && c <= 'F':
                return c - 'A' + 10, true
        }

        return 0, false
}

// EncodeToString returns the hexadecimal encoding of src.
func EncodeToString(src []byte) string {
        dst := make([]byte, EncodedLen(len(src)))
        Encode(dst, src)
        return string(dst)
}

// DecodeString returns the bytes represented by the hexadecimal string s.
func DecodeString(s string) ([]byte, error) {
        src := []byte(s)
        dst := make([]byte, DecodedLen(len(src)))
        _, err := Decode(dst, src)
        if err != nil {
                return nil, err
        }
        return dst, nil
}

// Dump returns a string that contains a hex dump of the given data. The format
// of the hex dump matches the output of `hexdump -C` on the command line.
func Dump(data []byte) string {
        var buf bytes.Buffer
        dumper := Dumper(&buf)
        dumper.Write(data)
        dumper.Close()
        return string(buf.Bytes())
}

// Dumper returns a WriteCloser that writes a hex dump of all written data to
// w. The format of the dump matches the output of `hexdump -C` on the command
// line.
func Dumper(w io.Writer) io.WriteCloser {
        return &dumper{w: w}
}

type dumper struct {
        w          io.Writer
        rightChars [18]byte
        buf        [14]byte
        used       int  // number of bytes in the current line
        n          uint // number of bytes, total
}

func toChar(b byte) byte {
        if b < 32 || b > 126 {
                return '.'
        }
        return b
}

func (h *dumper) Write(data []byte) (n int, err error) {
        // Output lines look like:
        // 00000010  2e 2f 30 31 32 33 34 35  36 37 38 39 3a 3b 3c 3d  |./0123456789:;<=|
        // ^ offset                          ^ extra space              ^ ASCII of line.
        for i := range data {
                if h.used == 0 {
                        // At the beginning of a line we print the current
                        // offset in hex.
                        h.buf[0] = byte(h.n >> 24)
                        h.buf[1] = byte(h.n >> 16)
                        h.buf[2] = byte(h.n >> 8)
                        h.buf[3] = byte(h.n)
                        Encode(h.buf[4:], h.buf[:4])
                        h.buf[12] = ' '
                        h.buf[13] = ' '
                        _, err = h.w.Write(h.buf[4:])
                }
                Encode(h.buf[:], data[i:i+1])
                h.buf[2] = ' '
                l := 3
                if h.used == 7 {
                        // There's an additional space after the 8th byte.
                        h.buf[3] = ' '
                        l = 4
                } else if h.used == 15 {
                        // At the end of the line there's an extra space and
                        // the bar for the right column.
                        h.buf[3] = ' '
                        h.buf[4] = '|'
                        l = 5
                }
                _, err = h.w.Write(h.buf[:l])
                if err != nil {
                        return
                }
                n++
                h.rightChars[h.used] = toChar(data[i])
                h.used++
                h.n++
                if h.used == 16 {
                        h.rightChars[16] = '|'
                        h.rightChars[17] = '\n'
                        _, err = h.w.Write(h.rightChars[:])
                        if err != nil {
                                return
                        }
                        h.used = 0
                }
        }
        return
}

func (h *dumper) Close() (err error) {
        // See the comments in Write() for the details of this format.
        if h.used == 0 {
                return
        }
        h.buf[0] = ' '
        h.buf[1] = ' '
        h.buf[2] = ' '
        h.buf[3] = ' '
        h.buf[4] = '|'
        nBytes := h.used
        for h.used < 16 {
                l := 3
                if h.used == 7 {
                        l = 4
                } else if h.used == 15 {
                        l = 5
                }
                _, err = h.w.Write(h.buf[:l])
                if err != nil {
                        return
                }
                h.used++
        }
        h.rightChars[nBytes] = '|'
        h.rightChars[nBytes+1] = '\n'
        _, err = h.w.Write(h.rightChars[:nBytes+2])
        return
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.