github.com/mithrandie/csvq@v1.18.1/lib/query/utils.go (about)

     1  package query
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strings"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/mithrandie/csvq/lib/option"
    11  	"github.com/mithrandie/csvq/lib/value"
    12  
    13  	"github.com/mithrandie/ternary"
    14  )
    15  
    16  const LimitToUseUintSlicePool = 20
    17  
    18  type UintPool struct {
    19  	limitToUseSlice int
    20  	m               map[uint]bool
    21  	values          []uint
    22  }
    23  
    24  func NewUintPool(initCap int, limitToUseSlice int) *UintPool {
    25  	return &UintPool{
    26  		limitToUseSlice: limitToUseSlice,
    27  		m:               make(map[uint]bool, initCap),
    28  		values:          make([]uint, 0, initCap),
    29  	}
    30  }
    31  
    32  func (c *UintPool) Exists(val uint) bool {
    33  	if c.limitToUseSlice <= len(c.values) {
    34  		_, ok := c.m[val]
    35  		return ok
    36  	}
    37  
    38  	for i := range c.values {
    39  		if val == c.values[i] {
    40  			return true
    41  		}
    42  	}
    43  	return false
    44  }
    45  
    46  func (c *UintPool) Add(val uint) {
    47  	c.m[val] = true
    48  	c.values = append(c.values, val)
    49  }
    50  
    51  func (c *UintPool) Range(fn func(idx int, value uint) error) error {
    52  	var err error
    53  	for i := range c.values {
    54  		if err = fn(i, c.values[i]); err != nil {
    55  			break
    56  		}
    57  	}
    58  	return err
    59  }
    60  
    61  func (c *UintPool) Len() int {
    62  	return len(c.values)
    63  }
    64  
    65  func InStrSliceWithCaseInsensitive(s string, list []string) bool {
    66  	for _, v := range list {
    67  		if strings.EqualFold(s, v) {
    68  			return true
    69  		}
    70  	}
    71  	return false
    72  }
    73  
    74  func Distinguish(list []value.Primary, flags *option.Flags) []value.Primary {
    75  	values := make(map[string]int, 40)
    76  	valueKeys := make([]string, 0, 40)
    77  
    78  	buf := GetComparisonKeysBuf()
    79  
    80  	for i, v := range list {
    81  		buf.Reset()
    82  		SerializeComparisonKeys(buf, []value.Primary{v}, flags)
    83  		key := buf.String()
    84  		if _, ok := values[key]; !ok {
    85  			values[key] = i
    86  			valueKeys = append(valueKeys, key)
    87  		}
    88  	}
    89  
    90  	PutComparisonkeysBuf(buf)
    91  
    92  	distinguished := make([]value.Primary, len(valueKeys))
    93  	for i, key := range valueKeys {
    94  		distinguished[i] = list[values[key]]
    95  	}
    96  
    97  	return distinguished
    98  }
    99  
   100  func FormatCount(i int, obj string) string {
   101  	var s string
   102  	if i == 0 {
   103  		s = fmt.Sprintf("no %s", obj)
   104  	} else if i == 1 {
   105  		s = fmt.Sprintf("%d %s", i, obj)
   106  	} else {
   107  		s = fmt.Sprintf("%d %ss", i, obj)
   108  	}
   109  	return s
   110  }
   111  
   112  var comparisonKeysBufPool = &sync.Pool{
   113  	New: func() interface{} {
   114  		return &bytes.Buffer{}
   115  	},
   116  }
   117  
   118  func GetComparisonKeysBuf() *bytes.Buffer {
   119  	buf := comparisonKeysBufPool.Get().(*bytes.Buffer)
   120  	return buf
   121  }
   122  
   123  func PutComparisonkeysBuf(buf *bytes.Buffer) {
   124  	buf.Reset()
   125  	comparisonKeysBufPool.Put(buf)
   126  }
   127  
   128  func SerializeComparisonKeys(buf *bytes.Buffer, values []value.Primary, flags *option.Flags) {
   129  	for i, val := range values {
   130  		if 0 < i {
   131  			buf.WriteByte(58)
   132  		}
   133  
   134  		if flags.StrictEqual {
   135  			SerializeIdenticalKey(buf, val)
   136  		} else {
   137  			SerializeKey(buf, val, flags)
   138  		}
   139  	}
   140  }
   141  
   142  func SerializeKey(buf *bytes.Buffer, val value.Primary, flags *option.Flags) {
   143  	if value.IsNull(val) {
   144  		serializeNull(buf)
   145  	} else if in := value.ToIntegerStrictly(val); !value.IsNull(in) {
   146  		serializeInteger(buf, in.(*value.Integer).String())
   147  		value.Discard(in)
   148  	} else if f := value.ToFloat(val); !value.IsNull(f) {
   149  		serializeFloat(buf, f.(*value.Float).String())
   150  		value.Discard(f)
   151  	} else if dt := value.ToDatetime(val, flags.DatetimeFormat, flags.GetTimeLocation()); !value.IsNull(dt) {
   152  		serializeDatetime(buf, dt.(*value.Datetime).Raw())
   153  		value.Discard(dt)
   154  	} else if b := value.ToBoolean(val); !value.IsNull(b) {
   155  		if b.(*value.Boolean).Raw() {
   156  			serializeInteger(buf, "1")
   157  		} else {
   158  			serializeInteger(buf, "0")
   159  		}
   160  	} else if s, ok := val.(*value.String); ok {
   161  		serializeString(buf, s.Raw())
   162  	} else {
   163  		serializeNull(buf)
   164  	}
   165  }
   166  
   167  func SerializeIdenticalKey(buf *bytes.Buffer, val value.Primary) {
   168  	switch val.(type) {
   169  	case *value.String:
   170  		serializeCaseSensitiveString(buf, val.(*value.String).Raw())
   171  	case *value.Integer:
   172  		serializeInteger(buf, val.(*value.Integer).String())
   173  	case *value.Float:
   174  		serializeFloat(buf, val.(*value.Float).String())
   175  	case *value.Boolean:
   176  		serializeBoolean(buf, val.(*value.Boolean).Raw())
   177  	case *value.Ternary:
   178  		serializeTernary(buf, val.(*value.Ternary).Ternary())
   179  	case *value.Datetime:
   180  		serializeDatetime(buf, val.(*value.Datetime).Raw())
   181  	default:
   182  		serializeNull(buf)
   183  	}
   184  }
   185  
   186  func serializeNull(buf *bytes.Buffer) {
   187  	buf.Write([]byte{91, 78, 93})
   188  }
   189  
   190  func serializeInteger(buf *bytes.Buffer, s string) {
   191  	buf.Write([]byte{91, 73, 93})
   192  	buf.WriteString(s)
   193  }
   194  
   195  func serializeFloat(buf *bytes.Buffer, s string) {
   196  	buf.Write([]byte{91, 70, 93})
   197  	buf.WriteString(s)
   198  }
   199  
   200  func serializeDatetime(buf *bytes.Buffer, t time.Time) {
   201  	serializeDatetimeFromUnixNano(buf, t.UnixNano())
   202  }
   203  
   204  func serializeDatetimeFromUnixNano(buf *bytes.Buffer, t int64) {
   205  	buf.Write([]byte{91, 68, 93})
   206  	buf.WriteString(value.Int64ToStr(t))
   207  }
   208  
   209  func serializeString(buf *bytes.Buffer, s string) {
   210  	buf.Write([]byte{91, 83, 93})
   211  	buf.WriteString(strings.ToUpper(option.TrimSpace(s)))
   212  }
   213  
   214  func serializeCaseSensitiveString(buf *bytes.Buffer, s string) {
   215  	buf.Write([]byte{91, 83, 93})
   216  	buf.WriteString(option.TrimSpace(s))
   217  }
   218  
   219  func serializeBoolean(buf *bytes.Buffer, b bool) {
   220  	buf.Write([]byte{91, 66, 93})
   221  	if b {
   222  		buf.WriteString("T")
   223  	} else {
   224  		buf.WriteString("F")
   225  	}
   226  }
   227  
   228  func serializeTernary(buf *bytes.Buffer, t ternary.Value) {
   229  	buf.Write([]byte{91, 84, 93})
   230  	if t == ternary.TRUE {
   231  		buf.WriteString("T")
   232  	} else if t == ternary.FALSE {
   233  		buf.WriteString("F")
   234  	} else {
   235  		buf.WriteString("U")
   236  	}
   237  }