github.com/qxnw/lib4go@v0.0.0-20180426074627-c80c7e84b925/influxdb/escape/bytes.go (about)

     1  // Package escape contains utilities for escaping parts of InfluxQL
     2  // and InfluxDB line protocol.
     3  package escape
     4  
     5  import (
     6  	"bytes"
     7  	"strings"
     8  )
     9  
    10  // Codes is a map of bytes to be escaped.
    11  var Codes = map[byte][]byte{
    12  	',': []byte(`\,`),
    13  	'"': []byte(`\"`),
    14  	' ': []byte(`\ `),
    15  	'=': []byte(`\=`),
    16  }
    17  
    18  // Bytes escapes characters on the input slice, as defined by Codes.
    19  func Bytes(in []byte) []byte {
    20  	for b, esc := range Codes {
    21  		in = bytes.Replace(in, []byte{b}, esc, -1)
    22  	}
    23  	return in
    24  }
    25  
    26  const escapeChars = `," =`
    27  
    28  // IsEscaped returns whether b has any escaped characters,
    29  // i.e. whether b seems to have been processed by Bytes.
    30  func IsEscaped(b []byte) bool {
    31  	for len(b) > 0 {
    32  		i := bytes.IndexByte(b, '\\')
    33  		if i < 0 {
    34  			return false
    35  		}
    36  
    37  		if i+1 < len(b) && strings.IndexByte(escapeChars, b[i+1]) >= 0 {
    38  			return true
    39  		}
    40  		b = b[i+1:]
    41  	}
    42  	return false
    43  }
    44  
    45  // AppendUnescaped appends the unescaped version of src to dst
    46  // and returns the resulting slice.
    47  func AppendUnescaped(dst, src []byte) []byte {
    48  	var pos int
    49  	for len(src) > 0 {
    50  		next := bytes.IndexByte(src[pos:], '\\')
    51  		if next < 0 || pos+next+1 >= len(src) {
    52  			return append(dst, src...)
    53  		}
    54  
    55  		if pos+next+1 < len(src) && strings.IndexByte(escapeChars, src[pos+next+1]) >= 0 {
    56  			if pos+next > 0 {
    57  				dst = append(dst, src[:pos+next]...)
    58  			}
    59  			src = src[pos+next+1:]
    60  			pos = 0
    61  		} else {
    62  			pos += next + 1
    63  		}
    64  	}
    65  
    66  	return dst
    67  }
    68  
    69  // Unescape returns a new slice containing the unescaped version of in.
    70  func Unescape(in []byte) []byte {
    71  	if len(in) == 0 {
    72  		return nil
    73  	}
    74  
    75  	if bytes.IndexByte(in, '\\') == -1 {
    76  		return in
    77  	}
    78  
    79  	i := 0
    80  	inLen := len(in)
    81  	var out []byte
    82  
    83  	for {
    84  		if i >= inLen {
    85  			break
    86  		}
    87  		if in[i] == '\\' && i+1 < inLen {
    88  			switch in[i+1] {
    89  			case ',':
    90  				out = append(out, ',')
    91  				i += 2
    92  				continue
    93  			case '"':
    94  				out = append(out, '"')
    95  				i += 2
    96  				continue
    97  			case ' ':
    98  				out = append(out, ' ')
    99  				i += 2
   100  				continue
   101  			case '=':
   102  				out = append(out, '=')
   103  				i += 2
   104  				continue
   105  			}
   106  		}
   107  		out = append(out, in[i])
   108  		i += 1
   109  	}
   110  	return out
   111  }