Example #1
0
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
}
Example #2
0
// 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
}
Example #3
0
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))
}
Example #4
0
func main() {
	s := []byte("123456789")
	f := func(r rune) bool {
		return r < '4'
	}
	fmt.Println(string(bytes.TrimLeftFunc(s, f)))
}
Example #5
0
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)
}
Example #6
0
//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
}
Example #7
0
// 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
}
Example #8
0
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)
}
Example #9
0
// 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...)
}
Example #10
0
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()
}
Example #11
0
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),
	)
}
Example #12
0
// 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)
}
Example #13
0
//<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
}
Example #14
0
// 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()
}
Example #15
0
// 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
}
Example #16
0
// 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
}
Example #17
0
// 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)
	}
}
Example #18
0
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
}
Example #19
0
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)
		}
	}
}
Example #20
0
// 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
}
Example #21
0
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
		}
	}
}
Example #22
0
File: ini.go Project: dulumao/gsgo
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

}