Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop to Master #1

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# gutils
Another (24183746th) library related to Go utils. Common and useful units which can be consumed to another repo to ease the implementation.
Another (24183746th) library related to Go utils. Common and useful units which can be consumed to another repo to ease the implementation. Separated by sub packages from the original ones.
102 changes: 102 additions & 0 deletions bytex/bytex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Package bytex contains byte (string) processing functions.
package bytex

import (
"unicode"
"unicode/utf8"
)

// ByteContainsFold is like bytes.Contains but uses Unicode case-folding.
func ByteContainsFold(s, substr []byte) bool {
return ByteIndexFold(s, substr) >= 0
}

// EqualFoldRune compares a and b runes whether they fold equally.
// The code comes from strings.EqualFold, but shortened to only one rune.
func EqualFoldRune(sr, tr rune) bool {
if sr == tr {
return true
}

// Make sr < tr to simplify what follows.
if tr < sr {
sr, tr = tr, sr
}

// Fast check for ASCII.
if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
// ASCII, and sr is upper case. tr must be lower case.
return tr == sr+'a'-'A'
}

// General case. SimpleFold(x) returns the next equivalent rune > x
// or wraps around to smaller values.
r := unicode.SimpleFold(sr)
for r != sr && r < tr {
r = unicode.SimpleFold(r)
}

return r == tr
}

// ByteIndexFold is like bytes.Contains but uses Unicode case-folding.
func ByteIndexFold(s, substr []byte) int {
if len(substr) == 0 {
return 0
}
if len(s) == 0 {
return -1
}

firstRune := rune(substr[0])
if firstRune >= utf8.RuneSelf {
firstRune, _ = utf8.DecodeRune(substr)
}

pos := 0
for {
rune, size := utf8.DecodeRune(s)
if EqualFoldRune(rune, firstRune) && ByteHasPrefixFold(s, substr) {
return pos
}
pos += size
s = s[size:]
if len(s) == 0 {
break
}
}

return -1
}

// ByteHasPrefixFold is like strings.HasPrefix but uses Unicode case-folding.
func ByteHasPrefixFold(s, prefix []byte) bool {
if len(prefix) == 0 {
return true
}

for {
pr, prSize := utf8.DecodeRune(prefix)
prefix = prefix[prSize:]
if len(s) == 0 {
return false
}

// Step with s, too.
sr, size := utf8.DecodeRune(s)
if sr == utf8.RuneError {
return false
}

s = s[size:]
if !EqualFoldRune(sr, pr) {
return false
}

if len(prefix) == 0 {
break
}
}

return true
}
31 changes: 31 additions & 0 deletions bytex/bytex_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package bytex

import "testing"

func TestByteIndexFold(t *testing.T) {
for i, tc := range []struct {
haystack, needle string
want int
}{
{"body", "body", 0},
} {
got := ByteIndexFold([]byte(tc.haystack), []byte(tc.needle))
if got != tc.want {
t.Errorf("%d. got %d, wanted %d.", i, got, tc.want)
}
}
}

func TestByteHasPrefixFold(t *testing.T) {
for i, tc := range []struct {
haystack, needle string
want bool
}{
{"body", "body", true},
} {
got := ByteHasPrefixFold([]byte(tc.haystack), []byte(tc.needle))
if got != tc.want {
t.Errorf("%d. got %t, wanted %t.", i, got, tc.want)
}
}
}
79 changes: 79 additions & 0 deletions convertx/convertx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package convertx

import (
"encoding/binary"
"fmt"
"reflect"
"strconv"
"strings"
)

// Accessible to external packages /////////////////////////////////////////////

// Atoi ...
func Atoi(str interface{}) int {
return atoi(str)
}

// Atoui ...
func Atoui(str interface{}) uint {
return atoui(str)
}

// ToInt64 should convert given value to int64.
func ToInt64(v interface{}) (d int64, err error) {
return toInt64(v)
}

// BytesToInt64 should convert bytes to int64.
func BytesToInt64(buf []byte) int64 {
return bytesToInt64(buf)
}

// Int64ToBytes should convert int64 to bytes.
func Int64ToBytes(i int64) []byte {
return int64ToBytes(i)
}

// Underlying functions ////////////////////////////////////////////////////////

func atoi(str interface{}) (i int) {
if str == nil {
return 0
}
i, _ = strconv.Atoi(strings.Trim(str.(string), " "))
return
}

func atoui(str interface{}) uint {
if str == nil {
return 0
}
u, _ := strconv.Atoi(strings.Trim(str.(string), " "))
return uint(u)
}

func toInt64(v interface{}) (d int64, err error) {
val := reflect.ValueOf(v)
switch v.(type) {
case int, int8, int16, int32, int64:
d = val.Int()
case uint, uint8, uint16, uint32, uint64:
d = int64(val.Uint())
default:
err = fmt.Errorf("ToInt64 need numeric not `%T`", v)
}
return
}

func bytesToInt64(buf []byte) int64 {
return int64(binary.BigEndian.Uint64(buf))
}

func int64ToBytes(i int64) []byte {
var buf = make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
return buf
}

////////////////////////////////////////////////////////////////////////////////
Loading