func ExampleIndexFunc() { f := func(c rune) bool { return unicode.Is(unicode.Han, c) } fmt.Println(bytes.IndexFunc([]byte("Hello, 世界"), f)) fmt.Println(bytes.IndexFunc([]byte("Hello, world"), f)) // Output: // 7 // -1 }
// TODO: func (f *File) OffsetLine(ln, start int) (offset int, e error) { if start < 0 || start > len(f.b) { return 0, memfile.OutOfBounds } if ln == 0 { i := bytes.LastIndex(f.b[:start], []byte("\n")) return i + 1, nil } if ln < 0 { i := 0 return bytes.LastIndexFunc(f.b[:start], func(r rune) bool { if r == '\n' { if i == ln { return true } i-- } return false }) + 1, nil } i := 0 va := bytes.IndexFunc(f.b[start:], func(r rune) bool { if r == '\n' { i++ if i == ln { return true } } return false }) if va != -1 { return va + start + 1, nil } return len(f.b), nil }
// Trim space from the left. func (buf *parserBuf) trimSpaceLeft() { n := bytes.IndexFunc(buf.bytes, func(r rune) bool { return !unicode.IsSpace(r) }) if n == -1 { n = len(buf.bytes) } buf.trimBytesLeft(n) }
func (l *LogFile) Add(b []byte) error { // Extract the first word --- which will be the command; the rest will be args if (l.linenum % l.Size) == l.Rank { ndx := bytes.IndexFunc(b, unicode.IsSpace) var comm, args string if ndx == -1 { comm = string(b) args = "" } else { comm = string(b[0:ndx]) args = string(b[ndx:]) } fmt.Fprintln(l.F, "-->", string(b)) out, err := exec.Command(comm, args).CombinedOutput() if err != nil { fmt.Fprintln(l.F, "-->ERROR : ", err) fmt.Fprintln(l.F, "-->Output follows :") } fmt.Fprintln(l.F, string(out)) fmt.Fprintln(l.F, "-->") } l.linenum += 1 return nil }
func writeBytesKey(w io.Writer, key []byte) error { if len(key) == 0 || bytes.IndexFunc(key, invalidKeyRune) != -1 { return ErrInvalidKey } _, err := w.Write(key) return err }
func indexFunc(s []byte, f func(rune) bool) { if i := bytes.IndexFunc(s, f); i == -1 { log.Printf("Something controlled by %#v does NOT appear in %s", f, s) } else { log.Printf("Something controlled by %#v appears at index %d in %s", f, i, s) } }
func IterWords(data []byte, cb func(word []byte)) { for { i := bytes.IndexFunc(data, IsWord) if i == -1 { return } data = data[i:] i = bytes.IndexFunc(data, func(r rune) bool { return !IsWord(r) }) if i == -1 { return } cb(data[:i]) data = data[i:] } }
func lastContiguousIndexFunc(s []byte, f func(r rune) bool) int { i := bytes.IndexFunc(s, func(r rune) bool { return !f(r) }) if i == -1 { i = len(s) } return i - 1 }
func writeBytesValue(w io.Writer, value []byte) error { var err error if bytes.IndexFunc(value, needsQuotedValueRune) >= 0 { _, err = writeQuotedBytes(w, value) } else { _, err = w.Write(value) } return err }
func consumeToken(v []byte) (token, rest []byte) { notPos := bytes.IndexFunc(v, isNotTokenChar) if notPos == -1 { return v, nil } if notPos == 0 { return nil, v } return v[0:notPos], v[notPos:] }
/*IndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points. It returns the byte index in s of the first Unicode code point satisfying f(c), or -1 if none do.*/ func main() { s := []byte("123456677") f := func(a rune) bool { if a > '6' { return true } return false } fmt.Println(bytes.IndexFunc(s, f)) }
func formatVal(val driver.Value, showPrintableUnicode bool, showNewLinesAndTabs bool) string { switch t := val.(type) { case nil: return "NULL" case string: if showPrintableUnicode { pred := isNotGraphicUnicode if showNewLinesAndTabs { pred = isNotGraphicUnicodeOrTabOrNewline } if utf8.ValidString(t) && strings.IndexFunc(t, pred) == -1 { return t } } else { if strings.IndexFunc(t, isNotPrintableASCII) == -1 { return t } } return fmt.Sprintf("%+q", t) case []byte: if showPrintableUnicode { pred := isNotGraphicUnicode if showNewLinesAndTabs { pred = isNotGraphicUnicodeOrTabOrNewline } if utf8.Valid(t) && bytes.IndexFunc(t, pred) == -1 { return string(t) } } else { if bytes.IndexFunc(t, isNotPrintableASCII) == -1 { return string(t) } } return fmt.Sprintf("%+q", t) case time.Time: return t.Format(parser.TimestampNodeFormat) } return fmt.Sprint(val) }
// glogBody logs a body output that could be either JSON or protobuf. It explicitly guards against // allocating a new string for the body output unless necessary. Uses a simple heuristic to determine // whether the body is printable. func glogBody(prefix string, body []byte) { if glog.V(8) { if bytes.IndexFunc(body, func(r rune) bool { return r < 0x0a }) != -1 { glog.Infof("%s:\n%s", prefix, hex.Dump(body)) } else { glog.Infof("%s: %s", prefix, string(body)) } } }
func parseRule(sel []byte, in *bufio.Reader) Item { // Clean up the selector. sel = bytes.TrimSpace(sel) sel = bytes.Replace(sel, []byte{'\t'}, []byte{' '}, -1) sel = bytes.Replace(sel, []byte{'\n'}, []byte{' '}, -1) for si := bytes.IndexByte(sel, ' '); si != -1; si = bytes.IndexByte(sel[si+2:], ' ') + si + 2 { lsi := bytes.IndexFunc(sel[si+1:], func(c rune) bool { return c != ' ' }) if lsi == -1 { // No non-space was found. break } else if lsi == 0 { // The very next character was a non-space. continue } copy(sel[si+1:], sel[si+lsi+1:]) sel = sel[:len(sel)-lsi] } sel = bytes.Replace(sel, []byte{',', ' '}, []byte{','}, -1) sel = bytes.Replace(sel, []byte{' ', ','}, []byte{','}, -1) sel = bytes.Replace(sel, []byte{'>', ' '}, []byte{'>'}, -1) sel = bytes.Replace(sel, []byte{' ', '>'}, []byte{'>'}, -1) // Read the body portion. body, _ := in.ReadBytes('}') // Clean up the body. body = bytes.TrimSpace(body[:len(body)-1]) if len(body) == 0 { // This rule doesn't do anything. It's useless. No need to // include it in the output. return nil } // Create the slice of pairs to store in the rule. (This slice will be // extended as necessary.) pairs := make([]pair, 0) // Iterate over the directives in the body. for _, p := range bytes.Split(body, []byte{';'}) { // Clean up the pair. p = bytes.TrimSpace(p) i := bytes.Index(p, []byte{':'}) if i == -1 { // Hmm. There's no colon in this pair. Something's wrong. // We'll just silently omit it. continue } // Extend our slice of pairs with the new directive. pairs = append(pairs, pair{bytes.TrimSpace(p[:i]), bytes.TrimSpace(p[i+1:])}) } return &rule{sel, pairs} }
// Charactor code 0x00 - 0x08 is control code (ASCII) func verifyBinary(buf []byte) bool { var b []byte if len(buf) > 256 { b = buf[:256] } else { b = buf } if bytes.IndexFunc(b, func(r rune) bool { return r < 0x09 }) != -1 { return true } return false }
func StringCutRune(str string, n int) string { b := []byte(str) i := 0 index := bytes.IndexFunc(b, func(r rune) bool { i++ if i > n { return true } return false }) if index < 0 { return str } return string(b[:index]) }
func tokenizeXML(data []byte, atEOF bool) (advance int, token []byte, err error) { var tcomment = []byte{'<', '!', '-', '-'} if bytes.HasPrefix(data, tcomment) { return len(tcomment), tcomment, nil } r, size := utf8.DecodeRune(data) if unicode.IsSpace(r) { return size, data[:size], nil } if data[0] == '<' || data[0] == '>' { return 1, data[:1], nil } if data[0] == '/' && data[1] == '>' { return 2, data[:2], nil } num := bytes.IndexFunc(data, nameboundary) if num > 0 { return num, data[:num], nil } return 1, data[:1], nil }
// Import parses the contents of a libotr private key file. func (priv *PrivateKey) Import(in []byte) bool { mpiStart := []byte(" #") mpis := make([]*big.Int, 5) for i := 0; i < len(mpis); i++ { start := bytes.Index(in, mpiStart) if start == -1 { return false } in = in[start+len(mpiStart):] end := bytes.IndexFunc(in, notHex) if end == -1 { return false } hexBytes := in[:end] in = in[end:] if len(hexBytes)&1 != 0 { return false } mpiBytes := make([]byte, len(hexBytes)/2) if _, err := hex.Decode(mpiBytes, hexBytes); err != nil { return false } mpis[i] = new(big.Int).SetBytes(mpiBytes) } priv.PrivateKey.P = mpis[0] priv.PrivateKey.Q = mpis[1] priv.PrivateKey.G = mpis[2] priv.PrivateKey.Y = mpis[3] priv.PrivateKey.X = mpis[4] priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey a := new(big.Int).Exp(priv.PrivateKey.G, priv.PrivateKey.X, priv.PrivateKey.P) return a.Cmp(priv.PrivateKey.Y) == 0 }
func getWord(b []byte, pos *filePos) (string, []byte) { // Skip over leading whitespace i := 0 for i < len(b) { r, size := utf8.DecodeRune(b[i:]) if r == '\n' { pos.line++ } if !unicode.IsSpace(r) { break } i += size } b = b[i:] // Find end of word i = bytes.IndexFunc(b, unicode.IsSpace) if i < 0 { i = len(b) } return string(b[0:i]), b[i:] }
func (p *PackageInfo) comment_format(comment, indent, preIndent string) string { containsOnlySpace := func(buf []byte) bool { isNotSpace := func(r rune) bool { return !unicode.IsSpace(r) } return bytes.IndexFunc(buf, isNotSpace) == -1 } var buf bytes.Buffer const punchCardWidth = 80 ToText(&buf, comment, indent, preIndent, punchCardWidth-2*len(indent)) if containsOnlySpace(buf.Bytes()) { return "" } lines := strings.Split(buf.String(), "\n") if len(lines) > 0 && lines[len(lines)-1] == "" { lines = lines[:len(lines)-1] } for i := 0; i < len(lines); i++ { if lines[i] == "" || lines[i][0] != '\t' { lines[i] = "// " + lines[i] } else { lines[i] = "//" + lines[i] } } return strings.Join(lines, "\n") }
func whitespace(src []byte) []byte { // remove needless comments for { pos := bytes.IndexFunc(src, func(r rune) bool { return r != ' ' && r != '\t' && r != '\n' }) if pos < 0 { break } if pos == 0 { src = src[1:] } else { src = append(src[:pos], src[pos+1:]...) } } // parse whitespace into tokens tokens := opcodes{} for len(src) > 0 { op := "" code := Nop for k, v := range optable { if bytes.HasPrefix(src, []byte(k)) { op = k code = v break } } if op == "" { src = src[1:] continue } src = src[len(op):] var arg int switch code { case Push: // handle argument handle_signed_arg: for i := 1; i < len(src); i++ { switch src[i] { case ' ': arg = (arg << 1) | 0 case '\t': arg = (arg << 1) | 1 case '\n': // Push take singed argument if src[0] == '\t' { arg = -arg } src = src[i+1:] break handle_signed_arg } } case Mark, Call, Jump, Jz, Jn: // handle argument handle_unsigned_arg: for i := 0; i < len(src); i++ { switch src[i] { case ' ': arg = (arg << 1) | 0 case '\t': arg = (arg << 1) | 1 case '\n': src = src[i+1:] break handle_unsigned_arg } } } tokens = append(tokens, opcode{code, arg}) } pc := 0 ps := stack{} cs := stack{} heap := map[int]int{} for { token := tokens[pc] code, arg := token.code, token.arg //fmt.Println(pc, code, arg) pc++ switch code { case Push: ps.push(arg) case Mark: case Dup: ps.dup() case OutN: fmt.Print(ps.pop()) case OutC: fmt.Print(string(rune(ps.pop()))) case Add: rhs := ps.pop() lhs := ps.pop() ps.push(lhs + rhs) case Sub: rhs := ps.pop() lhs := ps.pop() ps.push(lhs - rhs) case Mul: rhs := ps.pop() lhs := ps.pop() ps.push(lhs * rhs) case Div: rhs := ps.pop() lhs := ps.pop() ps.push(lhs / rhs) case Mod: rhs := ps.pop() lhs := ps.pop() ps.push(lhs % rhs) case Jz: if ps.pop() == 0 { tokens.jmp(arg, &pc) } case Jn: if ps.pop() < 0 { tokens.jmp(arg, &pc) } case Jump: tokens.jmp(arg, &pc) case Discard: ps.pop() case Exit: os.Exit(0) case Store: v := ps.pop() address := ps.pop() heap[address] = v case Call: cs.push(pc) tokens.jmp(arg, &pc) case Retrieve: ps.push(heap[ps.pop()]) case Ret: pc = cs.pop() case InC: var b [1]byte os.Stdin.Read(b[:]) heap[ps.pop()] = int(b[0]) case InN: scanner := bufio.NewScanner(os.Stdin) if scanner.Scan() { i, _ := strconv.Atoi(scanner.Text()) heap[ps.pop()] = i } case Swap: ps[len(ps)-1], ps[len(ps)-2] = ps[len(ps)-2], ps[len(ps)-1] default: panic(fmt.Sprintf("Unknown opcode: %v", code)) } } }
func (s *Server) receiver(c *net.UDPConn) { //q := (chan<- Message)(s.q) buf := make([]byte, 1024) for { n, addr, err := c.ReadFrom(buf) if err != nil { if !s.shutdown { s.l.Fatalln("Read error:", err) } return } pkt := buf[:n] m := new(Message) m.Source = addr m.Time = time.Now() // Parse priority (if exists) prio := 13 // default priority hasPrio := false if pkt[0] == '<' { n = 1 + bytes.IndexByte(pkt[1:], '>') if n > 1 && n < 5 { p, err := strconv.Atoi(string(pkt[1:n])) if err == nil && p >= 0 { hasPrio = true prio = p pkt = pkt[n+1:] } } } m.Severity = Severity(prio & 0x07) m.Facility = Facility(prio >> 3) // Parse header (if exists) if hasPrio && len(pkt) >= 16 && pkt[15] == ' ' { // Get timestamp layout := "Jan _2 15:04:05" ts, err := time.Parse(layout, string(pkt[:15])) if err == nil && !ts.IsZero() { // Get hostname n = 16 + bytes.IndexByte(pkt[16:], ' ') if n != 15 { m.Timestamp = ts m.Hostname = string(pkt[16:n]) pkt = pkt[n+1:] } } // TODO: check for version an new format of header as // described in RFC 5424. } // Parse msg part pkt = bytes.TrimRightFunc(pkt, isNulCrLf) n = bytes.IndexFunc(pkt, isNotAlnum) if n != -1 { m.Tag = string(pkt[:n]) pkt = pkt[n:] } m.Content = string(pkt) s.passToHandlers(m) } }
func Grep(arg *GrepArg) { var f []byte var path = "" var ok bool var stdin *os.File var err error var ic *iconv.Iconv if path, ok = arg.input.(string); ok { f, err = ioutil.ReadFile(path) if err != nil { errorline(err.Error()) return } } else if stdin, ok = arg.input.(*os.File); ok { f, err = ioutil.ReadAll(stdin) if err != nil { errorline(err.Error()) return } path = "stdin" } fencs := encodings if bytes.IndexFunc( f, func(r rune) bool { return r > 0 && r < 0x9 }) != -1 { fencs = []string{""} } for _, enc := range fencs { if verbose { println("trying("+enc+"):", path) } did := false var t []byte var n, l, size, next, prev int if enc != "" { ic, err = iconv.Open("utf-8", enc) if err != nil { continue } if enc == "utf-16" && len(f) > 2 { if f[0] == 0xfe && f[1] == 0xff { for nn := 0; nn < len(f); nn += 2 { nt := f[nn] f[nn] = f[nn+1] f[nn+1] = nt } } } ff, err := ic.ConvBytes(f) if err != nil { next = -1 continue } f = ff } size = len(f) if size == 0 { continue } for next != -1 { for { if next >= size { next = -1 break } if f[next] == '\n' { break } next++ } n++ if next == -1 { t = f[prev:] } else { t = f[prev:next] prev = next + 1 next++ } l = len(t) if l > 0 && t[l-1] == '\r' { t = t[:l-1] l-- } if l == 0 { continue } var match bool if only { var matches []string ts := string(t) if re, ok := arg.pattern.(*regexp.Regexp); ok { matches = re.FindAllString(ts, -1) } else if s, ok := arg.pattern.(string); ok { if ignorecase { ts = strings.ToLower(ts) } ti := 0 tl := len(ts) for ti != -1 && ti < tl-1 { ti = strings.Index(ts[ti:], s) if ti != -1 { matches = append(matches, s) ti++ } } } match = len(matches) > 0 if (!invert && !match) || (invert && match) { continue } if verbose { println("found("+enc+"):", path) } if list { printline(arg.oc, path) did = true break } for _, m := range matches { if strings.IndexFunc( m, func(r rune) bool { return r < 0x9 }) != -1 { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } else { if number { if !printline(arg.oc, fmt.Sprintf("%s:%d:%s", path, n, string(m))) { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } } else { if !printline(arg.oc, string(m)) { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } } } } } else { if re, ok := arg.pattern.(*regexp.Regexp); ok { if len(re.FindAllIndex(t, 1)) > 0 { match = true } } else if s, ok := arg.pattern.(string); ok { if ignorecase { if strings.Index(strings.ToLower(string(t)), strings.ToLower(s)) > -1 { match = true } } else { if strings.Index(string(t), s) > -1 { match = true } } } if (!invert && !match) || (invert && match) { continue } if verbose { println("found("+enc+"):", path) } if list { printline(arg.oc, path) did = true break } if arg.single && !number { if !printline(arg.oc, string(t)) { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } } else { if bytes.IndexFunc( t, func(r rune) bool { return r < 0x9 }) != -1 { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } else if !printline(arg.oc, fmt.Sprintf("%s:%d:%s", path, n, string(t))) { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } } } did = true } if ic != nil { ic.Close() ic = nil } runtime.GC() if did || next == -1 { break } } }
func containsOnlySpace(buf []byte) bool { isNotSpace := func(r rune) bool { return !unicode.IsSpace(r) } return bytes.IndexFunc(buf, isNotSpace) == -1 }
// transformResponse converts an API response into a structured API object func (r *Request) transformResponse(resp *http.Response, req *http.Request) Result { var body []byte if resp.Body != nil { if data, err := ioutil.ReadAll(resp.Body); err == nil { body = data } } if glog.V(8) { if bytes.IndexFunc(body, func(r rune) bool { return r < 0x0a }) != -1 { glog.Infof("Response Body:\n%s", hex.Dump(body)) } else { glog.Infof("Response Body: %s", string(body)) } } // verify the content type is accurate contentType := resp.Header.Get("Content-Type") decoder := r.serializers.Decoder if len(contentType) > 0 && (decoder == nil || (len(r.content.ContentType) > 0 && contentType != r.content.ContentType)) { mediaType, params, err := mime.ParseMediaType(contentType) if err != nil { return Result{err: errors.NewInternalError(err)} } decoder, err = r.serializers.RenegotiatedDecoder(mediaType, params) if err != nil { // if we fail to negotiate a decoder, treat this as an unstructured error switch { case resp.StatusCode == http.StatusSwitchingProtocols: // no-op, we've been upgraded case resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent: return Result{err: r.transformUnstructuredResponseError(resp, req, body)} } return Result{ body: body, contentType: contentType, statusCode: resp.StatusCode, } } } switch { case resp.StatusCode == http.StatusSwitchingProtocols: // no-op, we've been upgraded case resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent: // calculate an unstructured error from the response which the Result object may use if the caller // did not return a structured error. retryAfter, _ := retryAfterSeconds(resp) err := r.newUnstructuredResponseError(body, isTextResponse(resp), resp.StatusCode, req.Method, retryAfter) return Result{ body: body, contentType: contentType, statusCode: resp.StatusCode, decoder: decoder, err: err, } } return Result{ body: body, contentType: contentType, statusCode: resp.StatusCode, decoder: decoder, } }
// transformResponse converts an API response into a structured API object func (r *Request) transformResponse(resp *http.Response, req *http.Request) Result { var body []byte if resp.Body != nil { if data, err := ioutil.ReadAll(resp.Body); err == nil { body = data } } if glog.V(8) { if bytes.IndexFunc(body, func(r rune) bool { return r < 0x0a }) != -1 { glog.Infof("Response Body:\n%s", hex.Dump(body)) } else { glog.Infof("Response Body: %s", string(body)) } } // verify the content type is accurate contentType := resp.Header.Get("Content-Type") decoder := r.serializers.Decoder if len(contentType) > 0 && (decoder == nil || (len(r.content.ContentType) > 0 && contentType != r.content.ContentType)) { mediaType, params, err := mime.ParseMediaType(contentType) if err != nil { return Result{err: errors.NewInternalError(err)} } decoder, err = r.serializers.RenegotiatedDecoder(mediaType, params) if err != nil { // if we fail to negotiate a decoder, treat this as an unstructured error switch { case resp.StatusCode == http.StatusSwitchingProtocols: // no-op, we've been upgraded case resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent: return Result{err: r.transformUnstructuredResponseError(resp, req, body)} } return Result{ body: body, contentType: contentType, statusCode: resp.StatusCode, } } } // Did the server give us a status response? isStatusResponse := false status := &unversioned.Status{} // Because release-1.1 server returns Status with empty APIVersion at paths // to the Extensions resources, we need to use DecodeInto here to provide // default groupVersion, otherwise a status response won't be correctly // decoded. err := runtime.DecodeInto(decoder, body, status) if err == nil && len(status.Status) > 0 { isStatusResponse = true } switch { case resp.StatusCode == http.StatusSwitchingProtocols: // no-op, we've been upgraded case resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent: if !isStatusResponse { return Result{err: r.transformUnstructuredResponseError(resp, req, body)} } return Result{err: errors.FromObject(status)} } // If the server gave us a status back, look at what it was. success := resp.StatusCode >= http.StatusOK && resp.StatusCode <= http.StatusPartialContent if isStatusResponse && (status.Status != unversioned.StatusSuccess && !success) { // "Failed" requests are clearly just an error and it makes sense to return them as such. return Result{err: errors.FromObject(status)} } return Result{ body: body, contentType: contentType, statusCode: resp.StatusCode, decoder: decoder, } }
func doGrep(path string, f []byte, arg *GrepArg) { encs := encodings if ignorebinary { if bytes.IndexFunc(f, func(r rune) bool { return 0 < r && r < 0x9 }) != -1 { return } } if len(f) > 2 { if f[0] == 0xfe && f[1] == 0xff { arg.bom = f[0:2] f = f[2:] } else if f[0] == 0xff && f[1] == 0xfe { arg.bom = f[0:2] f = f[2:] } } if len(arg.bom) > 0 { if arg.bom[0] == 0xfe && arg.bom[1] == 0xff { encs = []string{"utf-16be"} } else if arg.bom[0] == 0xff && arg.bom[1] == 0xfe { encs = []string{"utf-16le"} } } for _, enc := range encs { if verbose { println("trying("+enc+"):", path) } if len(arg.bom) > 0 && enc != "utf-16be" && enc != "utf-16le" { continue } did := false var t []byte var n, l, size, next, prev int if enc != "" { if len(arg.bom) > 0 || bytes.IndexFunc(f, func(r rune) bool { return 0 < r && r < 0x9 }) == -1 { ee, _ := charset.Lookup(enc) if ee == nil { continue } var buf bytes.Buffer ic := transform.NewWriter(&buf, ee.NewDecoder()) _, err := ic.Write(f) if err != nil { next = -1 continue } lf := false if len(arg.bom) > 0 && len(f)%2 != 0 { ic.Write([]byte{0}) lf = true } err = ic.Close() if err != nil { if verbose { println(err.Error()) } next = -1 continue } f = buf.Bytes() if lf { f = f[:len(f)-1] } } } size = len(f) if size == 0 { continue } for next != -1 { for { if next >= size { next = -1 break } if f[next] == '\n' { break } next++ } n++ if next == -1 { t = f[prev:] } else { t = f[prev:next] prev = next + 1 next++ } l = len(t) if l > 0 && t[l-1] == '\r' { t = t[:l-1] l-- } var match bool if only { var matches []string ts := string(t) if re, ok := arg.pattern.(*regexp.Regexp); ok { matches = re.FindAllString(ts, -1) } else if s, ok := arg.pattern.(string); ok { if ignorecase { ts = strings.ToLower(ts) } ti := 0 tl := len(ts) for ti != -1 && ti < tl-1 { ti = strings.Index(ts[ti:], s) if ti != -1 { matches = append(matches, s) ti++ } } } match = len(matches) > 0 // skip if not match without invert, or match with invert. if match == invert { continue } if verbose { println("found("+enc+"):", path) } if list { matchedfile(path) did = true break } for _, m := range matches { countMatch++ if count { continue } if strings.IndexFunc( m, func(r rune) bool { return 0 < r && r < 0x9 }) != -1 { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } else { if number { if utf8.ValidString(m) { matchedline(path, n, m, arg) } else { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } } else { if utf8.ValidString(m) { matchedline("", 0, m, arg) } else { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } } } } } else { if re, ok := arg.pattern.(*regexp.Regexp); ok { if len(re.FindAllIndex(t, 1)) > 0 { match = true } } else if s, ok := arg.pattern.(string); ok { if ignorecase { if strings.Index(strings.ToLower(string(t)), strings.ToLower(s)) > -1 { match = true } } else { if strings.Index(string(t), s) > -1 { match = true } } } // skip if not match without invert, or match with invert. if match == invert { continue } if verbose { println("found("+enc+"):", path) } if list { matchedfile(path) did = true break } countMatch++ if count { did = true continue } if arg.single && !number { if utf8.Valid(t) { matchedline("", -1, string(t), arg) } else { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } } else { if bytes.IndexFunc( t, func(r rune) bool { return 0 < r && r < 0x9 }) != -1 { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } else if utf8.Valid(t) { if after <= 0 && before <= 0 { matchedline(path, n, string(t), arg) } else { if countMatch > 1 { os.Stdout.WriteString("---\n") } bprev, bnext := next-l-2, next-l-2 lines := make([]string, 0) for i := 0; i < before && bprev > 0; i++ { for { if bprev == 0 || f[bprev-1] == '\n' { lines = append(lines, string(f[bprev:bnext])) bnext = bprev - 1 bprev-- break } bprev-- } } for i := len(lines); i > 0; i-- { matchedline(path, i-n, lines[i-1], arg) } matchedline(path, n, string(t), arg) lines = make([]string, 0) aprev, anext := next, next for i := 0; i < after && anext >= 0 && anext < size; i++ { for { if anext == size || f[anext] == '\n' { lines = append(lines, string(f[aprev:anext])) aprev = anext + 1 anext++ break } anext++ } } for i := 0; i < len(lines); i++ { matchedline(path, -n-i-1, lines[i], arg) } } } else { errorline(fmt.Sprintf("matched binary file: %s", path)) did = true break } } } did = true } runtime.GC() if did || next == -1 { break } } }
func NewScanner(src []byte) *Scanner { r := bytes.NewReader(src) s := &Scanner{Scanner: bufio.NewScanner(r)} s.Split(func(byteData []byte, atEOF bool) (advance int, token []byte, err error) { data := []rune(string(byteData)) if atEOF && len(byteData) == 0 { return 0, nil, nil } // r, _ := utf8.DecodeRune(data) r := data[0] retRunes := func(data []rune) (int, []byte, error) { seg := []byte(string(data)) return len(seg), seg, nil } retBytes := func() (int, []byte, error) { return len(byteData), byteData, nil } isQuot := func(r rune) bool { return r == '`' || r == '\'' || r == '"' } if isQuot(r) { s.kind = STRING for j := 1; j < len(data); j++ { if data[j] == '\\' { j++ } else if data[j] == r { return retRunes(data[0 : j+1]) } else if atEOF { return retBytes() } } return 0, nil, nil } alpha := func(r rune) bool { return byte(r) == '_' || unicode.IsLetter(r) } alnum := func(r rune) bool { return alpha(r) || unicode.IsDigit(r) } if unicode.IsUpper(r) { s.typ = true s.kind = TYPE } else if alpha(r) { s.name = true s.kind = PLAINTEXT } if s.typ || s.name { i := lastContiguousIndexFunc([]byte(string(data)), alnum) if i >= 0 { s.typ, s.name = false, false if _, isKwd := Keywords[string(data[0:i+1])]; isKwd { s.kind = KEYWORD } return retRunes(data[0 : i+1]) } return 0, nil, nil } if unicode.IsDigit(r) { s.kind = DECIMAL i := lastContiguousIndexFunc([]byte(string(data)), unicode.IsDigit) if i >= 0 { return retRunes(data[:i+1]) } return 0, nil, nil } if unicode.IsSpace(r) { s.kind = WHITESPACE i := lastContiguousIndexFunc([]byte(string(data)), unicode.IsSpace) if i >= 0 { if i+1 <= len(data) { return retRunes(data[:i+1]) } else { return retRunes(data) } } if atEOF { return retBytes() } return 0, nil, nil } lineComments := []string{"//", "#"} for _, lc := range lineComments { if i := indexRunes(data, string(lc)); i == 0 { s.kind = COMMENT if i := indexRune(data, '\n'); i >= 0 { return retRunes(data[0 : i+1]) } if atEOF { return retBytes() } return 0, nil, nil } } if i := indexRunes(data, "/*"); i == 0 { s.kind = COMMENT if i := indexRunes(data, "*/"); i >= 0 { return retRunes(data[0 : i+2]) } if atEOF { return retBytes() } return 0, nil, nil } if i := bytes.IndexFunc([]byte(string(data)), func(r rune) bool { return !alnum(r) && !unicode.IsSpace(r) && !isQuot(r) }); i >= 0 { s.kind = PUNCTUATION return retRunes(data[0 : i+1]) } if atEOF { return retBytes() } return 0, nil, nil }) return s }