Go Small Library

Related tags

Utilities gosl
Overview

Go Small Library (gosl)

Copyright Gon Y. Yi 2021 https://gonyyi.com/copyright

Goal

General

  • No import of any library whatsoever including standard library.
  • Most of the code should have zero memory allocation.
  • Only frequently used functions.
  • Only very minimum functions.
  • Safe code
    • 99%+ code coverage
    • All the code should have tests, benchmarks and examples
  • Minimize default allocation caused by importing the library
    • Currently bufp is allocated at global level when importing the library as this is required for the logger.
Comments
  • Mutex, MuInt, Pool

    Mutex, MuInt, Pool

    Add Status() that returns if channel is not-init, active or closed.

    Apply to all where channel is being used.

    Status

    • -1: un-initialized
    • 0: closed
    • 1: active
    // Status will return channel status
    // -1 Not init
    //  0 Closed
    //  1 Active
    func (m Mutex) Status() int {
    	// Not initialized
    	if m == nil {
    		return -1
    	}
    
    	// Active with data
    	if len(m) > 0 {
    		return 1
    	}
    
    	// Either active or closed
    	select {
    	case _, ok := <-m: // NOTE: this only runs when the chan is closed OR has something.
    		if !ok {
    			// Closed
    			return 0
    		}
    	default:
    	}
    	// Active without data
    	return 1
    }
    
    Rejected Feature - Modify Coded 
    opened by gonyyi 4
  • Bug on Elem() - returning the delimiter

    Bug on Elem() - returning the delimiter

    Elem -1 returned a delimiter with it.

    gosl.Elem("T1~Fri Oct 01, 2021 at 00:00:01", '~', -1) 
    // returned: "~Fri Oct 01, 2021 at 00:00:01"
    
    Bug Accepted Coded 
    opened by gonyyi 3
  • Add type `Ver` back

    Add type `Ver` back

    Textbox (https://github.com/gonyyi/textbox) is very simple and often used for every code. Maybe add it to Gosl?

    Usage suggestions

    • TextBox(string) string
    • TextBox(string, Writer)

    Maybe integrate with a type Ver?

    Name suggestion: Whoami, Ver, Name, Info In last release, Version was removed. But maybe can be integrated together?

    const Version gosl.Ver = "Gosl 1.1.0"
    ...
    Version.PrintBox() // print box to stdout
    n, err := Version.WriteBox(io.Writer)
    s := Version.BoxString()
    // Version.Append([]byte) []byte
    dst = Version.Append(dst) 
    

    If Ver's coming back, any way to include source, date, etc into it? Maybe store as a single string and parse it?

    Eg. Gosl; v=1.1.0; c=Copyright 2022 Gon Yi; a=Gon Yi; d=2020-01-06; u=gonyyi.com; u=github.com/gonyyi where multiple u= in this example will indicate multiple items or lines.

    • Semicolon delimited, but the first item to be name of the program.
    • v: version
    • a: author
    • c: copyright message
    • d: date
    • u: URL

    Usage

    • Basic
      • v.String()string
      • v.Bytes([]byte)[]byte
      • v.Println()
      • v.Name() string
      • v.Author() string
      • v.Date() string
      • v.Box() Box // convert version to Box

    ??

    • Box
      • b.String(...string) string
      • v.BoxPrintln(...string)
      • v.BoxWrite(Writer)
      • v.BoxBytes([]byte) []byte
    Feature - New Rejected Coded 
    opened by gonyyi 3
  • Custom comparator bug with `SortSlice()`, and `SortString()`

    Custom comparator bug with `SortSlice()`, and `SortString()`

    Error Message

    panic: runtime error: index out of range [2] with length 2
    
    goroutine 1 [running]:
    main.main.func2(0x102d23a, 0x1066eb0)
            .../test.go:29 +0x67
    github.com/gonyyi/gosl.SortStrings({0xc000112ee0, 0x3, 0x2}, 0xc000112ea0)
            ...github.com/gonyyi/[email protected]/sort.go:43 +0x5e
    main.main()
            .../test.go:28 +0x2b9
    

    Affected

    This error is triggered when two conditions are met.

    1. Two (2) or less items in the slice
    2. And uses comparator (func(idx1, idx2 int) bool)

    This bug affects sort functions below.

    • SortSlice()
    • SortString()

    Cuase

    https://github.com/gonyyi/gosl/blob/7f3f8cc6802ef1755fb9f001b86c1ae6845175e7/sort.go#L14-L18 https://github.com/gonyyi/gosl/blob/7f3f8cc6802ef1755fb9f001b86c1ae6845175e7/sort.go#L41-L45

    When a comparator is given, it example the comparator by examing it to avoid a bug. However, this became a bug itself adversally..

    Bug 
    opened by gonyyi 3
  • Add `Contains(string, string)bool`

    Add `Contains(string, string)bool`

    Gosl has HasPrefix and HasSuffix, but doesn't have Contains.

    Function name to be either Contain() or Contains()

    if gosl.Contain("hello Gon", "Gon") {
        println("Greeting for Gon")
    }
    
    Feature - New Accepted Coded 
    opened by gonyyi 3
  • Add `NewBufferPool(size int) BufferPool`

    Add `NewBufferPool(size int) BufferPool`

    This will require some changes, however, current default buffer pool does not allow a user to change the size of buffer. Therefore need one that can be customized.

    Usage

    bp := gosl.NewBufferPool(1024) // create buffer pool with buffer size 1k
    buf := bp.Get() // get a buffer
    buf.Free() // returns a buffer to pool 
    
    Feature - Modify 
    opened by gonyyi 2
  • Add `ByteCount([]byte, byte) int`, `Count(string, string) int`

    Add `ByteCount([]byte, byte) int`, `Count(string, string) int`

    This will be used to check if number of delimiter is correct

    // Count counts string lookup value from string s, returns total
    func Count(s string, lookup string) int {
    	count := 0
    	for i:=0; i<len(s)-len(lookup)+1; i++ {
    		if s[i:i+len(lookup)] == lookup {
    			count += 1
    		}
    	}
    	return count
    }
    
    // ByteCount counts byte `c` value from bytes `p`, returns total
    func ByteCount(p []byte, c byte) int {
    	count := 0
    	for _, v := range p {
    		if v == c {
    			count += 1
    		}
    	}
    	return count
    }
    
    Feature - New Accepted Coded 
    opened by gonyyi 2
  • Add `SortAny()`

    Add `SortAny()`

    This function will sort any slice without any memory allocation.

    Desired name: SortAny or SortSlice

    package main
    
    // SortAny is designed to sort any slice with no memory allocation.
    // The usage is bit different than Go's `sort.Slice()` function.
    // - pSize: size of slice that needs to be sorted
    // - swap: a function that will swap the slice
    // - less: a function that will return true when index i of slice is less than j's.
    //
    // Example:
    // 	SortAny(
    //		len(a), // size of the slice
    //		func(i1, i2 int) { a[i1], a[i2] = a[i2], a[i1] },       // swap
    //		func(i, j int) bool { return a[i].Score > a[j].Score }, // less
    //	)
    func SortAny(pSize int, swap func(i, j int), less func(i, j int) bool) {
    	// This function requires both swap and less function.
    	if pSize < 2 ||  swap == nil || less == nil {
    		return
    	}
    	for {
    		changed := false
    		for i := 0; i < pSize-1; i++ {
    			if !less(i, i+1) { // 2nd one is bigger
    				if !less(i+1, i) {
    					continue // equal
    				}
    				// swap
    				swap(i, i+1)
    				changed = true
    			}
    		}
    		// Nothing changed, no more need to run
    		if changed == false {
    			break
    		}
    	}
    }
    
    type Alien struct {
    	StudentID int
    	Name      string
    	Score     int
    }
    
    func main() {
    	a := []Alien{
    		{StudentID: 4, Name: "Jordon", Score: 11},
    		{StudentID: 1, Name: "Aaron", Score: 13},
    		{StudentID: 2, Name: "Gon", Score: 11},
    		{StudentID: 3, Name: "Aaron", Score: 17},
    		{StudentID: 5, Name: "Jordan", Score: 20},
    	}
    
    	// Sort by highest score
    	// If want multi sort, modify `less` function such as:
    	//   // Sort by highest score, and alphabetical 
    	//   func(i,j int) bool {
    	//     if a[i].Score == a[j].Score { return a[i].Name > a[j].Name }
    	//     return a[i].Score > a[j].Score
    	//   }
    	SortAny(
    		len(a), // size of the slice
    		func(i1, i2 int) { a[i1], a[i2] = a[i2], a[i1] },       // swap
    		func(i,j int) bool {
    			if a[i].Score == a[j].Score { return a[i].Name > a[j].Name }
    			return a[i].Score > a[j].Score
    		},
    	)
    	
    	for _, v := range a {
    		println(v.StudentID, v.Score, v.Name)
    	}
    
    }
    
    Feature - New Accepted Coded 
    opened by gonyyi 2
  • Add `DeduplicateStrings([]string)[]string`

    Add `DeduplicateStrings([]string)[]string`

    Not sure about the naming.. But considering,

    • DedupStrings()
    • DeduplicateStrings()
    • UniqueStrings()
    package main
    
    import (
    	"github.com/gonyyi/gosl"
    )
    
    // DeduplicateStrings will deduplicate string slice
    // First, it will sort, then exam from the left to make sure every values are different from previous.
    // NOTE: during the dedup process, this will alter original slice -- this will sort it.
    func DeduplicateStrings(p []string) []string {
    	// when there's one or no element, no need to dedup
    	if len(p) < 2 {
    		return p
    	}
    
    	// sort the string
    	gosl.SortStrings(p, nil)
    
    	// starting with the 2nd element as 1st will be the baseline.
    	// whenever new one's found, set its index to cur; and return up to cur
    	cur := 0
    	for i := 1; i < len(p); i++ {
    		// if element is same as previous, skip
    		if p[i-1] == p[i] {
    			continue
    		}
    		cur += 1
    		p[cur] = p[i]
    	}
    	return p[:cur+1]
    }
    
    func main() {
    	a := []string{"a", "d", "b", "x", "b", "d"}
    	a = DeduplicateStrings(a)
    
    	for _, v := range a {
    		print(v + " ")
    	}
    }
    
    Documentation Coded 
    opened by gonyyi 2
  • `bufPoolItem` to support more methods

    `bufPoolItem` to support more methods

    Now all the buf pool item from GetBuffer() has to saved to buf.Buf again as below. And this became common bug when writing a code with buf pool item.

    buf := gosl.GetBuffer()
    buf.Buf = buf.Buf.WriteString(s.time.Format("2006/01/02 15:04:05"))
    

    Add methods to simplify as below.

    buf := gosl.GetBuffer()
    buf.WriteString(s.time.Format("2006/01/02 15:04:05"))
    
    Feature - New Accepted Coded 
    opened by gonyyi 2
  • FilterAny() for any slice

    FilterAny() for any slice

    Func

    func FilterAny(pSize int, cut func(idx int), keep func(idx int) bool) (removed int) {
    	for i := pSize - 1; i >= 0; i-- { // since need an index, subtract by 1
    		if keep(i) == false {
    			cut(i)
    			removed += 1
    		}
    	}
    	return removed
    }
    

    Test

    func TestFilterAny(t *testing.T) {
    	t.Run("basic", func(t *testing.T) {
    		SHOW := false
    
    		prn := func(s []string) {
    			for i := 0; i < len(s); i++ {
    				println("\t", i, s[i])
    			}
    		}
    		_ = prn
    
    		var s = []string{"GON", "IS", "HERE", "123", "HAHAHA", "BLAH", "", "OK", "HAH"}
    
    		if SHOW {
    			println("Original")
    			prn(s)
    		}
    
    		removed := FilterAny(
    			len(s),
    			func(idx int) {
    				s = append(s[:idx], s[idx+1:]...)
    			},
    			func(idx int) bool {
    				if l := len(s[idx]); l == 3 || l == 0 {
    					return false
    				}
    				return true
    			},
    		)
    
    		if SHOW {
    			println("Filtered")
    			prn(s)
    			println("Removed: ", removed)
    		}
    
    		buf := make(gosl.Buf, 0, 128)
    		buf = buf.WriteStrings(s, ',')
    
    		gosl.Test(t, 4, removed)
    		gosl.Test(t, "IS,HERE,HAHAHA,BLAH,OK", buf.String())
    	})
    }
    
    Feature - New Accepted Coded 
    opened by gonyyi 1
  • ElmKey

    ElmKey

    Maybe rename whole Elem to Elm?? Think about naming...

    // ElemByKey takes string and search for the key, and return the value.
    // Eg. ElemByKey(`id=123,name=Gon,age=40`, "age", '=', ',') --> "40"
    func ElemByKey(s string, key string, sep, delim rune) string {
    	// Get first delim
    	cur := 0
    	foundKey := false
    	lastIdx := len(s) - 1
    	var prevC rune
    	for idx, c := range s {
    		if foundKey {
    			if idx == lastIdx {
    				return s[cur : idx+1] // when [1,2], to select 1,2, s[1:3]; need [:n+1].. therefore
    			}
    			if c == delim {
    				return s[cur:idx]
    			}
    			continue
    		}
    		if c == sep || c == delim {
    			if c == sep && s[cur:idx] == key { // sep separates key and value, `abc=123, def=456` --> "="
    				foundKey = true
    			}
    			// delimiter splits diff fields, `abc=123, def=456` --> ","
    			cur = idx
    			if idx != lastIdx {
    				cur += 1
    			}
    			prevC = c
    			continue
    		}
    
    		if prevC == delim {
    			if c == ' ' {
    				continue
    			}
    			cur = idx
    		}
    		prevC = c
    	}
    	return ""
    }
    

    TEST

    	t.Run("ElemByKey", func(t *testing.T) {
    		s := `id=123, name=Gon, age=40,name2=Jon,blank=,age2=100`
    		gosl.Test(t, "123", gosl.ElemByKey(s, "id", '=', ','))
    		gosl.Test(t, "Gon", gosl.ElemByKey(s, "name", '=', ','))
    		gosl.Test(t, "40", gosl.ElemByKey(s, "age", '=', ','))
    		gosl.Test(t, "Jon", gosl.ElemByKey(s, "name2", '=', ','))
    		gosl.Test(t, "100", gosl.ElemByKey(s, "age2", '=', ','))
    		gosl.Test(t, "", gosl.ElemByKey(s, "blank", '=', ','))
    	})
    

    BENCH

    func Benchmark_String_ElemByKey(b *testing.B) {
    	b.Run("ElemByKey", func(b *testing.B) {
    		b.ReportAllocs()
    		s := `id=123, name=Gon, age=40, someLong=,name2=Jon,age2=100`
    		var out string
    		for i := 0; i < b.N; i++ {
    			out = gosl.ElemByKey(s, "age", '=', ',')
    		}
    		_ = out
    		//println(out)
    	})
    }
    
    Feature - New Coded 
    opened by gonyyi 0
  • Bytes to Integer

    Bytes to Integer

    func IntAsBytes(i int64) [8]byte {
    	// Little endian
    	return [8]byte{
    		byte(0xff & i),
    		byte(0xff & (i >> 8)),
    		byte(0xff & (i >> 16)),
    		byte(0xff & (i >> 24)),
    		byte(0xff & (i >> 32)),
    		byte(0xff & (i >> 40)),
    		byte(0xff & (i >> 48)),
    		byte(0xff & (i >> 56)),
    	}
    }
    func BytesAsInt(b [8]byte) (out int64) {
    	// Little endian
    	return int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 |
    		int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
    }
    
    Feature - New Coded 
    opened by gonyyi 0
  • Clean up those aren't absolutely needed.

    Clean up those aren't absolutely needed.

    This became too big. Time to clean up.

    1. mutex.go + pool.go --> sync.go (8f222eebbc129dc464cb808cff1c2c7872e9d043)
    2. Any func in string.go to have String prefix ? a. Itoa, Atoi, MustAtoi ?
    3. logger.go + write.go --> logger.go (8f222eebbc129dc464cb808cff1c2c7872e9d043)

    Goal

    1. For a function, copy and paste a single file should work -- eg. any uses byte function should be within byte file.
    2. Combine buf.go -> bytes.go.

    Tasks

    • [x] All the test files should be in /test folder
    • [ ] Remove Global Buffers, and combine buf.go -> bytes.go
    • [x] Remove the Logger{}, and create LineWriter{} instead.
    • [ ] Maybe instead of Split(), write something that can be generalized??? Hmm..
      names := "Gon,Jon,Don"
      
      gosl.StringSplit(
          names,
          ',', // rune comma 
          func( idx, beg, end ){ 
              if idx == 2 {
                  println(names[beg:end])  // should be Don
              }
          })
      
    Documentation Accepted Feature - Modify 
    opened by gonyyi 0
Releases(v0.7.9)
Owner
Gon
where's the headache coming from? naming and documenting things.
Gon
A small & fast dependency-free library for parsing micro expressions.

MicroExpr A small & fast dependency-free library for parsing micro expressions. This library was originally built for use in templating languages (e.g

Daniel G. Taylor 10 Nov 25, 2022
Go Small Library

Go Small Library (gosl) Copyright Gon Y. Yi 2021 Goal General No import of any library whatsoever including standard libr

Gon 0 Jan 12, 2022
A collection of small Go utilities to make life easier.

The simplego package provides a collection of Go utilities for common tasks.

John Wang 41 Jan 4, 2023
Small utility to allow simpler, quicker testing of parsing files in crowdsec

cs_parser_test Small utility to allow simpler, quicker testing of parsing files in crowdsec Usage $ sudo cs_parser_test -t syslog /var/log/mail.log N

david reid 3 Jul 13, 2021
A small utility to extract your Telegram contacts as VCF file.

Telegram to VCF A small utility to extract your Telegram contacts as VCF file. Usage At first build this application or use the precompiled binaries o

Hirbod Behnam 4 Nov 16, 2022
This is a small utility that finds unused exported Go symbols (functions, methods ...) in Go

This is a small utility that finds unused exported Go symbols (functions, methods ...) in Go. For all other similar use cases

Bjørn Erik Pedersen 22 Nov 8, 2022
Small utility to cleanup entries with unexpected/erroneous ttl in redis

Small utility to cleanup entries with unexpected/erroneous ttl in redis

Selva 0 Apr 28, 2022
An API that provides a small but well-thought service converting Euro to US Dollar and vice-versa

Currency Converter ###Problem An API that provides a small but well-thought service converting Euro to US Dollar and vice-versa. That API should only

Akshay Nambiar 0 Jan 30, 2022
Small tool for splitting files found in a path into multiple groups

Small tool for splitting files found in a path into multiple groups. Usefull for parallelisation of whatever can be paralleled with multiple files.

Antonio Martinović 0 Jan 30, 2022
Govalid is a data validation library that can validate most data types supported by golang

Govalid is a data validation library that can validate most data types supported by golang. Custom validators can be used where the supplied ones are not enough.

null 61 Apr 22, 2022
Maintain a lower-bitrate copy of a music library in sync with the main copy.

msync Maintain a lower-bitrate copy of your music library, in sync with the main copy.

Chris Dzombak 18 Mar 6, 2022
Golang library to act on structure fields at runtime. Similar to Python getattr(), setattr(), hasattr() APIs.

go-attr Golang library to act on structure fields at runtime. Similar to Python getattr(), setattr(), hasattr() APIs. This package provides user frien

Shyamsunder Rathi 28 Dec 16, 2022
Go library for HTTP content type negotiation

Content-Type support library for Go This library can be used to parse the value Content-Type header (if one is present) and select an acceptable media

Elviss Strazdins 42 Jul 10, 2022
A tool and library for using structural regular expressions.

Structural Regular Expressions sregx is a package and tool for using structural regular expressions as described by Rob Pike (link).

Zachary Yedidia 41 Dec 7, 2022
A super simple Lodash like utility library with essential functions that empowers the development in Go

A simple Utility library for Go Go does not provide many essential built in functions when it comes to the data structure such as slice and map. This

Rahul Baruri 134 Jan 4, 2023
go-sysinfo is a library for collecting system information.

go-sysinfo go-sysinfo is a library for collecting system information. This includes information about the host machine and processes running on the ho

elastic 220 Dec 26, 2022
Molecule is a Go library for parsing protobufs in an efficient and zero-allocation manner

Molecule Molecule is a Go library for parsing protobufs in an efficient and zero-allocation manner. The API is loosely based on this excellent Go JSON

Richard Artoul 376 Jan 5, 2023
A Go (golang) library for parsing and verifying versions and version constraints.

go-version is a library for parsing versions and version constraints, and verifying versions against a set of constraints. go-version can sort a collection of versions properly, handles prerelease/beta versions, can increment versions, etc.

HashiCorp 1.3k Jan 9, 2023
A library for parsing ANSI encoded strings

Go ANSI Parser converts strings with ANSI escape codes into a slice of structs that represent styled text

Lea Anthony 37 Sep 20, 2022