Files
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

165 lines
3.3 KiB
Go

package checkfn
import (
"bytes"
"fmt"
"reflect"
"regexp"
"strings"
)
// IsNil value check
func IsNil(v any) bool {
if v == nil {
return true
}
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return rv.IsNil()
default:
return false
}
}
// IsSimpleKind kind in: string, bool, intX, uintX, floatX
func IsSimpleKind(k reflect.Kind) bool {
if reflect.String == k {
return true
}
return k > reflect.Invalid && k <= reflect.Float64
}
// IsEqual determines if two objects are considered equal.
//
// TIP: cannot compare function type
func IsEqual(src, dst any) bool {
if src == nil || dst == nil {
return src == dst
}
bs1, ok := src.([]byte)
if !ok {
return reflect.DeepEqual(src, dst)
}
bs2, ok := dst.([]byte)
if !ok {
return false
}
if bs1 == nil || bs2 == nil {
return bs1 == nil && bs2 == nil
}
return bytes.Equal(bs1, bs2)
}
// Contains try loop over the data check if the data includes the element.
//
// data allow types: string, map, array, slice
//
// map - check key exists
// string - check sub-string exists
// array,slice - check sub-element exists
//
// Returns:
// - valid: data is valid
// - found: element was found
//
// return (false, false) if impossible.
// return (true, false) if element was not found.
// return (true, true) if element was found.
func Contains(data, elem any) (valid, found bool) {
if data == nil {
return false, false
}
dataRv := reflect.ValueOf(data)
dataRt := reflect.TypeOf(data)
dataKind := dataRt.Kind()
// string
if dataKind == reflect.String {
return true, strings.Contains(dataRv.String(), fmt.Sprint(elem))
}
// map
if dataKind == reflect.Map {
mapKeys := dataRv.MapKeys()
for i := 0; i < len(mapKeys); i++ {
if IsEqual(mapKeys[i].Interface(), elem) {
return true, true
}
}
return true, false
}
// array, slice - other return false
if dataKind != reflect.Slice && dataKind != reflect.Array {
return false, false
}
for i := 0; i < dataRv.Len(); i++ {
if IsEqual(dataRv.Index(i).Interface(), elem) {
return true, true
}
}
return true, false
}
// StringsContains check string slice contains sub-string
func StringsContains(ss []string, sub string) bool {
for _, v := range ss {
if v == sub {
return true
}
}
return false
}
var (
// check is number: int or float
numReg = regexp.MustCompile(`^[-+]?\d*\.?\d+$`)
// is positive number: int or float
pNumReg = regexp.MustCompile(`^\d*\.?\d+$`)
)
// IsNumeric returns true if the given string is a numeric, otherwise false.
func IsNumeric(s string) bool {
if s == "" {
return false
}
return numReg.MatchString(s)
}
// IsPositiveNum check input string is positive number
func IsPositiveNum(s string) bool {
if s == "" {
return false
}
if s[0] == '-' {
return false
}
return pNumReg.MatchString(s)
}
// IsHttpURL check input is http/https url
func IsHttpURL(s string) bool {
return strings.HasPrefix(s, "http://") || strings.HasPrefix(s, "https://")
}
// IndexByteAfter find index of byte after startIndex. return -1 if not found
//
// eg:
//
// IndexByteAfter("abcabc", 'b', 0) = 1
// IndexByteAfter("abcabc", 'b', 2) = 4
func IndexByteAfter(s string, b byte, startIndex int) int {
idx := strings.IndexByte(s[startIndex:], b)
if idx < 0 {
return -1
}
return idx + startIndex
}