func parseline(line []byte, i int) (int, int, int, error) { comma := bytes.Index(line, []byte{'#'}) if comma >= 0 { line = line[0:comma] } if l := len(line); l < 4 { return -1, -1, -1, fmt.Errorf("line %d length invalid: %d %q\n", i, l, line) } rl := bytes.TrimSpace(line) rl = re_space.ReplaceAll(rl, []byte{' '}) chs := bytes.Split(rl, []byte{' '}) if len(chs) != 2 { return -1, -1, -1, fmt.Errorf("line %d has %d numbers: %s\n", i, len(chs), rl) } ret, err := strconv.ParseInt(string(bytes.ToLower(chs[0])), 0, 32) if err != nil { return -1, -1, -1, fmt.Errorf("convert %q to int failed at line %d: %s\n", chs[0], i, err) } gb2312 := int(ret) if gb2312 <= 0x7f { return gb2312, gb2312, gb2312, fmt.Errorf("No need convert for ascii 0x%x\n", gb2312) } ret, err = strconv.ParseInt(string(bytes.ToLower(chs[1])), 0, 32) if err != nil { return -1, -1, -1, fmt.Errorf("convert %q to int failed at line %d: %s\n", chs[1], i, err) } unicode := int(ret) utf8 := unicode2utf8(unicode) return gb2312, unicode, utf8, nil }
// Equals reports whether a pattern is identical to another pattern. func (c IgnoreCase) Equals(pat patterns.Pattern) bool { c2, ok := pat.(IgnoreCase) if ok && bytes.Equal(bytes.ToLower(c), bytes.ToLower(c2)) { return true } return false }
func ParseIni(reader io.Reader) (*Config, error) { section, lastKey, cfg := "/", "", make(map[string]string) firstLine, scanner := true, bufio.NewScanner(reader) for scanner.Scan() { s := scanner.Bytes() if firstLine { s = removeUtf8Bom(s) firstLine = false } s = bytes.TrimSpace(s) if len(s) == 0 || s[0] == '#' { // empty or comment continue } if s[0] == '[' && s[len(s)-1] == ']' { // section s = bytes.TrimSpace(s[1 : len(s)-1]) if len(s) >= 0 { section = "/" + string(bytes.ToLower(s)) } continue } k, v := "", "" if i := bytes.IndexByte(s, '='); i != -1 { k = string(bytes.ToLower(bytes.TrimSpace(s[:i]))) v = string(bytes.TrimSpace(s[i+1:])) } if len(k) > 0 { lastKey = section + "/" + k cfg[lastKey] = v continue } else if len(lastKey) == 0 { continue } c, lv := byte(128), cfg[lastKey] if len(lv) > 0 { c = lv[len(lv)-1] } if len(v) == 0 { // empty value means a new line cfg[lastKey] = lv + "\n" } else if c < 128 && c != '-' && v[0] < 128 { // need a white space? // not good enough, but should be ok in most cases cfg[lastKey] = lv + " " + v } else { cfg[lastKey] = lv + v } } if e := scanner.Err(); e != nil { return nil, e } return &Config{data: cfg}, nil }
// PremiumUserHandle user logs + replies func PremiumUserHandle(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) nick := bytes.ToLower([]byte(vars["nick"])) filter := func(line []byte) bool { return bytes.Contains(bytes.ToLower(line), nick) } serveFilteredLogs(w, common.GetConfig().LogPath+"/"+vars["channel"]+"/"+vars["month"], filter) }
func local_ac(view *view) ([]ac_proposal, int) { var dups llrb_tree var others llrb_tree proposals := make([]ac_proposal, 0, 100) prefix := view.cursor.word_under_cursor() // update word caches view.other_buffers(func(buf *buffer) { buf.update_words_cache() }) collect := func(ignorecase bool) { words := view.collect_words([][]byte(nil), &dups, ignorecase) for _, word := range words { proposals = append(proposals, ac_proposal{ display: word, content: word, }) } lprefix := prefix if ignorecase { lprefix = bytes.ToLower(prefix) } view.other_buffers(func(buf *buffer) { buf.words_cache.walk(func(word []byte) { lword := word if ignorecase { lword = bytes.ToLower(word) } if bytes.HasPrefix(lword, lprefix) { ok := dups.insert_maybe(word) if !ok { return } others.insert_maybe(word) } }) }) others.walk(func(word []byte) { proposals = append(proposals, ac_proposal{ display: word, content: word, }) }) others.clear() } collect(false) if len(proposals) == 0 { collect(true) } if prefix != nil { return proposals, utf8.RuneCount(prefix) } return proposals, 0 }
func searchKey(nick, filter string) func([]byte) bool { nick += ":" return func(line []byte) bool { for i := 0; i < len(nick); i++ { if i+LogLinePrefixLength > len(line) || line[i+LogLinePrefixLength] != nick[i] { return false } } return bytes.Contains(bytes.ToLower(line[len(nick)+LogLinePrefixLength:]), bytes.ToLower([]byte(filter))) } }
func build_comptbl() { l1 := []byte("UACBDKRWSN") l2 := []byte("ATGVHMYWSN") l1_lower := bytes.ToLower(l1) l2_lower := bytes.ToLower(l2) for i, c1 := range l1 { c2 := l2[i] comptbl[c1] = c2 comptbl[c2] = c1 comptbl[l1_lower[i]] = c2 comptbl[l2_lower[i]] = c1 } }
func (v *view) collect_words(slice [][]byte, dups *llrb_tree, ignorecase bool) [][]byte { append_word_full := func(prefix, word []byte, clone bool) { lword := word lprefix := prefix if ignorecase { lword = bytes.ToLower(word) lprefix = bytes.ToLower(prefix) } if !bytes.HasPrefix(lword, lprefix) { return } ok := dups.insert_maybe(word) if ok { if clone { slice = append(slice, clone_byte_slice(word)) } else { slice = append(slice, word) } } } prefix := v.cursor.word_under_cursor() if prefix != nil { dups.insert_maybe(prefix) } append_word := func(word []byte) { append_word_full(prefix, word, false) } append_word_clone := func(word []byte) { append_word_full(prefix, word, true) } line := v.cursor.line iter_words_backward(line.data[:v.cursor.boffset], append_word_clone) line = line.prev for line != nil { iter_words_backward(line.data, append_word) line = line.prev } line = v.cursor.line iter_words(line.data[v.cursor.boffset:], append_word_clone) line = line.next for line != nil { iter_words(line.data, append_word) line = line.next } return slice }
func handleHTTPHdr(rdr *bufio.Reader, c net.Conn, header *bytes.Buffer) (addr []byte, err error) { hdrXff := "X-Forwarded-For: " + ipAddrFromRemoteAddr(c.RemoteAddr().String()) var cipherAddr []byte for { line, isPrefix, err := rdr.ReadLine() if err != nil || isPrefix { log.Println(err) writeErrCode(c, []byte("4107"), true) return nil, err } if bytes.HasPrefix(bytes.ToLower(line), _hdrCipherOrigin) { // copy instead of point cipherAddr = []byte(string(bytes.TrimSpace(line[(len(_hdrCipherOrigin) + 1):]))) continue } if bytes.HasPrefix(bytes.ToLower(line), _hdrForwardedFor) { hdrXff = hdrXff + ", " + string(bytes.TrimSpace(line[(len(_hdrForwardedFor)+1):])) continue } if len(bytes.TrimSpace(line)) == 0 { // end of HTTP header if len(cipherAddr) == 0 { writeErrCode(c, []byte("4108"), true) return nil, errors.New("empty http cipher address header") } if len(hdrXff) > 0 { header.Write([]byte(hdrXff)) header.Write([]byte("\n")) } header.Write(line) header.Write([]byte("\n")) break } header.Write(line) header.Write([]byte("\n")) if header.Len() > _maxHTTPHeaderSize { writeErrCode(c, []byte("4108"), true) return nil, errors.New("http header size overflowed") } } return cipherAddr, nil }
// NewRequestHeader returns RequestHeader from bytes func NewRequestHeader(b []byte) (*RequestHeader, error) { lines := bytes.Split(b, eol) reqline := bytes.Split(lines[0], []byte{' '}) headers := [][][]byte{} bodySize := 0 headerLines := lines[1:] for _, l := range headerLines { tokens := bytes.SplitN(l, []byte{':', ' '}, 2) if len(tokens) == 2 { headers = append(headers, tokens) } if bytes.Equal(bytes.ToLower(tokens[0]), []byte("content-length")) { size, err := strconv.Atoi(string(tokens[1])) if err != nil { return nil, err } bodySize = size } } r := &RequestHeader{ ReqLineTokens: reqline, Headers: headers, BodySize: bodySize, BodyRead: 0, } return r, nil }
// load method creates the trie for processing func (root *Node) load() (ln int) { f, err := os.Open(fname) defer f.Close() if err != nil { log.Fatal("File open error: ", err) } var w []byte var nr *Node var ltr byte var i int wk := new(wrk) // using Buffered Reader instead of Scanner to avoid the allocation issue r := bufio.NewReader(f) for w, err = r.ReadBytes('\n'); err == nil; w, err = r.ReadBytes('\n') { w, nr = bytes.ToLower(bytes.TrimSpace(w)), root for i, ltr = range w { wk.depth, nr.chld = i+1, true nr = nr.addChar(<r, wk) } nr.word = true if nr.depth > ln { ln = nr.depth } } return }
func netshInterfaceIPv6ShowAddress(name string) ([]string, error) { // TODO: need to test ipv6 netmask too, but netsh does not outputs it out, err := runCmd("netsh", "interface", "ipv6", "show", "address", "interface=\""+name+"\"") if err != nil { return nil, err } addrs := make([]string, 0) lines := bytes.Split(out, []byte{'\r', '\n'}) for _, line := range lines { if !bytes.HasPrefix(line, []byte("Address")) { continue } if !bytes.HasSuffix(line, []byte("Parameters")) { continue } f := bytes.Split(line, []byte{' '}) if len(f) != 3 { continue } // remove scope ID if present f = bytes.Split(f[1], []byte{'%'}) addrs = append(addrs, string(bytes.ToLower(bytes.TrimSpace(f[0])))) } return addrs, nil }
// ParseBytes is like Parse, except it parses a byte slice instead of a string. func ParseBytes(b []byte) (UUID, error) { var uuid UUID if len(b) != 36 { if len(b) != 36+9 { return uuid, fmt.Errorf("invalid UUID length: %d", len(b)) } if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) { return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) } b = b[9:] } if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { return uuid, errors.New("invalid UUID format") } for i, x := range [16]int{ 0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} { if v, ok := xtob(b[x], b[x+1]); !ok { return uuid, errors.New("invalid UUID format") } else { uuid[i] = v } } return uuid, nil }
// fetchTitle attempts to retrieve the title element for a given url. func fetchTitle(c *proto.Client, m *proto.Message, url string) { resp, err := http.Get(url) if err != nil { return } body, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { return } body = bytes.ToLower(body) s := bytes.Index(body, []byte("<title>")) if s == -1 { return } body = body[s+7:] e := bytes.Index(body, []byte("</title>")) if e == -1 { e = len(body) - 1 } body = bytes.TrimSpace(body[:e]) c.PrivMsg(m.Receiver, "%s's link shows: %s", m.SenderName, html.UnescapeString(string(body))) }
func (options *html) Citation(out *bytes.Buffer, link, title []byte) { out.WriteString("<a class=\"cite\" href=\"#") out.Write(bytes.ToLower(link)) out.WriteString("\">") out.Write(title) out.WriteString("</a>") }
func findNews(text [][]byte, address, sender string) []byte { // prep the address for searching against text addr := []byte(address) addrStart := bytes.SplitN(addr, []byte("@"), 2)[0] // so we can reuse similar addresses? if len(addrStart) > 15 { addrStart = addrStart[:15] } var news [][]byte badLines := 0 senderBytes := bytes.ToLower([]byte(sender)) for _, line := range text { line := bytes.Trim(line, "-| ?") if isNews(line, addr, addrStart, senderBytes) { badLines = 0 news = append(news, line) } else if (len(news) > 0) && (len(line) > 0) { badLines++ } // get at most 3 or quit if we have bad rows and at least 2 or over 2 bads and 1 good if (len(news) >= 3) || ((badLines > 0) && (len(news) >= 2)) || ((badLines >= 2) && (len(news) >= 1)) { break } } return bytes.Join(news, []byte(" ")) }
// IdentifyRedHatRelease tires to identify the derivretives of Red Hat Linux. // It supports following distributions: // // - CentOS // - Red Hat Enterprise Linux // // If failed to identify the platform or the platform is the derivatives of // Red Hat Linux, IdentifyRedHatRelease returns an ErrNotIdentifier. func IdentifyRedHatRelease() (*Info, error) { file, err := os.Open("/etc/redhat-release") if err != nil { if os.IsNotExist(err) { return nil, ErrNotIdentified } return nil, err } b, err := ioutil.ReadAll(file) if err != nil { return nil, err } var platform Name lb := bytes.ToLower(b) switch { case bytes.HasPrefix(lb, []byte("centos")): platform = PlatformCentOS case bytes.HasPrefix(lb, []byte("red hat enterprise")): platform = PlatformRHEL } version := "" if matches := regexp.MustCompile(`release (\d[\d.]*)`).FindSubmatch(b); len(matches) > 1 { version = string(matches[1]) } return &Info{ Platform: platform, Family: FamilyRHEL, Version: version, }, nil }
func TestAgent_Self(t *testing.T) { meta := map[string]string{ "somekey": "somevalue", } dir, srv := makeHTTPServerWithConfig(t, func(conf *Config) { conf.Meta = meta }) defer os.RemoveAll(dir) defer srv.Shutdown() defer srv.agent.Shutdown() req, err := http.NewRequest("GET", "/v1/agent/self", nil) if err != nil { t.Fatalf("err: %v", err) } obj, err := srv.AgentSelf(nil, req) if err != nil { t.Fatalf("err: %v", err) } val := obj.(AgentSelf) if int(val.Member.Port) != srv.agent.config.Ports.SerfLan { t.Fatalf("incorrect port: %v", obj) } if int(val.Config.Ports.SerfLan) != srv.agent.config.Ports.SerfLan { t.Fatalf("incorrect port: %v", obj) } c, err := srv.agent.server.GetLANCoordinate() if err != nil { t.Fatalf("err: %v", err) } if !reflect.DeepEqual(c, val.Coord) { t.Fatalf("coordinates are not equal: %v != %v", c, val.Coord) } if !reflect.DeepEqual(meta, val.Meta) { t.Fatalf("meta fields are not equal: %v != %v", meta, val.Meta) } srv.agent.config.DisableCoordinates = true obj, err = srv.AgentSelf(nil, req) if err != nil { t.Fatalf("err: %v", err) } val = obj.(AgentSelf) if val.Coord != nil { t.Fatalf("should have been nil: %v", val.Coord) } // Make sure there's nothing called "token" that's leaked. raw, err := srv.marshalJSON(req, obj) if err != nil { t.Fatalf("err: %v", err) } if bytes.Contains(bytes.ToLower(raw), []byte("token")) { t.Fatalf("bad: %s", raw) } }
func (rr *Reader) readSingleCmd() (cmd *Command, err error) { if vals, err := rr.readSingleLineVals(); err != nil { return nil, newError(err, "error reading single command") } else { cmd = new(Command) cmd.Name = bytes.ToLower(vals[0]) cmd.Args = vals[1:] } fmt.Printf("got cmd '%s\n'", cmd.Name) isBulk := RedisCmds[string(cmd.Name)]&REDIS_CMD_BULK == REDIS_CMD_BULK // if its a bulk cmd, the last arg is the number of bytes of the real last arg // So lets swap it out if isBulk { if nbytes, err := strconv.Atoi(string(cmd.Args[len(cmd.Args)])); err != nil { return nil, newError(err, "parsing bulk argument length failed") } else { bulkbuf := make([]byte, nbytes) rr.rd.Read(bulkbuf) cmd.Args[len(cmd.Args)] = bulkbuf } } // The line should end with crlf so check the last char is \r return cmd, nil }
func IsValidCharsets(cs []byte) bool { if _, ok := ValidCharsets[string(bytes.ToLower(cs))]; ok { return true } return false }
func argsCheck() *tunnel.Options { var options tunnel.Options var tgw string var rc4Key string flag.BoolVar(&options.TunnelServer, "tunnel_server", false, "work as tunnel server or client") flag.BoolVar(&options.Front, "front", false, "work as front door or back door") flag.StringVar(&tgw, "tgw", "", "tgw header") flag.StringVar(&rc4Key, "rc4", "the answer to life, the universe and everything", "rc4 key, disable if no key") flag.StringVar(&options.FrontAddr, "front_addr", "0.0.0.0:8001", "front door address(0.0.0.0:8001)") flag.StringVar(&options.TunnelAddr, "tunnel_addr", "0.0.0.0:8002", "tunnel door address(0.0.0.0:8002)") flag.IntVar(&options.LogLevel, "log", 1, "larger value for detail log") flag.Usage = usage flag.Parse() options.Capacity = 65535 options.Tgw = bytes.ToLower([]byte(tgw)) options.Rc4Key = []byte(rc4Key) if len(options.Rc4Key) > 256 { fmt.Println("rc4 key at most 256 bytes") os.Exit(1) } if !options.Front { args := flag.Args() if len(args) < 1 { usage() } else { options.ConfigFile = args[0] } } return &options }
func netshInterfaceIPv6ShowAddress(name string) ([]string, error) { // TODO: need to test ipv6 netmask too, but netsh does not outputs it out, err := runCmd("netsh", "interface", "ipv6", "show", "address", "interface=\""+name+"\"") if err != nil { return nil, err } addrs := make([]string, 0) lines := bytes.Split(out, []byte{'\r', '\n'}) for _, line := range lines { if !bytes.HasPrefix(line, []byte("Address")) { continue } if !bytes.HasSuffix(line, []byte("Parameters")) { continue } f := bytes.Split(line, []byte{' '}) if len(f) != 3 { continue } // remove scope ID if present f = bytes.Split(f[1], []byte{'%'}) // netsh can create IPv4-embedded IPv6 addresses, like fe80::5efe:192.168.140.1. // Convert these to all hexadecimal fe80::5efe:c0a8:8c01 for later string comparisons. ipv4Tail := regexp.MustCompile(`:\d+\.\d+\.\d+\.\d+$`) if ipv4Tail.Match(f[0]) { f[0] = []byte(ParseIP(string(f[0])).String()) } addrs = append(addrs, string(bytes.ToLower(bytes.TrimSpace(f[0])))) } return addrs, nil }
func Stem(body []byte) []byte { word := bytes.TrimSpace(bytes.ToLower(body)) if len(word) > 2 { return five_b(five_a(four(three(two(one_c(one_b(one_a(word)))))))) } return word }
// toLowerDeferredCopy will function exactly like // bytes.ToLower() only it will reuse (overwrite) // the original byte array when possible // NOTE: because its possible that the lower-case // form of a rune has a different utf-8 encoded // length, in these cases a new byte array is allocated func toLowerDeferredCopy(s []byte) []byte { j := 0 for i := 0; i < len(s); { wid := 1 r := rune(s[i]) if r >= utf8.RuneSelf { r, wid = utf8.DecodeRune(s[i:]) } l := unicode.ToLower(r) lwid := utf8.RuneLen(l) if lwid > wid { // utf-8 encoded replacement is wider // for now, punt and defer // to bytes.ToLower() for the remainder // only known to happen with chars // Rune Ⱥ(570) width 2 - Lower ⱥ(11365) width 3 // Rune Ⱦ(574) width 2 - Lower ⱦ(11366) width 3 rest := bytes.ToLower(s[i:]) rv := make([]byte, j+len(rest)) copy(rv[:j], s[:j]) copy(rv[j:], rest) return rv } else { utf8.EncodeRune(s[j:], l) } i += wid j += lwid } return s[:j] }
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 }
func TestAssertNotEqual(t *testing.T) { AssertNotEqual(t, 2, 1) AssertNotEqual(t, "ABC", strings.ToLower("ABC")) AssertNotEqual(t, []byte("ABC"), bytes.ToLower([]byte("ABC"))) AssertNotEqual(t, image.Pt(1, 2), image.Pt(2, 2)) AssertNotEqual(t, image.Pt(1, 2), image.Rect(1, 2, 3, 4)) }
func main() { quickBrownFox := []byte("The quick brown fox jumped over the lazy dog") title := bytes.Title(quickBrownFox) log.Printf("Title turned %q into %q", quickBrownFox, title) allTitle := bytes.ToTitle(quickBrownFox) log.Printf("ToTitle turned %q to %q", quickBrownFox, allTitle) allTitleTurkish := bytes.ToTitleSpecial(unicode.TurkishCase, quickBrownFox) log.Printf("ToTitleSpecial turned %q into %q using the Turkish case rules", quickBrownFox, allTitleTurkish) lower := bytes.ToLower(title) log.Printf("ToLower turned %q into %q", title, lower) turkishCapitalI := []byte("İ") turkishLowerI := bytes.ToLowerSpecial(unicode.TurkishCase, turkishCapitalI) log.Printf("ToLowerSpecial turned %q into %q using the Turkish case rules", turkishCapitalI, turkishLowerI) upper := bytes.ToUpper(quickBrownFox) log.Printf("ToUpper turned %q to %q", quickBrownFox, upper) upperSpecial := bytes.ToUpperSpecial(unicode.TurkishCase, quickBrownFox) log.Printf("ToUpperSpecial turned %q into %q using the Turkish case rules", quickBrownFox, upperSpecial) }
//Main parse loop func (blp *Bls) parseBinlogEvents(sendReply proto.SendBinlogResponse, binlogReader io.Reader) { // read over the stream and buffer up the transactions var err error var line []byte bigLine := make([]byte, 0, BINLOG_BLOCK_SIZE) lineReader := bufio.NewReaderSize(binlogReader, BINLOG_BLOCK_SIZE) readAhead := false var event *blsEventBuffer var delimIndex int for { line = line[:0] bigLine = bigLine[:0] line, err = blp.readBlsLine(lineReader, bigLine) if err != nil { if err == io.EOF { //end of stream blp.globalState.blsStats.parseStats.Add("EOFErrors."+blp.keyrangeTag, 1) panic(newBinlogServerError(fmt.Sprintf("EOF"))) } panic(newBinlogServerError(fmt.Sprintf("ReadLine err: , %v", err))) } if len(line) == 0 { continue } if line[0] == '#' { //parse positional data line = bytes.TrimSpace(line) blp.currentLine = string(line) blp.parsePositionData(line) } else { //parse event data if readAhead { event.LogLine = append(event.LogLine, line...) } else { event = newBlsEventBuffer(blp.currentPosition, line) } delimIndex = bytes.LastIndex(event.LogLine, BINLOG_DELIMITER) if delimIndex != -1 { event.LogLine = event.LogLine[:delimIndex] readAhead = false } else { readAhead = true continue } event.LogLine = bytes.TrimSpace(event.LogLine) event.firstKw = string(bytes.ToLower(bytes.SplitN(event.LogLine, SPACE, 2)[0])) blp.currentLine = string(event.LogLine) //processes statements only for the dbname that it is subscribed to. blp.parseDbChange(event) blp.parseEventData(sendReply, event) } } }
func controlDbStatement(sql []byte, dmlType string) bool { sql = bytes.ToLower(sql) if bytes.Contains(sql, _VT) || (bytes.Contains(sql, ADMIN) && bytes.Contains(sql, HEARTBEAT)) { return true } return false }
// parseEvents parses events and transmits them as transactions for the current mysqlbinlog stream. func (bls *BinlogStreamer) parseEvents(sendTransaction sendTransactionFunc, reader io.Reader) (err error) { bls.delim = DEFAULT_DELIM bufReader := bufio.NewReader(reader) var statements []proto.Statement for { sql, err := bls.nextStatement(bufReader) if sql == nil { return err } prefix := string(bytes.ToLower(bytes.SplitN(sql, SPACE, 2)[0])) switch category := statementPrefixes[prefix]; category { // We trust that mysqlbinlog doesn't send proto.BL_DMLs withot a proto.BL_BEGIN case proto.BL_BEGIN, proto.BL_ROLLBACK: statements = nil case proto.BL_DDL: statements = append(statements, proto.Statement{Category: category, Sql: sql}) fallthrough case proto.BL_COMMIT: trans := &proto.BinlogTransaction{ Statements: statements, GroupId: bls.blPos.GroupId, } if err = sendTransaction(trans); err != nil { if err == io.EOF { return err } return fmt.Errorf("send reply error: %v", err) } statements = nil // proto.BL_DML, proto.BL_SET or proto.BL_UNRECOGNIZED default: statements = append(statements, proto.Statement{Category: category, Sql: sql}) } } }