func consumeParam(v []byte) (param, value, rest []byte) { param, rest = consumeToken(v) param = bytes.ToLower(param) if param == nil { return nil, nil, v } rest = bytes.TrimLeftFunc(rest, unicode.IsSpace) if len(rest) == 0 || rest[0] != '=' { return nil, nil, v } rest = rest[1:] // consume equals sign rest = bytes.TrimLeftFunc(rest, unicode.IsSpace) if len(rest) == 0 { return nil, nil, v } if rest[0] != '"' { value, rest = consumeToken(rest) } else { value, rest = consumeValue(rest) } if value == nil { return nil, nil, v } return param, value, rest }
// Parse parses a Link header value into a slice of Links. It does not currently // implement RFC 2231 handling of non-ASCII character encoding and language // information. func Parse(l string) ([]Link, error) { v := []byte(l) v = bytes.TrimSpace(v) if len(v) == 0 { return nil, nil } links := make([]Link, 0, 1) for len(v) > 0 { if v[0] != '<' { return nil, errors.New("link: does not start with <") } lend := bytes.IndexByte(v, '>') if lend == -1 { return nil, errors.New("link: does not contain ending >") } params := make(map[string]string) link := Link{URI: string(v[1:lend]), Params: params} links = append(links, link) // trim off parsed url v = v[lend+1:] if len(v) == 0 { break } v = bytes.TrimLeftFunc(v, unicode.IsSpace) for len(v) > 0 { if v[0] != ';' && v[0] != ',' { return nil, errors.New(`link: expected ";" or "'", got "` + string(v[0:1]) + `"`) } var next bool if v[0] == ',' { next = true } v = bytes.TrimLeftFunc(v[1:], unicode.IsSpace) if next || len(v) == 0 { break } var key, value []byte key, value, v = consumeParam(v) if key == nil || value == nil { return nil, errors.New("link: malformed param") } if k := string(key); k == "rel" { if links[len(links)-1].Rel == "" { links[len(links)-1].Rel = string(value) } } else { params[k] = string(value) } v = bytes.TrimLeftFunc(v, unicode.IsSpace) } } return links, nil }
func EncodeKey(key []byte) string { // we do sloppy work and process safe bytes only at the beginning // and end; this avoids many false positives in large binary data var left, middle, right string { mid := bytes.TrimLeftFunc(key, isSafe) if len(key)-len(mid) > prettyTheshold { left = string(key[:len(key)-len(mid)]) + string(FragSeparator) key = mid } } { mid := bytes.TrimRightFunc(key, isSafe) if len(key)-len(mid) > prettyTheshold { right = string(FragSeparator) + string(key[len(mid):]) key = mid } } if len(key) > 0 { middle = "@" + hex.EncodeToString(key) } return strings.Trim(left+middle+right, string(FragSeparator)) }
func main() { s := []byte("123456789") f := func(r rune) bool { return r < '4' } fmt.Println(string(bytes.TrimLeftFunc(s, f))) }
func main() { whitespace := " \t\r\n" padded := []byte(" \t\r\n\r\n\r\n hello!!! \t\t\t\t") trimmed := bytes.Trim(padded, whitespace) log.Printf("Trim removed runes in %q from the ends of %q to produce %q", whitespace, padded, trimmed) rhyme := []byte("aabbccddee") trimFunced := bytes.TrimFunc(rhyme, trimOdd) log.Printf("TrimFunc removed 'odd' runes from %q to produce %q", rhyme, trimFunced) leftTrimmed := bytes.TrimLeft(padded, whitespace) log.Printf("TrimLeft removed runes in %q from the left side of %q to produce %q", whitespace, padded, leftTrimmed) leftTrimFunced := bytes.TrimLeftFunc(rhyme, trimOdd) log.Printf("TrimLeftFunc removed 'odd' runes from the left side of %q to produce %q", rhyme, leftTrimFunced) rightTrimmed := bytes.TrimRight(padded, whitespace) log.Printf("TrimRight removed runes in %q from the right side of %q to produce %q", whitespace, padded, rightTrimmed) rightTrimFunced := bytes.TrimRightFunc(rhyme, trimOdd) log.Printf("TrimRightFunc removed 'odd' runes from the right side of %q to produce %q", rhyme, rightTrimFunced) spaceTrimmed := bytes.TrimSpace(padded) log.Printf("TrimSpace trimmed all whitespace from the ends of %q to produce %q", padded, spaceTrimmed) }
//isJSON checks the file for an opening brace //to determine if it is a json file or not func isJSON(data []byte) bool { spacesRemoved := bytes.TrimLeftFunc(data, unicode.IsSpace) prefix := []byte("{") if bytes.HasPrefix(spacesRemoved, prefix) { return true } return false }
// ParseFile creates a new Config and parses the file configuration from the // named file. func LoadConfig(name string) (*Config, error) { file, err := os.Open(name) if err != nil { return nil, err } cfg := &Config{ file.Name(), make(map[int][]string), make(map[string]string), make(map[string]int64), sync.RWMutex{}, } cfg.Lock() defer cfg.Unlock() defer file.Close() var comment bytes.Buffer buf := bufio.NewReader(file) for nComment, off := 0, int64(1); ; { line, _, err := buf.ReadLine() if err == io.EOF { break } if bytes.Equal(line, bEmpty) { continue } off += int64(len(line)) if bytes.HasPrefix(line, bComment) { line = bytes.TrimLeft(line, "#") line = bytes.TrimLeftFunc(line, unicode.IsSpace) comment.Write(line) comment.WriteByte('\n') continue } if comment.Len() != 0 { cfg.comment[nComment] = []string{comment.String()} comment.Reset() nComment++ } val := bytes.SplitN(line, bEqual, 2) if bytes.HasPrefix([]byte(strings.TrimSpace(string(val[1]))), bDQuote) { val[1] = bytes.Trim([]byte(strings.TrimSpace(string(val[1]))), `"`) } key := strings.TrimSpace(string(val[0])) cfg.comment[nComment-1] = append(cfg.comment[nComment-1], key) cfg.data[key] = strings.TrimSpace(string(val[1])) cfg.offset[key] = off } AppConf = cfg return cfg, nil }
func formatVal(val driver.Value) string { switch t := val.(type) { case nil: return "NULL" case []byte: // We don't escape strings that contain only printable ASCII characters. if len(bytes.TrimLeftFunc(t, func(r rune) bool { return r >= 0x20 && r < 0x80 })) == 0 { return string(t) } // We use %+q to ensure the output contains only ASCII (see issue #4315). return fmt.Sprintf("%+q", t) } return fmt.Sprint(val) }
// SuppressHtmlHeaders writes only the first line of html headers. func SuppressHtmlHeaders(w WriteFramer, s *Sniffer, dataIn ...[]byte) error { data := join(dataIn...) // If the first line contains HTTP data = bytes.TrimLeftFunc(data, unicode.IsSpace) splits := bytes.SplitN(data, []byte("\r\n"), 2) if len(splits) > 1 && bytes.Contains(splits[0], []byte("HTTP/1.")) { // Get rid of everything through the double line headerBody := bytes.SplitN(splits[1], []byte("\r\n\r\n"), 2) first := splits[0] var rest []byte if len(headerBody) > 1 { rest = headerBody[1] } return w.WriteFrame(s, first, []byte("\n"), rest) } return w.WriteFrame(s, dataIn...) }
func minifyReadFile(file string) []byte { f, err := os.Open(file) if err != nil { log.Fatalln(err) } defer f.Close() var lastLineEnd byte var partMark int var r = bufio.NewReader(f) var buf = new(bytes.Buffer) for { line, part, err := r.ReadLine() if part { partMark++ } else if partMark > 0 { partMark = -1 } else { partMark = 0 } if len(line) > 0 { switch partMark { case 0: line = bytes.TrimSpace(line) case 1: line = bytes.TrimLeftFunc(line, unicode.IsSpace) default: if partMark < 0 { partMark = 0 line = bytes.TrimRightFunc(line, unicode.IsSpace) } } buf.Write(line) lastLineEnd = line[len(line)-1] } if err != nil && r.Buffered() == 0 { break } } // make sure line end with \n if lastLineEnd != '\n' { buf.WriteByte('\n') } return buf.Bytes() }
func EncodeKey(key []byte) string { // we do sloppy work and process safe bytes only at the beginning // and end; this avoids many false positives in large binary data var left, right []byte var middle string if key[0] != '.' { mid := bytes.TrimLeftFunc(key, isSafe) if len(key)-len(mid) > prettyTheshold { left = key[:len(key)-len(mid)] key = mid } } { mid := bytes.TrimRightFunc(key, isSafe) if len(mid) == 0 && len(key) > 0 && key[0] == '.' { // don't let right safe zone reach all the way to leading dot mid = key[:1] } if len(key)-len(mid) > prettyTheshold { right = key[len(mid):] key = mid } } if len(key) > 0 { middle = "@" + hex.EncodeToString(key) } return strings.Trim( string(left)+string(FragSeparator)+middle+string(FragSeparator)+string(right), string(FragSeparator), ) }
// Return true if the first non-whitespace bytes in buf is // prefix. func hasPrefix(buf []byte, prefix []byte) bool { trim := bytes.TrimLeftFunc(buf, unicode.IsSpace) return bytes.HasPrefix(trim, prefix) }
//<xml> // <ToUserName><![CDATA[gh_b1eb3f8bd6c6]]></ToUserName> // <Encrypt><![CDATA[DlCGq+lWQuyjNNK+vDaO0zUltpdUW3u4V00WCzsdNzmZGEhrU7TPxG52viOKCWYPwTMbCzgbCtakZHyNxr5hjoZJ7ORAUYoIAGQy/LDWtAnYgDO+ppKLp0rDq+67Dv3yt+vatMQTh99NII6x9SEGpY3O2h8RpG99+NYevQiOLVKqiQYzan21sX/jE4Y3wZaeudsb4QVjqzRAPaCJ5nS3T31uIR9fjSRgHTDRDOzjQ1cHchge+t6faUhniN5VQVTE+wIYtmnejc55BmHYPfBnTkYah9+cTYnI3diUPJRRiyVocJyHlb+XOZN22dsx9yzKHBAyagaoDIV8Yyb/PahcUbsqGv5wziOgLJQIa6z93/VY7d2Kq2C2oBS+Qb+FI9jLhgc3RvCi+Yno2X3cWoqbsRwoovYdyg6jme/H7nMZn77PSxOGRt/dYiWx2NuBAF7fNFigmbRiive3DyOumNCMvA==]]></Encrypt> //</xml> func xmlUnmarshal(data []byte, p *cipherRequestHttpBody) error { data = bytes.TrimSpace(data) if !bytes.HasPrefix(data, msgStartElementLiteral) || !bytes.HasSuffix(data, msgEndElementLiteral) { log.Printf("[WARNING] xmlUnmarshal failed, data:\n%s\n", data) return xml.Unmarshal(data, p) } data2 := data[len(msgStartElementLiteral) : len(data)-len(msgEndElementLiteral)] // ToUserName ToUserNameElementBytes := data2 i := bytes.Index(ToUserNameElementBytes, msgToUserNameStartElementLiteral) if i == -1 { log.Printf("[WARNING] xmlUnmarshal failed, data:\n%s\n", data) return xml.Unmarshal(data, p) } ToUserNameElementBytes = ToUserNameElementBytes[i+len(msgToUserNameStartElementLiteral):] ToUserNameElementBytes = bytes.TrimLeftFunc(ToUserNameElementBytes, unicode.IsSpace) if !bytes.HasPrefix(ToUserNameElementBytes, cdataStartLiteral) { log.Printf("[WARNING] xmlUnmarshal failed, data:\n%s\n", data) return xml.Unmarshal(data, p) } ToUserNameElementBytes = ToUserNameElementBytes[len(cdataStartLiteral):] i = bytes.Index(ToUserNameElementBytes, cdataEndLiteral) if i == -1 { log.Printf("[WARNING] xmlUnmarshal failed, data:\n%s\n", data) return xml.Unmarshal(data, p) } ToUserName := ToUserNameElementBytes[:i] ToUserNameElementBytes = ToUserNameElementBytes[i+len(cdataEndLiteral):] ToUserNameElementBytes = bytes.TrimLeftFunc(ToUserNameElementBytes, unicode.IsSpace) if !bytes.HasPrefix(ToUserNameElementBytes, msgToUserNameEndElementLiteral) { log.Printf("[WARNING] xmlUnmarshal failed, data:\n%s\n", data) return xml.Unmarshal(data, p) } ToUserNameElementBytes = ToUserNameElementBytes[len(msgToUserNameEndElementLiteral):] // Encrypt EncryptElementBytes := ToUserNameElementBytes i = bytes.Index(EncryptElementBytes, msgEncryptStartElementLiteral) if i == -1 { EncryptElementBytes = data2 i = bytes.Index(EncryptElementBytes, msgEncryptStartElementLiteral) if i == -1 { log.Printf("[WARNING] xmlUnmarshal failed, data:\n%s\n", data) return xml.Unmarshal(data, p) } } EncryptElementBytes = EncryptElementBytes[i+len(msgEncryptStartElementLiteral):] EncryptElementBytes = bytes.TrimLeftFunc(EncryptElementBytes, unicode.IsSpace) if !bytes.HasPrefix(EncryptElementBytes, cdataStartLiteral) { log.Printf("[WARNING] xmlUnmarshal failed, data:\n%s\n", data) return xml.Unmarshal(data, p) } EncryptElementBytes = EncryptElementBytes[len(cdataStartLiteral):] i = bytes.Index(EncryptElementBytes, cdataEndLiteral) if i == -1 { log.Printf("[WARNING] xmlUnmarshal failed, data:\n%s\n", data) return xml.Unmarshal(data, p) } Encrypt := EncryptElementBytes[:i] EncryptElementBytes = EncryptElementBytes[i+len(cdataEndLiteral):] EncryptElementBytes = bytes.TrimLeftFunc(EncryptElementBytes, unicode.IsSpace) if !bytes.HasPrefix(EncryptElementBytes, msgEncryptEndElementLiteral) { log.Printf("[WARNING] xmlUnmarshal failed, data:\n%s\n", data) return xml.Unmarshal(data, p) } p.ToUserName = string(ToUserName) p.Base64EncryptedMsg = Encrypt return nil }
// PrettyPrint returns the value in a human readable format. // e.g. `Put /Table/51/1/1/0 -> /TUPLE/2:2:Int/7/1:3:Float/6.28` // In `1:3:Float/6.28`, the `1` is the column id diff as stored, `3` is the // computed (i.e. not stored) actual column id, `Float` is the type, and `6.28` // is the encoded value. func (v Value) PrettyPrint() string { var buf bytes.Buffer t := v.GetTag() buf.WriteRune('/') buf.WriteString(t.String()) buf.WriteRune('/') var err error switch t { case ValueType_TUPLE: b := v.dataBytes() var colID uint32 for i := 0; len(b) > 0; i++ { if i != 0 { buf.WriteRune('/') } _, _, colIDDiff, typ, err := encoding.DecodeValueTag(b) if err != nil { break } colID += colIDDiff var s string b, s, err = encoding.PrettyPrintValueEncoded(b) if err != nil { break } fmt.Fprintf(&buf, "%d:%d:%s/%s", colIDDiff, colID, typ, s) } case ValueType_INT: var i int64 i, err = v.GetInt() buf.WriteString(strconv.FormatInt(i, 10)) case ValueType_FLOAT: var f float64 f, err = v.GetFloat() buf.WriteString(strconv.FormatFloat(f, 'g', -1, 64)) case ValueType_BYTES: var data []byte data, err = v.GetBytes() printable := len(bytes.TrimLeftFunc(data, unicode.IsPrint)) == 0 if printable { buf.WriteString(string(data)) } else { buf.WriteString(hex.EncodeToString(data)) } case ValueType_TIME: var t time.Time t, err = v.GetTime() buf.WriteString(t.UTC().Format(time.RFC3339Nano)) case ValueType_DECIMAL: var d *inf.Dec d, err = v.GetDecimal() buf.WriteString(d.String()) case ValueType_DURATION: var d duration.Duration d, err = v.GetDuration() buf.WriteString(d.String()) default: err = errors.Errorf("unknown tag: %s", t) } if err != nil { // Ignore the contents of buf and return directly. return fmt.Sprintf("/<err: %s>", err) } return buf.String() }
// parse parses data through an io.Reader. func (f *File) parse(reader io.Reader) (err error) { p := newParser(reader) if err = p.BOM(); err != nil { return fmt.Errorf("BOM: %v", err) } // Ignore error because default section name is never empty string. section, _ := f.NewSection(DEFAULT_SECTION) var line []byte for !p.isEOF { line, err = p.readUntil('\n') if err != nil { return err } line = bytes.TrimLeftFunc(line, unicode.IsSpace) if len(line) == 0 { continue } // Comments if line[0] == '#' || line[0] == ';' { // Note: we do not care ending line break, // it is needed for adding second line, // so just clean it once at the end when set to value. p.comment.Write(line) continue } // Section if line[0] == '[' { // Read to the next ']' (TODO: support quoted strings) closeIdx := bytes.IndexByte(line, ']') if closeIdx == -1 { return fmt.Errorf("unclosed section: %s", line) } section, err = f.NewSection(string(line[1:closeIdx])) if err != nil { return err } comment, has := cleanComment(line[closeIdx+1:]) if has { p.comment.Write(comment) } section.Comment = strings.TrimSpace(p.comment.String()) // Reset aotu-counter and comments p.comment.Reset() p.count = 1 continue } kname, offset, err := readKeyName(line) if err != nil { return err } // Auto increment. isAutoIncr := false if kname == "-" { isAutoIncr = true kname = "#" + strconv.Itoa(p.count) p.count++ } key, err := section.NewKey(kname, "") if err != nil { return err } key.isAutoIncr = isAutoIncr value, err := p.readValue(line[offset:]) if err != nil { return err } key.SetValue(value) key.Comment = strings.TrimSpace(p.comment.String()) p.comment.Reset() } return nil }
// ParseFile creates a new Config and parses the file configuration from the // named file. func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { file, err := os.Open(name) if err != nil { return nil, err } cfg := &IniConfigContainer{ file.Name(), make(map[string]map[string]string), make(map[string]string), make(map[string]string), sync.RWMutex{}, } cfg.Lock() defer cfg.Unlock() defer file.Close() var comment bytes.Buffer buf := bufio.NewReader(file) section := DEFAULT_SECTION for { line, _, err := buf.ReadLine() if err == io.EOF { break } if bytes.Equal(line, bEmpty) { continue } line = bytes.TrimSpace(line) var bComment []byte switch { case bytes.HasPrefix(line, bNumComment): bComment = bNumComment case bytes.HasPrefix(line, bSemComment): bComment = bSemComment } if bComment != nil { line = bytes.TrimLeft(line, string(bComment)) line = bytes.TrimLeftFunc(line, unicode.IsSpace) comment.Write(line) comment.WriteByte('\n') continue } if bytes.HasPrefix(line, sectionStart) && bytes.HasSuffix(line, sectionEnd) { section = string(line[1 : len(line)-1]) section = strings.ToLower(section) // section name case insensitive if comment.Len() > 0 { cfg.sectionComment[section] = comment.String() comment.Reset() } if _, ok := cfg.data[section]; !ok { cfg.data[section] = make(map[string]string) } } else { if _, ok := cfg.data[section]; !ok { cfg.data[section] = make(map[string]string) } keyval := bytes.SplitN(line, bEqual, 2) val := bytes.TrimSpace(keyval[1]) if bytes.HasPrefix(val, bDQuote) { val = bytes.Trim(val, `"`) } key := string(bytes.TrimSpace(keyval[0])) // key name case insensitive key = strings.ToLower(key) cfg.data[section][key] = string(val) if comment.Len() > 0 { cfg.keycomment[section+"."+key] = comment.String() comment.Reset() } } } return cfg, nil }
// PrettyPrintValueEncoded returns a string representation of the first // decodable value in the provided byte slice, along with the remaining byte // slice after decoding. func PrettyPrintValueEncoded(b []byte) ([]byte, string, error) { _, dataOffset, _, typ, err := DecodeValueTag(b) if err != nil { return b, "", err } switch typ { case Null: b = b[dataOffset:] return b, "NULL", nil case True: b = b[dataOffset:] return b, "true", nil case False: b = b[dataOffset:] return b, "false", nil case Int: var i int64 b, i, err = DecodeIntValue(b) if err != nil { return b, "", err } return b, strconv.FormatInt(i, 10), nil case Float: var f float64 b, f, err = DecodeFloatValue(b) if err != nil { return b, "", err } return b, strconv.FormatFloat(f, 'g', -1, 64), nil case Decimal: var d *inf.Dec b, d, err = DecodeDecimalValue(b) if err != nil { return b, "", err } return b, d.String(), nil case Bytes: var data []byte b, data, err = DecodeBytesValue(b) if err != nil { return b, "", err } printable := len(bytes.TrimLeftFunc(data, unicode.IsPrint)) == 0 if printable { return b, string(data), nil } return b, hex.EncodeToString(data), nil case Time: var t time.Time b, t, err = DecodeTimeValue(b) if err != nil { return b, "", err } return b, t.UTC().Format(time.RFC3339Nano), nil case Duration: var d duration.Duration b, d, err = DecodeDurationValue(b) if err != nil { return b, "", err } return b, d.String(), nil default: return b, "", errors.Errorf("unknown type %s", typ) } }
func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) { file, err := os.Open(name) if err != nil { return nil, err } cfg := &IniConfigContainer{ file.Name(), make(map[string]map[string]string), make(map[string]string), make(map[string]string), sync.RWMutex{}, } cfg.Lock() defer cfg.Unlock() defer file.Close() var comment bytes.Buffer buf := bufio.NewReader(file) // check the BOM head, err := buf.Peek(3) if err == nil && head[0] == 239 && head[1] == 187 && head[2] == 191 { for i := 1; i <= 3; i++ { buf.ReadByte() } } section := DEFAULT_SECTION for { line, _, err := buf.ReadLine() if err == io.EOF { break } if bytes.Equal(line, bEmpty) { continue } line = bytes.TrimSpace(line) var bComment []byte switch { case bytes.HasPrefix(line, bNumComment): bComment = bNumComment case bytes.HasPrefix(line, bSemComment): bComment = bSemComment } if bComment != nil { line = bytes.TrimLeft(line, string(bComment)) line = bytes.TrimLeftFunc(line, unicode.IsSpace) comment.Write(line) comment.WriteByte('\n') continue } if bytes.HasPrefix(line, sectionStart) && bytes.HasSuffix(line, sectionEnd) { section = strings.ToLower(string(line[1 : len(line)-1])) // section name case insensitive if comment.Len() > 0 { cfg.sectionComment[section] = comment.String() comment.Reset() } if _, ok := cfg.data[section]; !ok { cfg.data[section] = make(map[string]string) } continue } if _, ok := cfg.data[section]; !ok { cfg.data[section] = make(map[string]string) } keyValue := bytes.SplitN(line, bEqual, 2) key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive key = strings.ToLower(key) // handle include "other.conf" if len(keyValue) == 1 && strings.HasPrefix(key, "include") { includefiles := strings.Fields(key) if includefiles[0] == "include" && len(includefiles) == 2 { otherfile := strings.Trim(includefiles[1], "\"") if !path.IsAbs(otherfile) { otherfile = path.Join(path.Dir(name), otherfile) } i, err := ini.parseFile(otherfile) if err != nil { return nil, err } for sec, dt := range i.data { if _, ok := cfg.data[sec]; !ok { cfg.data[sec] = make(map[string]string) } for k, v := range dt { cfg.data[sec][k] = v } } for sec, comm := range i.sectionComment { cfg.sectionComment[sec] = comm } for k, comm := range i.keyComment { cfg.keyComment[k] = comm } continue } } if len(keyValue) != 2 { return nil, errors.New("read the content error: \"" + string(line) + "\", should key = val") } val := bytes.TrimSpace(keyValue[1]) if bytes.HasPrefix(val, bDQuote) { val = bytes.Trim(val, `"`) } cfg.data[section][key] = string(val) if comment.Len() > 0 { cfg.keyComment[section+"."+key] = comment.String() comment.Reset() } } return cfg, nil }
func main() { var rf *os.File var iLen int var Ver byte if len(os.Args) != 2 { fmt.Printf("Please input mp3 filename\n") return } if path.Ext(os.Args[1]) != ".mp3" { fmt.Printf("Do not support this file format [%s]\n", path.Ext(os.Args[1])) return } if v, err := os.Open(os.Args[1]); err != nil { fmt.Printf("Error: %v\n", err) } else { rf = v } defer rf.Close() buffer := make([]byte, 10) if n, err := rf.Read(buffer); err != nil { fmt.Printf("Error: %v\n", err) return } else { iLen = n } Ver = '1' if isAtHeadOfMP3(buffer[:iLen]) { Ver = '2' } fi, err := rf.Stat() if err != nil { fmt.Printf("Error: %v\n", err) return } if Ver == '2' { if buffer[3] != 0x03 { fmt.Printf("Only support Version IDV3 Version 2.3\n") return } iLen := uint32(buffer[6]&0x7f)<<21 | uint32(buffer[7]&0x7f)<<14 | uint32(buffer[8]&0x7f)<<7 | uint32(buffer[9]&0x7f) - 10 bufferIn := make([]byte, int(iLen)) if n, err := rf.Read(bufferIn); err != nil { fmt.Printf("Error: %v\n", err) return } else { if n != len(bufferIn) { fmt.Printf("Error: File is Bad\n") return } i := 0 iCount := 0 // println("#####", n, "#####") // k := 0 for i < n { if bufferIn[i] == 0x0 { i++ continue } j := i + 4 iCount = i iLen := uint32(bufferIn[j])<<24 | uint32(bufferIn[j+1])<<16 | uint32(bufferIn[j+2])<<8 | uint32(bufferIn[j+3]) x := string(bufferIn[iCount : iCount+4]) tLen := int(iLen) bufferTmp := bytes.TrimLeftFunc(bufferIn[i+10:i+10+tLen], func(r rune) bool { return r == 0x00 || r == 0x01 }) if bufferTmp == nil { i += 10 + tLen continue } switch x { case "TIT2": outLen := 0 bufferOut := make([]byte, len(bufferTmp)*4) if err := iconv.ConvertGBKToUTF8(bufferTmp, len(bufferTmp), bufferOut, &outLen); err != nil { byteCopy(bufferOut, bufferTmp, len(bufferTmp)) outLen = len(bufferTmp) } fmt.Printf("标题: %s\n", string(bufferOut[:outLen])) case "TPE1": outLen := 0 bufferOut := make([]byte, len(bufferTmp)*4) if err := iconv.ConvertGBKToUTF8(bufferTmp, len(bufferTmp), bufferOut, &outLen); err != nil { byteCopy(bufferOut, bufferTmp, len(bufferTmp)) outLen = len(bufferTmp) } fmt.Printf("作者: %s\n", string(bufferOut[:outLen])) case "TALB": outLen := 0 bufferOut := make([]byte, len(bufferTmp)*4) if err := iconv.ConvertGBKToUTF8(bufferTmp, len(bufferTmp), bufferOut, &outLen); err != nil { byteCopy(bufferOut, bufferTmp, len(bufferTmp)) outLen = len(bufferTmp) } fmt.Printf("专辑名: %s\n", string(bufferOut[:outLen])) case "TYER": outLen := 0 bufferOut := make([]byte, len(bufferTmp)*4) if err := iconv.ConvertGBKToUTF8(bufferTmp, len(bufferTmp), bufferOut, &outLen); err != nil { byteCopy(bufferOut, bufferTmp, len(bufferTmp)) outLen = len(bufferTmp) } fmt.Printf("发行年份: %s\n", string(bufferOut[:outLen])) case "TCON": outLen := 0 bufferOut := make([]byte, len(bufferTmp)*4) if err := iconv.ConvertGBKToUTF8(bufferTmp, len(bufferTmp), bufferOut, &outLen); err != nil { byteCopy(bufferOut, bufferTmp, len(bufferTmp)) outLen = len(bufferTmp) } fmt.Printf("类型: %s\n", string(bufferOut[:outLen])) case "COMM": outLen := 0 bufferOut := make([]byte, len(bufferTmp)*4) if err := iconv.ConvertGBKToUTF8(bufferTmp, len(bufferTmp), bufferOut, &outLen); err != nil { byteCopy(bufferOut, bufferTmp, len(bufferTmp)) outLen = len(bufferTmp) } fmt.Printf("备注信息: %s\n", string(bufferOut[:outLen])) } i += 10 + tLen /*println(i, "|", iLen) k++ if k == 25 { break }*/ } } } else { lPos := fi.Size() - 128 bufferIn := make([]byte, 128) byteSet(bufferIn, 0, len(bufferIn)) bufferOut := make([]byte, 1024) if n, err := rf.ReadAt(bufferIn, lPos); err != nil { fmt.Printf("Error: %v\n", err) return } else { iLen = n } if !bytes.Equal(bufferIn[:3], []byte("TAG")) { fmt.Printf("This file no idv3 information\n") return } outLen := 0 if err := iconv.ConvertGBKToUTF8(bufferIn[3:33], 30, bufferOut, &outLen); err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("标题: %s\n", string(bufferOut[:outLen])) outLen = 0 byteSet(bufferOut, 0, len(bufferOut)) if err := iconv.ConvertGBKToUTF8(bufferIn[33:63], 30, bufferOut, &outLen); err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("演唱/奏者: %s\n", string(bufferOut[:outLen])) outLen = 0 byteSet(bufferOut, 0, len(bufferOut)) if err := iconv.ConvertGBKToUTF8(bufferIn[63:93], 30, bufferOut, &outLen); err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("专辑名: %s\n", string(bufferOut[:outLen])) outLen = 0 byteSet(bufferOut, 0, len(bufferOut)) if err := iconv.ConvertGBKToUTF8(bufferIn[93:97], 4, bufferOut, &outLen); err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("发行年份: %s\n", string(bufferOut[:outLen])) outLen = 0 byteSet(bufferOut, 0, len(bufferOut)) if err := iconv.ConvertGBKToUTF8(bufferIn[97:127], 30, bufferOut, &outLen); err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("备注信息: %s\n", string(bufferOut[:outLen])) if v, ok := LPInfo[bufferIn[127]]; !ok { fmt.Printf("流派: %s\n", "未知") } else { fmt.Printf("流派: %s\n", v) } } }
// Read trims off any unicode whitespace from the originating reader func (tr trimReader) Read(buf []byte) (int, error) { n, err := tr.rd.Read(buf) t := bytes.TrimLeftFunc(buf[:n], unicode.IsSpace) n = copy(buf, t) return n, err }
func (p *parser) NextValue() (*parseValue, error) { result := new(parseValue) inValue := false for { rawLine, err := p.nextLine() // make copy rawLine = append([]byte{}, rawLine...) if err == io.EOF && inValue { // will return EOF on next read return result, nil } else if err != nil { return result, err } // strip trailing whitespace line := bytes.TrimRightFunc(rawLine, unicode.IsSpace) if inValue { if len(line) == 0 || !startsWithSpace(line) { // leave p.bufLine intact for next call return result, nil } result.value = append(result.value, '\n') result.value = append(result.value, bytes.TrimLeftFunc(line, unicode.IsSpace)...) result.addRawLine(rawLine) // we crossed the line, so mark it zero p.bufLine = nil } else if len(line) > 0 { result.lineNum = p.lineNum switch line[0] { case ';': result.entryType = entryTypeComment result.addRawLine(rawLine) p.bufLine = nil return result, nil case '[': if line[len(line)-1] != ']' { return nil, newParseError(ErrInvalidSection, p.lineNum) } result.entryType = entryTypeSection result.section = strings.TrimFunc(string(line[1:len(line)-1]), unicode.IsSpace) result.addRawLine(rawLine) p.bufLine = nil return result, nil default: kv := bytes.SplitN(line, []byte("="), 2) if len(kv) != 2 { return nil, newParseError(ErrInvalidEntry, p.lineNum) } result.entryType = entryTypeKV result.key = string(bytes.TrimRightFunc(kv[0], unicode.IsSpace)) value := bytes.TrimLeftFunc(kv[1], unicode.IsSpace) result.value = append([]byte{}, value...) result.addRawLine(rawLine) // the next line may be a continuation of this value inValue = true p.bufLine = nil } } else { // empty line result.entryType = entryTypeBlank result.addRawLine([]byte("")) p.bufLine = nil return result, nil } } }
func (ini *IniConfig) parseFile(name string) (ConfigManager, error) { file, err := os.Open(name) if err != nil { return nil, err } cfg := &IniConfigManager{filename: file.Name(), data: make(map[string]map[string]string), sectionComment: make(map[string]string), keyComment: make(map[string]string), RWMutex: sync.RWMutex{}, } cfg.Lock() defer cfg.Unlock() defer file.Close() var comment bytes.Buffer //需要将注解记录下来,回写的时候有用 buf := bufio.NewReader(file) head, err := buf.Peek(3) if err == nil && head[0] == 239 && head[1] == 187 && head[2] == 191 { for i := 1; i <= 3; i++ { buf.ReadByte() } } section := DEFAULT_SECTION for { line, _, err := buf.ReadLine() if err == io.EOF { break } if bytes.Equal(line, bEmptyFlag) { continue } line = bytes.TrimSpace(line) var bComment bool = false switch { case bytes.HasPrefix(line, bNotesFlag): bComment = true } if bComment { line = bytes.TrimLeft(line, string(bNotesFlag)) line = bytes.TrimLeftFunc(line, unicode.IsSpace) comment.Write(line) comment.WriteByte('\n') continue } if bytes.HasPrefix(line, sectionStartFlag) && bytes.HasSuffix(line, sectionEndFlag) { //new section section = string(line[1 : len(line)-1]) if comment.Len() > 0 { cfg.sectionComment[section] = comment.String() comment.Reset() } if _, ok := cfg.data[section]; !ok { cfg.data[section] = make(map[string]string) } continue } if _, ok := cfg.data[section]; !ok { cfg.data[section] = make(map[string]string) } keyValue := bytes.SplitN(line, bEqualFlag, 2) key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive //key = strings.ToLower(key) if len(keyValue) != 2 { return nil, errors.New("read the content error: \"" + string(line) + "\", should key = val") } val := bytes.TrimSpace(keyValue[1]) if bytes.HasPrefix(val, bDQuoteFlag) { val = bytes.Trim(val, `"`) } cfg.data[section][key] = string(val) if comment.Len() > 0 { cfg.keyComment[section+"::"+key] = comment.String() comment.Reset() } } return cfg, nil }