github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgGoSource/kmgGoParser/string.go (about)

     1  package kmgGoParser
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/bronze1man/kmg/kmgGoSource/kmgGoReader"
     7  	"strconv"
     8  )
     9  
    10  // 可以读这两种 "abc" `abc` ,返回这个东西实际存放的信息.
    11  func MustReadGoString(r *kmgGoReader.Reader) (output []byte) {
    12  	b := r.ReadByte()
    13  	if b == '"' {
    14  		buf := &bytes.Buffer{}
    15  		for {
    16  			if r.IsEof() {
    17  				panic(r.GetFileLineInfo() + " unexcept EOF " + buf.String())
    18  			}
    19  			b := r.ReadByte()
    20  			switch b {
    21  			case '"':
    22  				return buf.Bytes()
    23  			case '\\':
    24  				handleSlashInGoChar(r, buf)
    25  			default:
    26  				buf.WriteByte(b)
    27  			}
    28  		}
    29  	} else if b == '`' {
    30  		return r.ReadUntilByte('`')
    31  	} else {
    32  		panic(fmt.Errorf("%s unexcept byte %d '%s'", r.GetFileLineInfo(), b, string(rune(b))))
    33  	}
    34  }
    35  
    36  // 可以读 '"' 这种,返回这个东西实际占的字节数据
    37  func mustReadGoChar(r *kmgGoReader.Reader) []byte {
    38  	b := r.ReadByte()
    39  	if b != '\'' {
    40  		panic(r.GetFileLineInfo() + " unexcept byte " + strconv.Itoa(int(b)))
    41  	}
    42  	buf := &bytes.Buffer{}
    43  	run := r.ReadRune()
    44  	if run == '\\' {
    45  		handleSlashInGoChar(r, buf)
    46  	} else {
    47  		buf.WriteRune(run)
    48  	}
    49  	b = r.ReadByte()
    50  	if b != '\'' {
    51  		panic(r.GetFileLineInfo() + " unexcept byte " + strconv.Itoa(int(b)))
    52  	}
    53  	return buf.Bytes()
    54  }
    55  
    56  // 此处已经读过了 /
    57  func handleSlashInGoChar(r *kmgGoReader.Reader, buf *bytes.Buffer) {
    58  	if r.IsEof() {
    59  		panic(r.GetFileLineInfo() + " unexcept EOF")
    60  	}
    61  	b := r.ReadByte()
    62  	switch b {
    63  	case '0', '1', '2', '3', '4', '5', '6', '7':
    64  		r.UnreadByte()
    65  		octal := r.MustReadWithSize(3)
    66  		b64, err := strconv.ParseUint(string(octal), 8, 8)
    67  		if err != nil {
    68  			panic(r.GetFileLineInfo() + " " + err.Error())
    69  		}
    70  		buf.WriteByte(byte(b64))
    71  	case 'x':
    72  		octal := r.MustReadWithSize(2)
    73  		b64, err := strconv.ParseUint(string(octal), 16, 8)
    74  		if err != nil {
    75  			panic(r.GetFileLineInfo() + " " + err.Error())
    76  		}
    77  		buf.WriteByte(byte(b64))
    78  	case 'u':
    79  		octal := r.MustReadWithSize(4)
    80  		b64, err := strconv.ParseUint(string(octal), 16, 16)
    81  		if err != nil {
    82  			panic(r.GetFileLineInfo() + " " + err.Error())
    83  		}
    84  		buf.WriteRune(rune(b64))
    85  	case 'U':
    86  		octal := r.MustReadWithSize(8)
    87  		b64, err := strconv.ParseUint(string(octal), 16, 32)
    88  		if err != nil {
    89  			panic(r.GetFileLineInfo() + " " + err.Error())
    90  		}
    91  		buf.WriteRune(rune(b64))
    92  	case 'a':
    93  		buf.WriteByte('\a')
    94  	case 'b':
    95  		buf.WriteByte('\b')
    96  	case 'f':
    97  		buf.WriteByte('\f')
    98  	case 'n':
    99  		buf.WriteByte('\n')
   100  	case 'r':
   101  		buf.WriteByte('\r')
   102  	case 't':
   103  		buf.WriteByte('\t')
   104  	case 'v':
   105  		buf.WriteByte('\v')
   106  	case '\\':
   107  		buf.WriteByte('\\')
   108  	case '\'':
   109  		buf.WriteByte('\'')
   110  	case '"':
   111  		buf.WriteByte('"')
   112  	default:
   113  		panic(r.GetFileLineInfo() + " unexcept byte " + strconv.Itoa(int(b)))
   114  	}
   115  }