github.com/tobgu/qframe@v0.4.0/internal/strings/convert.go (about)

     1  package strings
     2  
     3  import (
     4  	"strconv"
     5  	"unicode"
     6  	"unicode/utf8"
     7  	"unsafe"
     8  )
     9  
    10  func ParseInt(b []byte) (i int, err error) {
    11  	s := UnsafeBytesToString(b)
    12  	return strconv.Atoi(s)
    13  }
    14  
    15  func ParseFloat(b []byte) (float64, error) {
    16  	s := UnsafeBytesToString(b)
    17  	return strconv.ParseFloat(s, 64)
    18  }
    19  
    20  func ParseBool(b []byte) (bool, error) {
    21  	return strconv.ParseBool(UnsafeBytesToString(b))
    22  }
    23  
    24  func UnsafeBytesToString(in []byte) string {
    25  	return unsafe.String(unsafe.SliceData(in), len(in))
    26  }
    27  
    28  func QuotedBytes(s string) []byte {
    29  	result := make([]byte, 0, len(s)+2)
    30  	result = append(result, byte('"'))
    31  	result = append(result, []byte(s)...)
    32  	return append(result, byte('"'))
    33  }
    34  
    35  // This is a modified, zero alloc, version of the stdlib function strings.ToUpper.
    36  // The passed in byte buffer is used to hold the converted string. The returned
    37  // string is not safe to use when bP goes out of scope and the content may
    38  // be overwritten upon next call to this function.
    39  func ToUpper(bP *[]byte, s string) string {
    40  	// nbytes is the number of bytes encoded in b.
    41  	var nbytes int
    42  
    43  	var b []byte
    44  	for i, c := range s {
    45  		r := unicode.ToUpper(c)
    46  		if r == c {
    47  			continue
    48  		}
    49  
    50  		if len(*bP) >= len(s)+utf8.UTFMax {
    51  			b = *bP
    52  		} else {
    53  			b = make([]byte, len(s)+utf8.UTFMax)
    54  		}
    55  		nbytes = copy(b, s[:i])
    56  		if r >= 0 {
    57  			if r <= utf8.RuneSelf {
    58  				b[nbytes] = byte(r)
    59  				nbytes++
    60  			} else {
    61  				nbytes += utf8.EncodeRune(b[nbytes:], r)
    62  			}
    63  		}
    64  
    65  		if c == utf8.RuneError {
    66  			// RuneError is the result of either decoding
    67  			// an invalid sequence or '\uFFFD'. Determine
    68  			// the correct number of bytes we need to advance.
    69  			_, w := utf8.DecodeRuneInString(s[i:])
    70  			i += w
    71  		} else {
    72  			i += utf8.RuneLen(c)
    73  		}
    74  
    75  		s = s[i:]
    76  		break
    77  	}
    78  
    79  	if b == nil {
    80  		return s
    81  	}
    82  
    83  	for _, c := range s {
    84  		r := unicode.ToUpper(c)
    85  
    86  		// common case
    87  		if (0 <= r && r <= utf8.RuneSelf) && nbytes < len(b) {
    88  			b[nbytes] = byte(r)
    89  			nbytes++
    90  			continue
    91  		}
    92  
    93  		// b is not big enough or r is not a ASCII rune.
    94  		if r >= 0 {
    95  			if nbytes+utf8.UTFMax >= len(b) {
    96  				// Grow the buffer.
    97  				nb := make([]byte, 2*len(b))
    98  				copy(nb, b[:nbytes])
    99  				b = nb
   100  			}
   101  			nbytes += utf8.EncodeRune(b[nbytes:], r)
   102  		}
   103  	}
   104  
   105  	*bP = b
   106  	return UnsafeBytesToString(b[:nbytes])
   107  }
   108  
   109  // InterfaceSliceToStringSlice converts a slice of interface{} to a slice of strings.
   110  // If the input is not a slice of interface{} it is returned unmodified. If the input
   111  // slice does not consist of strings (only) the input is returned unmodified.
   112  func InterfaceSliceToStringSlice(input interface{}) interface{} {
   113  	ifSlice, ok := input.([]interface{})
   114  	if !ok {
   115  		return input
   116  	}
   117  
   118  	result := make([]string, len(ifSlice))
   119  	for i, intfc := range ifSlice {
   120  		s, ok := intfc.(string)
   121  		if !ok {
   122  			return input
   123  		}
   124  		result[i] = s
   125  	}
   126  
   127  	return result
   128  }