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 }