github.com/qiniu/x@v1.11.9/bytes/replace.go (about)

     1  /*
     2   Copyright 2020 Qiniu Limited (qiniu.com)
     3  
     4   Licensed under the Apache License, Version 2.0 (the "License");
     5   you may not use this file except in compliance with the License.
     6   You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10   Unless required by applicable law or agreed to in writing, software
    11   distributed under the License is distributed on an "AS IS" BASIS,
    12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   See the License for the specific language governing permissions and
    14   limitations under the License.
    15  */
    16  
    17  package bytes
    18  
    19  import (
    20  	"bytes"
    21  )
    22  
    23  // ---------------------------------------------------
    24  
    25  // ReplaceAt does a replace operation at position `off` in place.
    26  func ReplaceAt(b []byte, off, nsrc int, dest []byte) []byte {
    27  	ndelta := len(dest) - nsrc
    28  	if ndelta < 0 {
    29  		left := b[off+nsrc:]
    30  		off += copy(b[off:], dest)
    31  		off += copy(b[off:], left)
    32  		return b[:off]
    33  	}
    34  
    35  	if ndelta > 0 {
    36  		b = append(b, dest[:ndelta]...)
    37  		copy(b[off+len(dest):], b[off+nsrc:])
    38  		copy(b[off:], dest)
    39  	} else {
    40  		copy(b[off:], dest)
    41  	}
    42  	return b
    43  }
    44  
    45  // ReplaceOne does a replace operation from `from` position in place.
    46  // It returns an offset for next replace operation.
    47  // If the returned offset is -1, it means no replace operation occurred.
    48  func ReplaceOne(b []byte, from int, src, dest []byte) ([]byte, int) {
    49  	pos := bytes.Index(b[from:], src)
    50  	if pos < 0 {
    51  		return b, -1
    52  	}
    53  
    54  	from += pos
    55  	return ReplaceAt(b, from, len(src), dest), from + len(dest)
    56  }
    57  
    58  // Unlike bytes.Replace, this Replace does replace operations in place.
    59  func Replace(b []byte, src, dest []byte, n int) []byte {
    60  	from := 0
    61  	for n != 0 {
    62  		b, from = ReplaceOne(b, from, src, dest)
    63  		if from < 0 {
    64  			break
    65  		}
    66  		n--
    67  	}
    68  	return b
    69  }
    70  
    71  // ---------------------------------------------------