diff --git a/collections/ArrayList.go b/collections/ArrayList.go index 47d942d..d804f27 100644 --- a/collections/ArrayList.go +++ b/collections/ArrayList.go @@ -6,21 +6,18 @@ import ( ) type ArrayList[T lang.Object] struct { + lang.BaseObject array []T - used int } func NewArrayList[T lang.Object]() *ArrayList[T] { - return &ArrayList[T]{ - make([]T, 16), - 0, - } + return NewArrayListByCapacity[T](16) } func NewArrayListByCapacity[T lang.Object](cap int) *ArrayList[T] { return &ArrayList[T]{ - make([]T, cap), - 0, + BaseObject: lang.NewBaseObject(), + array: make([]T, 0, cap), } } @@ -33,7 +30,7 @@ func (a ArrayList[T]) Iterator() Iterator[T] { } func (a ArrayList[T]) Size() int { - return a.used + return lang.Len(a.array) } func (a ArrayList[T]) IsEmpty() bool { @@ -49,20 +46,14 @@ func (a ArrayList[T]) ContainsAll(c Collection[T]) bool { } func (a *ArrayList[T]) Add(element T) bool { - if a.used >= len(a.array) { - oldArray := a.array - a.array = make([]T, a.used*2) - copy(a.array, oldArray) - } - a.array[a.used] = element - a.used++ + a.array = lang.Append(a.array, element) return true } func (a ArrayList[T]) IndexOf(element T) int { - for i := 0; i < a.used; i++ { + for i := 0; i < a.Size(); i++ { if lang.Equals(element, a.array[i]) { - return int(i) + return i } } return -1 @@ -73,7 +64,7 @@ func (a *ArrayList[T]) Remove(element T) exceptions.Exception { if index < 0 { return exceptions.NewElementNotFoundException("", nil) } else { - return a.RemoveAt(int(index)) + return a.RemoveAt(index) } } @@ -90,11 +81,11 @@ func (a *ArrayList[T]) RetainAll(c Collection[T]) bool { } func (a *ArrayList[T]) Clear() { - a.used = 0 + a.array = []T{} } func (a ArrayList[T]) Get(index int) (T, exceptions.Exception) { - if index >= a.used { + if index >= a.Size() { return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil) } else { return a.array[index], nil @@ -106,7 +97,7 @@ func (a ArrayList[T]) SubList(from, to int) List[T] { } func (a *ArrayList[T]) Set(index int, element T) exceptions.Exception { - if index >= a.used { + if index >= a.Size() { return exceptions.NewIndexOutOfBound("", nil) } a.array[index] = element @@ -114,47 +105,45 @@ func (a *ArrayList[T]) Set(index int, element T) exceptions.Exception { } func (a *ArrayList[T]) AddAtIndex(index int, element T) bool { - if !a.Add(element) { + if index >= a.Size() { return false } array := a.array - for i := a.used - 1; i > index; i++ { - array[i] = array[i-1] - } - array[index] = element - a.used++ + a.array = lang.Append[T](array[:index], element) + a.array = lang.Append[T](a.array, array[index:]...) return true } func (a *ArrayList[T]) RemoveAt(index int) exceptions.Exception { - if index >= a.used { + if index >= a.Size() { return exceptions.NewIndexOutOfBound("", nil) } - array := a.array - for i := index + 1; i < a.used; i++ { - array[i-1] = array[i] - } - a.used-- + a.array = lang.Append[T](a.array[:index], a.array[index+1:]...) return nil } func (a *ArrayList[T]) SubMutableList(from, to int) MutableList[T] { - panic("implement me") + return NewMutableSubList[T](a, from, to) } func (a *ArrayList[T]) MutableIterator() MutableIterator[T] { return &arrayListIterator[T]{a, 0} } +func (a *ArrayList[T]) RemoveLast() (T, exceptions.Exception) { + v, _ := a.Get(a.Size() - 1) + return v, a.RemoveAt(a.Size() - 1) +} + type arrayListIterator[T lang.Object] struct { arrayList *ArrayList[T] index int } func (a *arrayListIterator[T]) HasNext() bool { - return a.index < a.arrayList.used + return a.index < a.arrayList.Size() } func (a *arrayListIterator[T]) Next() (T, exceptions.Exception) { diff --git a/collections/ArrayList_test.go b/collections/ArrayList_test.go new file mode 100644 index 0000000..2b5e223 --- /dev/null +++ b/collections/ArrayList_test.go @@ -0,0 +1,58 @@ +package collections + +import ( + "fmt" + "github.com/tursom/GoCollections/exceptions" + "github.com/tursom/GoCollections/lang" + "testing" +) + +func TestArrayListAdd(t *testing.T) { + list := NewArrayList[lang.Int]() + for i := 0; i < 10; i++ { + list.Add(lang.Int(i)) + fmt.Println(list) + } + for i := 0; i < 10; i++ { + list.RemoveLast() + fmt.Println(list) + } +} + +func TestLinkedList(t *testing.T) { + list := NewLinkedList[lang.Int]() + for i := 0; i < 10; i++ { + list.Add(lang.Int(i)) + fmt.Println(list) + for j := 0; j <= i; j++ { + //exceptions.Exec2r0[ + // func(func() (error, error, error)) (error, error), + // func() (error, error, error), + // error, + //]( + exceptions.Exec2r0( + //exceptions.Exec1r1, + //exceptions.Exec0r2, + exceptions.Exec1r1[func() (error, error, error), error, error], + exceptions.Exec0r2[error, error, error], + func() (error, error, error) { + return nil, nil, nil + }, + ) + fmt.Println(exceptions.Exec2r1((*LinkedList[lang.Int]).Get, list, j).AsInt()) + } + } + for i := 0; i < 10; i++ { + list.RemoveLast() + fmt.Println(list) + } +} + +func TestEqualsFunc(t *testing.T) { + f := func() {} + fmt.Println(equals(f, f)) +} + +func equals(v1, v2 any) bool { + return v1 == v2 +} diff --git a/collections/Collection.go b/collections/Collection.go index 98d94a7..eec87b4 100644 --- a/collections/Collection.go +++ b/collections/Collection.go @@ -68,6 +68,14 @@ type ( } ) +func ListGet[T lang.Object](list List[T], index int) T { + get, err := list.Get(index) + if err != nil { + panic(err) + } + return get +} + func ContainsAll[T lang.Object](l Collection[T], collection Collection[T]) bool { return Loop[T](collection, func(e T) exceptions.Exception { if l.Contains(e) { diff --git a/collections/ConcurrentLinkedQueue.go b/collections/ConcurrentLinkedQueue.go index 900d5df..b32ee3f 100644 --- a/collections/ConcurrentLinkedQueue.go +++ b/collections/ConcurrentLinkedQueue.go @@ -8,10 +8,11 @@ import ( ) type ConcurrentLinkedQueue[T lang.Object] struct { + lang.BaseObject head *concurrentLinkedQueueNode[T] } -func (c ConcurrentLinkedQueue[T]) String() string { +func (c *ConcurrentLinkedQueue[T]) String() string { return String[T](c) } @@ -30,10 +31,10 @@ func NewConcurrentLinkedQueue[T lang.Object]() *ConcurrentLinkedQueue[T] { head := &concurrentLinkedQueueNode[T]{} head.prev = head head.next = head - return &ConcurrentLinkedQueue[T]{head} + return &ConcurrentLinkedQueue[T]{lang.NewBaseObject(), head} } -func (c ConcurrentLinkedQueue[T]) Iterator() Iterator[T] { +func (c *ConcurrentLinkedQueue[T]) Iterator() Iterator[T] { return c.MutableIterator() } diff --git a/collections/ConcurrentLinkedStack.go b/collections/ConcurrentLinkedStack.go index 8c854f4..77a8111 100644 --- a/collections/ConcurrentLinkedStack.go +++ b/collections/ConcurrentLinkedStack.go @@ -8,6 +8,7 @@ import ( ) type ConcurrentLinkedStack[T any] struct { + lang.BaseObject head *concurrentLinkedStackNode[T] p *unsafe.Pointer } @@ -28,7 +29,7 @@ type concurrentLinkedStackIterator[T any] struct { func NewConcurrentLinkedStack[T any]() *ConcurrentLinkedStack[T] { head := &concurrentLinkedStackNode[T]{} - return &ConcurrentLinkedStack[T]{head, (*unsafe.Pointer)(unsafe.Pointer(&head.next))} + return &ConcurrentLinkedStack[T]{lang.NewBaseObject(), head, (*unsafe.Pointer)(unsafe.Pointer(&head.next))} } func (c ConcurrentLinkedStack[T]) Iterator() Iterator[T] { diff --git a/collections/GoMap.go b/collections/GoMap.go new file mode 100644 index 0000000..2070c7b --- /dev/null +++ b/collections/GoMap.go @@ -0,0 +1,6 @@ +package collections + +import "github.com/tursom/GoCollections/lang" + +type GoMap[K lang.Object, V any] struct { +} diff --git a/collections/Hash.go b/collections/Hash.go new file mode 100644 index 0000000..ff07238 --- /dev/null +++ b/collections/Hash.go @@ -0,0 +1,15 @@ +package collections + +import ( + "github.com/tursom/GoCollections/exceptions" + "github.com/tursom/GoCollections/lang" +) + +func HashIterable[E lang.Object](iterable Iterable[E]) int32 { + hashCode := int32(0) + _ = Loop(iterable, func(element E) exceptions.Exception { + hashCode = hashCode*31 ^ element.HashCode() + return nil + }) + return hashCode +} diff --git a/collections/Hash_test.go b/collections/Hash_test.go new file mode 100644 index 0000000..f10e306 --- /dev/null +++ b/collections/Hash_test.go @@ -0,0 +1,15 @@ +package collections + +import ( + "fmt" + "github.com/tursom/GoCollections/lang" + "testing" +) + +func TestHashIterable(t *testing.T) { + list := NewArrayList[lang.String]() + for i := 0; i < 201; i++ { + list.Add(lang.Int(i).ToString()) + } + fmt.Println(HashIterable[lang.String](list)) +} diff --git a/collections/LinkedList.go b/collections/LinkedList.go index a3b7feb..95359f9 100644 --- a/collections/LinkedList.go +++ b/collections/LinkedList.go @@ -7,6 +7,7 @@ import ( type ( LinkedList[T lang.Object] struct { + lang.BaseObject head *linkedListNode[T] size int } @@ -14,9 +15,13 @@ type ( prev, next *linkedListNode[T] value T } + linkedListIterator[T lang.Object] struct { + list *LinkedList[T] + node, head *linkedListNode[T] + } ) -func (l LinkedList[T]) String() string { +func (l *LinkedList[T]) String() string { return String[T](l) } @@ -24,23 +29,23 @@ func NewLinkedList[T lang.Object]() *LinkedList[T] { tail := &linkedListNode[T]{} tail.prev = tail tail.next = tail - return &LinkedList[T]{tail, 0} + return &LinkedList[T]{lang.NewBaseObject(), tail, 0} } -func (l LinkedList[T]) Size() int { +func (l *LinkedList[T]) Size() int { return l.size } -func (l LinkedList[T]) IsEmpty() bool { +func (l *LinkedList[T]) IsEmpty() bool { return l.size == 0 } -func (l LinkedList[T]) Contains(element T) bool { - return Contains[T](&l, element) +func (l *LinkedList[T]) Contains(element T) bool { + return Contains[T](l, element) } -func (l LinkedList[T]) ContainsAll(c Collection[T]) bool { - return ContainsAll[T](&l, c) +func (l *LinkedList[T]) ContainsAll(c Collection[T]) bool { + return ContainsAll[T](l, c) } func (l *LinkedList[T]) Add(element T) bool { @@ -83,7 +88,7 @@ func (l *LinkedList[T]) Clear() { l.size = 0 } -func (l LinkedList[T]) SubList(from, to int) List[T] { +func (l *LinkedList[T]) SubList(from, to int) List[T] { return NewSubList[T](l, from, to) } @@ -125,24 +130,52 @@ func (l *LinkedList[T]) RemoveAt(index int) exceptions.Exception { } return exceptions.NewIndexOutOfBound("", nil) } +func (l *LinkedList[T]) RemoveLast() (T, exceptions.Exception) { + if l.head.next == l.head { + return lang.Nil[T](), exceptions.NewIndexOutOfBound("list is empty", nil) + } + return l.head.prev.remove(), nil +} func (l *LinkedList[T]) SubMutableList(from, to int) MutableList[T] { return NewMutableSubList[T](l, from, to) } -func (l LinkedList[T]) Get(index int) (T, exceptions.Exception) { - node := l.head - for node != l.head { +func (l *LinkedList[T]) Get(index int) (T, exceptions.Exception) { + if index < l.size/2 { + return loopLinkedListNodeUp[T](l.head, index) + } else { + return loopLinkedListNodeDown[T](l.head, l.size-index-1) + } +} + +func loopLinkedListNodeUp[T lang.Object](head *linkedListNode[T], index int) (T, exceptions.Exception) { + node := head.next + for node != head { if index == 0 { return node.value, nil } index-- + node = node.next } return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil) } -func (l LinkedList[T]) Iterator() Iterator[T] { +func loopLinkedListNodeDown[T lang.Object](head *linkedListNode[T], index int) (T, exceptions.Exception) { + node := head.prev + for node != head { + if index == 0 { + return node.value, nil + } + index-- + node = node.prev + } + + return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil) +} + +func (l *LinkedList[T]) Iterator() Iterator[T] { return l.MutableIterator() } @@ -150,11 +183,6 @@ func (l *LinkedList[T]) MutableIterator() MutableIterator[T] { return &linkedListIterator[T]{l, l.head.next, l.head} } -type linkedListIterator[T lang.Object] struct { - list *LinkedList[T] - node, head *linkedListNode[T] -} - func (l *linkedListIterator[T]) HasNext() bool { return l.node != l.head } @@ -176,7 +204,8 @@ func (l *linkedListIterator[T]) Remove() exceptions.Exception { return nil } -func (l *linkedListNode[T]) remove() { +func (l *linkedListNode[T]) remove() T { l.next.prev = l.prev l.prev.next = l.next + return l.value } diff --git a/collections/LockedMutableList.go b/collections/LockedMutableList.go new file mode 100644 index 0000000..56a4bc8 --- /dev/null +++ b/collections/LockedMutableList.go @@ -0,0 +1,162 @@ +package collections + +import ( + "github.com/tursom/GoCollections/concurrent" + "github.com/tursom/GoCollections/exceptions" + "github.com/tursom/GoCollections/lang" + "sync" +) + +type ( + LockedMutableList[T lang.Object] struct { + list MutableList[T] + lock concurrent.RWLock + } + lockedMutableListIterator[T lang.Object] struct { + iterator MutableIterator[T] + lock concurrent.RWLock + } +) + +func MutableListWithLock[T lang.Object](list MutableList[T]) MutableList[T] { + return &LockedMutableList[T]{ + list: list, + lock: &sync.RWMutex{}, + } +} + +func (l *LockedMutableList[T]) String() string { + return String[T](l) +} + +func (l *LockedMutableList[T]) Iterator() Iterator[T] { + return l.MutableIterator() +} + +func (l *LockedMutableList[T]) Size() int { + l.lock.RLock() + defer l.lock.RUnlock() + + return l.list.Size() +} + +func (l *LockedMutableList[T]) IsEmpty() bool { + return l.Size() == 0 +} + +func (l *LockedMutableList[T]) Contains(element T) bool { + l.lock.RLock() + defer l.lock.RUnlock() + + return l.list.Contains(element) +} + +func (l *LockedMutableList[T]) ContainsAll(c Collection[T]) bool { + l.lock.RLock() + defer l.lock.RUnlock() + + return l.list.ContainsAll(c) +} + +func (l *LockedMutableList[T]) MutableIterator() MutableIterator[T] { + return &lockedMutableListIterator[T]{l.list.MutableIterator(), l.lock} +} + +func (l *LockedMutableList[T]) Add(element T) bool { + l.lock.Lock() + defer l.lock.Unlock() + + return l.list.Add(element) +} + +func (l *LockedMutableList[T]) Remove(element T) exceptions.Exception { + l.lock.Lock() + defer l.lock.Unlock() + + return l.list.Remove(element) +} + +func (l *LockedMutableList[T]) AddAll(c Collection[T]) bool { + l.lock.Lock() + defer l.lock.Unlock() + + return l.list.AddAll(c) +} + +func (l *LockedMutableList[T]) RemoveAll(c Collection[T]) bool { + l.lock.Lock() + defer l.lock.Unlock() + + return l.list.RemoveAll(c) +} + +func (l *LockedMutableList[T]) RetainAll(c Collection[T]) bool { + l.lock.Lock() + defer l.lock.Unlock() + + return l.list.RetainAll(c) +} + +func (l *LockedMutableList[T]) Clear() { + l.lock.Lock() + defer l.lock.Unlock() + + l.list.Clear() +} + +func (l *LockedMutableList[T]) Get(index int) (T, exceptions.Exception) { + l.lock.RLock() + defer l.lock.RUnlock() + + return l.list.Get(index) +} + +func (l *LockedMutableList[T]) SubList(from, to int) List[T] { + return l.SubMutableList(from, to) +} + +func (l *LockedMutableList[T]) Set(index int, element T) exceptions.Exception { + l.lock.Lock() + defer l.lock.Unlock() + + return l.list.Set(index, element) +} + +func (l *LockedMutableList[T]) AddAtIndex(index int, element T) bool { + l.lock.Lock() + defer l.lock.Unlock() + + return l.list.AddAtIndex(index, element) +} + +func (l *LockedMutableList[T]) RemoveAt(index int) exceptions.Exception { + l.lock.Lock() + defer l.lock.Unlock() + + return l.list.RemoveAt(index) +} + +func (l *LockedMutableList[T]) SubMutableList(from, to int) MutableList[T] { + return &LockedMutableList[T]{l.list.SubMutableList(from, to), l.lock} +} + +func (l *lockedMutableListIterator[T]) HasNext() bool { + l.lock.RLock() + defer l.lock.RUnlock() + + return l.iterator.HasNext() +} + +func (l *lockedMutableListIterator[T]) Next() (T, exceptions.Exception) { + l.lock.RLock() + defer l.lock.RUnlock() + + return l.iterator.Next() +} + +func (l *lockedMutableListIterator[T]) Remove() exceptions.Exception { + l.lock.Lock() + defer l.lock.Unlock() + + return l.iterator.Remove() +} diff --git a/collections/Map.go b/collections/Map.go new file mode 100644 index 0000000..64fdac3 --- /dev/null +++ b/collections/Map.go @@ -0,0 +1,11 @@ +package collections + +import ( + "github.com/tursom/GoCollections/exceptions" + "github.com/tursom/GoCollections/lang" +) + +type Map[K lang.Object, V any] interface { + Put(k K, v V) (bool, exceptions.Exception) + Get(k K) (V, exceptions.Exception) +} diff --git a/collections/MutableSubList.go b/collections/MutableSubList.go index c76cafb..942e06e 100644 --- a/collections/MutableSubList.go +++ b/collections/MutableSubList.go @@ -6,12 +6,13 @@ import ( ) type MutableSubList[T lang.Object] struct { + lang.BaseObject list MutableList[T] from, to int } -func NewMutableSubList[T lang.Object](list MutableList[T], from, to int) MutableList[T] { - return &MutableSubList[T]{list, from, to} +func NewMutableSubList[T lang.Object](list MutableList[T], from, to int) *MutableSubList[T] { + return &MutableSubList[T]{lang.NewBaseObject(), list, from, to} } func (s *MutableSubList[T]) Iterator() Iterator[T] { diff --git a/collections/SubList.go b/collections/SubList.go index 7e22e3f..b82c2d8 100644 --- a/collections/SubList.go +++ b/collections/SubList.go @@ -6,12 +6,13 @@ import ( ) type SubList[T lang.Object] struct { + lang.BaseObject list List[T] from, to int } -func NewSubList[T lang.Object](list List[T], from, to int) List[T] { - return &SubList[T]{list, from, to} +func NewSubList[T lang.Object](list List[T], from, to int) *SubList[T] { + return &SubList[T]{lang.NewBaseObject(), list, from, to} } func (s *SubList[T]) Iterator() Iterator[T] { diff --git a/concurrent/Lock.go b/concurrent/Lock.go new file mode 100644 index 0000000..b2df61b --- /dev/null +++ b/concurrent/Lock.go @@ -0,0 +1,14 @@ +package concurrent + +type ( + Lock interface { + Lock() + Unlock() + } + RWLock interface { + Lock() + Unlock() + RLock() + RUnlock() + } +) diff --git a/concurrent/ReentrantLock.go b/concurrent/ReentrantLock.go new file mode 100644 index 0000000..38d9fcf --- /dev/null +++ b/concurrent/ReentrantLock.go @@ -0,0 +1,26 @@ +package concurrent + +import "sync" + +type ReentrantLock struct { + sync.Mutex + cnt int32 +} + +func (l *ReentrantLock) Lock() { + defer func() { + r := recover() + if r != nil { + l.cnt++ + } + }() + + l.Mutex.Lock() +} + +func (l *ReentrantLock) Unlock() { + l.cnt-- + if l.cnt == 0 { + l.Mutex.Unlock() + } +} diff --git a/concurrent/ReentrantLock_test.go b/concurrent/ReentrantLock_test.go new file mode 100644 index 0000000..a129b2b --- /dev/null +++ b/concurrent/ReentrantLock_test.go @@ -0,0 +1,11 @@ +package concurrent + +import ( + "testing" +) + +func TestMutex(t *testing.T) { + mutex := &ReentrantLock{} + mutex.Lock() + mutex.Lock() +} diff --git a/exceptions/ElementNotFound.go b/exceptions/ElementNotFound.go index f3f4da6..01326b8 100644 --- a/exceptions/ElementNotFound.go +++ b/exceptions/ElementNotFound.go @@ -4,7 +4,7 @@ type ElementNotFoundException struct { RuntimeException } -func NewElementNotFoundException(message interface{}, config *ExceptionConfig) *ElementNotFoundException { +func NewElementNotFoundException(message any, config *ExceptionConfig) *ElementNotFoundException { config.AddSkipStack(1) return &ElementNotFoundException{ NewRuntimeException( diff --git a/exceptions/Exception.go b/exceptions/Exception.go index 657b1dc..01037e4 100644 --- a/exceptions/Exception.go +++ b/exceptions/Exception.go @@ -57,7 +57,7 @@ func BuildStackTrace(builder *strings.Builder, e Exception, exceptionMsg string) func Try[R any]( f func() (ret R, err Exception), - catch func(panic interface{}) (ret R, err Exception), + catch func(panic any) (ret R, err Exception), ) (ret R, err Exception) { defer func() { if r := recover(); r != nil { @@ -95,7 +95,7 @@ func Package(err error) Exception { return NewRuntimeException(err, "", DefaultExceptionConfig().SetCause(err)) } -func PackageAny(err interface{}) Exception { +func PackageAny(err any) Exception { if err == nil { return nil } @@ -107,7 +107,7 @@ func PackageAny(err interface{}) Exception { } } -func PackagePanic(panic interface{}, exceptionMessage string) Exception { +func PackagePanic(panic any, exceptionMessage string) Exception { if panic == nil { return nil } diff --git a/exceptions/ExceptionConfig.go b/exceptions/ExceptionConfig.go index 3592a77..b1d7b1a 100644 --- a/exceptions/ExceptionConfig.go +++ b/exceptions/ExceptionConfig.go @@ -3,7 +3,7 @@ package exceptions type ExceptionConfig struct { SkipStack int GetStackTrace bool - Cause interface{} + Cause any } func DefaultExceptionConfig() *ExceptionConfig { @@ -30,7 +30,7 @@ func (c *ExceptionConfig) SetGetStackTrace(getStackTrace bool) *ExceptionConfig return c } -func (c *ExceptionConfig) SetCause(cause interface{}) *ExceptionConfig { +func (c *ExceptionConfig) SetCause(cause any) *ExceptionConfig { if c == nil { return DefaultExceptionConfig().SetCause(cause) } diff --git a/exceptions/Exec.go b/exceptions/Exec.go new file mode 100644 index 0000000..be08cab --- /dev/null +++ b/exceptions/Exec.go @@ -0,0 +1,93 @@ +package exceptions + +func Exec0r0[E error](f func() E) { + err := f() + if error(err) != nil { + panic(Package(err)) + } +} + +func Exec0r1[R1 any, E error](f func() (R1, E)) R1 { + r, err := f() + if error(err) != nil { + panic(Package(err)) + } + return r +} + +func Exec0r2[R1, R2 any, E error](f func() (R1, R2, E)) (R1, R2) { + r1, r2, err := f() + if error(err) != nil { + panic(Package(err)) + } + return r1, r2 +} + +func Exec1r0[A1 any, E error](f func(A1) E, a1 A1) { + err := f(a1) + if error(err) != nil { + panic(Package(err)) + } +} + +func Exec1r1[A1, R1 any, E error](f func(A1) (R1, E), a1 A1) R1 { + r, err := f(a1) + if error(err) != nil { + panic(Package(err)) + } + return r +} + +func Exec1r2[A1, R1, R2 any, E error](f func(A1) (R1, R2, E), a1 A1) (R1, R2) { + r1, r2, err := f(a1) + if error(err) != nil { + panic(Package(err)) + } + return r1, r2 +} + +func Exec2r0[A1, A2 any, E error](f func(A1, A2) E, a1 A1, a2 A2) { + err := f(a1, a2) + if error(err) != nil { + panic(Package(err)) + } +} + +func Exec2r1[A1, A2, R1 any, E error](f func(A1, A2) (R1, E), a1 A1, a2 A2) R1 { + r, err := f(a1, a2) + if error(err) != nil { + panic(Package(err)) + } + return r +} + +func Exec2r2[A1, A2, R1, R2 any, E error](f func(A1, A2) (R1, R2, E), a1 A1, a2 A2) (R1, R2) { + r1, r2, err := f(a1, a2) + if error(err) != nil { + panic(Package(err)) + } + return r1, r2 +} + +func Exec3r0[A1, A2, A3 any, E error](f func(A1, A2, A3) E, a1 A1, a2 A2, a3 A3) { + err := f(a1, a2, a3) + if error(err) != nil { + panic(Package(err)) + } +} + +func Exec3r1[A1, A2, A3, R1 any, E error](f func(A1, A2, A3) (R1, E), a1 A1, a2 A2, a3 A3) R1 { + r, err := f(a1, a2, a3) + if error(err) != nil { + panic(Package(err)) + } + return r +} + +func Exec3r2[A1, A2, A3, R1, R2 any, E error](f func(A1, A2, A3) (R1, R2, E), a1 A1, a2 A2, a3 A3) (R1, R2) { + r1, r2, err := f(a1, a2, a3) + if error(err) != nil { + panic(Package(err)) + } + return r1, r2 +} diff --git a/exceptions/IndexOutOfBoundError.go b/exceptions/IndexOutOfBoundError.go index 678e5fa..fea398c 100644 --- a/exceptions/IndexOutOfBoundError.go +++ b/exceptions/IndexOutOfBoundError.go @@ -4,7 +4,7 @@ type IndexOutOfBound struct { RuntimeException } -func NewIndexOutOfBound(message interface{}, config *ExceptionConfig) *IndexOutOfBound { +func NewIndexOutOfBound(message any, config *ExceptionConfig) *IndexOutOfBound { config.AddSkipStack(1) return &IndexOutOfBound{ NewRuntimeException( diff --git a/exceptions/NPE.go b/exceptions/NPE.go index 7683e70..8a3274a 100644 --- a/exceptions/NPE.go +++ b/exceptions/NPE.go @@ -4,7 +4,7 @@ type NPE struct { RuntimeException } -func NewNPE(message interface{}, config *ExceptionConfig) *NPE { +func NewNPE(message any, config *ExceptionConfig) *NPE { config.AddSkipStack(1) return &NPE{ NewRuntimeException( diff --git a/exceptions/OperationNotSupportedException.go b/exceptions/OperationNotSupportedException.go index d84b662..91c3284 100644 --- a/exceptions/OperationNotSupportedException.go +++ b/exceptions/OperationNotSupportedException.go @@ -4,7 +4,7 @@ type OperationNotSupportedException struct { RuntimeException } -func NewOperationNotSupportedException(message interface{}, config *ExceptionConfig) *OperationNotSupportedException { +func NewOperationNotSupportedException(message any, config *ExceptionConfig) *OperationNotSupportedException { config.AddSkipStack(1) return &OperationNotSupportedException{ NewRuntimeException( diff --git a/exceptions/PackageException.go b/exceptions/PackageException.go index 43b7cb8..d2341e9 100644 --- a/exceptions/PackageException.go +++ b/exceptions/PackageException.go @@ -2,10 +2,10 @@ package exceptions type PackageException struct { RuntimeException - err interface{} + err any } -func NewPackageException(err interface{}, exceptionMessage string, config *ExceptionConfig) *PackageException { +func NewPackageException(err any, exceptionMessage string, config *ExceptionConfig) *PackageException { config.AddSkipStack(1) return &PackageException{ RuntimeException: NewRuntimeException(err, exceptionMessage, config), @@ -13,11 +13,11 @@ func NewPackageException(err interface{}, exceptionMessage string, config *Excep } } -func (p *PackageException) Err() interface{} { +func (p *PackageException) Err() any { return p.err } -func UnpackException(err interface{}) interface{} { +func UnpackException(err any) any { for err != nil { switch err.(type) { case *PackageException: diff --git a/exceptions/RuntimeException.go b/exceptions/RuntimeException.go index 58e29b8..c2ec1ac 100644 --- a/exceptions/RuntimeException.go +++ b/exceptions/RuntimeException.go @@ -2,19 +2,21 @@ package exceptions import ( "fmt" + "github.com/tursom/GoCollections/lang" "io" "os" "strings" ) type RuntimeException struct { + lang.BaseObject message string exceptionMessage string stackTrace []StackTrace cause Exception } -func NewRuntimeException(message interface{}, exceptionMessage string, config *ExceptionConfig) RuntimeException { +func NewRuntimeException(message any, exceptionMessage string, config *ExceptionConfig) RuntimeException { if config == nil { config = DefaultExceptionConfig() } @@ -40,6 +42,7 @@ func NewRuntimeException(message interface{}, exceptionMessage string, config *E } return RuntimeException{ + BaseObject: lang.NewBaseObject(), message: fmt.Sprint(message), exceptionMessage: exceptionMessage, stackTrace: stackTrace, diff --git a/lang/Complex128.go b/lang/Complex128.go new file mode 100644 index 0000000..b08e763 --- /dev/null +++ b/lang/Complex128.go @@ -0,0 +1,35 @@ +package lang + +import ( + "fmt" +) + +type Complex128 complex128 + +func (i Complex128) AsComplex128() complex128 { + return complex128(i) +} + +func (i Complex128) String() string { + return fmt.Sprint(complex64(i)) +} + +func (i Complex128) AsObject() Object { + return i +} + +func (i Complex128) Equals(e Object) bool { + i2, ok := e.(Complex128) + if !ok { + return false + } + return i == i2 +} + +func (i Complex128) ToString() String { + return NewString(i.String()) +} + +func (i Complex128) HashCode() int32 { + return Float64(real(complex64(i))).HashCode() ^ Float64(imag(complex64(i))).HashCode() +} diff --git a/lang/Complex64.go b/lang/Complex64.go new file mode 100644 index 0000000..2b1dc12 --- /dev/null +++ b/lang/Complex64.go @@ -0,0 +1,35 @@ +package lang + +import ( + "fmt" +) + +type Complex64 complex64 + +func (i Complex64) AsComplex64() complex64 { + return complex64(i) +} + +func (i Complex64) String() string { + return fmt.Sprint(complex64(i)) +} + +func (i Complex64) AsObject() Object { + return i +} + +func (i Complex64) Equals(e Object) bool { + i2, ok := e.(Complex64) + if !ok { + return false + } + return i == i2 +} + +func (i Complex64) ToString() String { + return NewString(i.String()) +} + +func (i Complex64) HashCode() int32 { + return Float32(real(complex64(i))).HashCode() ^ Float32(imag(complex64(i))).HashCode() +} diff --git a/lang/Float32.go b/lang/Float32.go new file mode 100644 index 0000000..e5026a5 --- /dev/null +++ b/lang/Float32.go @@ -0,0 +1,46 @@ +package lang + +import ( + "fmt" +) + +type Float32 float32 + +func (i Float32) AsFloat32() float32 { + return float32(i) +} + +func (i Float32) String() string { + return fmt.Sprint(float32(i)) +} + +func (i Float32) AsObject() Object { + return i +} + +func (i Float32) Equals(e Object) bool { + i2, ok := e.(Float32) + if !ok { + return false + } + return i == i2 +} + +func (i Float32) ToString() String { + return NewString(i.String()) +} + +func (i Float32) HashCode() int32 { + return Hash32(&i) +} + +func (i Float32) Compare(t Float32) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/Float64.go b/lang/Float64.go new file mode 100644 index 0000000..da2cf25 --- /dev/null +++ b/lang/Float64.go @@ -0,0 +1,46 @@ +package lang + +import ( + "fmt" +) + +type Float64 float64 + +func (i Float64) AsFloat64() float64 { + return float64(i) +} + +func (i Float64) String() string { + return fmt.Sprint(float64(i)) +} + +func (i Float64) AsObject() Object { + return i +} + +func (i Float64) Equals(e Object) bool { + i2, ok := e.(Float64) + if !ok { + return false + } + return i == i2 +} + +func (i Float64) ToString() String { + return NewString(i.String()) +} + +func (i Float64) HashCode() int32 { + return Hash64(&i) +} + +func (i Float64) Compare(t Float64) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/Hash.go b/lang/Hash.go new file mode 100644 index 0000000..fae60e7 --- /dev/null +++ b/lang/Hash.go @@ -0,0 +1,41 @@ +package lang + +import ( + "unsafe" +) + +//goland:noinspection GoVetUnsafePointer +func HashAddr[V any](v *V) int32 { + p := uintptr(unsafe.Pointer(v)) + remain := int32(unsafe.Sizeof(*v)) + hash := int32(0) + for remain-4 >= 0 { + remain -= 4 + hash = hash*31 ^ *(*int32)(unsafe.Pointer(p)) + p += 4 + } + for remain > 0 { + hash = hash*31 ^ int32(*(*int8)(unsafe.Pointer(p))) + p++ + remain-- + } + + return hash +} + +func Hash32[T any](p *T) int32 { + return *(*int32)(unsafe.Pointer(p)) +} + +func Hash64[T any](p *T) int32 { + i := *(*int64)(unsafe.Pointer(p)) + return int32(i)*31 ^ int32(i>>32) +} + +func HashString(str string) int32 { + hashCode := int32(0) + for _, r := range str { + hashCode = 31*hashCode + r + } + return hashCode +} diff --git a/lang/Hash_test.go b/lang/Hash_test.go new file mode 100644 index 0000000..fbaa54f --- /dev/null +++ b/lang/Hash_test.go @@ -0,0 +1,15 @@ +package lang + +import ( + "fmt" + "testing" +) + +func TestHashAddr(t *testing.T) { + str := "test" + fmt.Println(HashAddr(&str)) +} + +func TestHashString(t *testing.T) { + fmt.Println(HashString("testwerwefdcsd")) +} diff --git a/lang/Int.go b/lang/Int.go index 9d1728f..36ca3ab 100644 --- a/lang/Int.go +++ b/lang/Int.go @@ -1,7 +1,17 @@ package lang +import "strconv" + type Int int +func (i Int) AsInt() int { + return int(i) +} + +func (i Int) String() string { + return strconv.Itoa(int(i)) +} + func (i Int) Equals(e Object) bool { i2, ok := e.(Int) if !ok { @@ -10,6 +20,25 @@ func (i Int) Equals(e Object) bool { return i == i2 } -func (i Int) Compare(t Int) int { - return int(t - i) +func (i Int) AsObject() Object { + return i +} + +func (i Int) ToString() String { + return NewString(i.String()) +} + +func (i Int) HashCode() int32 { + return Int64(i).HashCode() +} + +func (i Int) Compare(t Int) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } } diff --git a/lang/Int16.go b/lang/Int16.go new file mode 100644 index 0000000..22935fc --- /dev/null +++ b/lang/Int16.go @@ -0,0 +1,44 @@ +package lang + +import "strconv" + +type Int16 int16 + +func (i Int16) AsInt16() int16 { + return int16(i) +} + +func (i Int16) String() string { + return strconv.FormatInt(int64(i), 10) +} + +func (i Int16) AsObject() Object { + return i +} + +func (i Int16) Equals(e Object) bool { + i2, ok := e.(Int16) + if !ok { + return false + } + return i == i2 +} + +func (i Int16) ToString() String { + return NewString(i.String()) +} + +func (i Int16) HashCode() int32 { + return int32(i) +} + +func (i Int16) Compare(t Int16) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/Int32.go b/lang/Int32.go new file mode 100644 index 0000000..24f00e5 --- /dev/null +++ b/lang/Int32.go @@ -0,0 +1,46 @@ +package lang + +import "strconv" + +type Int32 int32 + +type Rune = Int32 + +func (i Int32) AsInt32() int32 { + return int32(i) +} + +func (i Int32) String() string { + return strconv.FormatInt(int64(i), 10) +} + +func (i Int32) AsObject() Object { + return i +} + +func (i Int32) Equals(e Object) bool { + i2, ok := e.(Int32) + if !ok { + return false + } + return i == i2 +} + +func (i Int32) ToString() String { + return NewString(i.String()) +} + +func (i Int32) HashCode() int32 { + return int32(i) +} + +func (i Int32) Compare(t Int32) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/Int64.go b/lang/Int64.go new file mode 100644 index 0000000..2a48d9b --- /dev/null +++ b/lang/Int64.go @@ -0,0 +1,44 @@ +package lang + +import "strconv" + +type Int64 int64 + +func (i Int64) AsInt64() int64 { + return int64(i) +} + +func (i Int64) String() string { + return strconv.FormatInt(int64(i), 10) +} + +func (i Int64) AsObject() Object { + return i +} + +func (i Int64) Equals(e Object) bool { + i2, ok := e.(Int64) + if !ok { + return false + } + return i == i2 +} + +func (i Int64) ToString() String { + return NewString(i.String()) +} + +func (i Int64) HashCode() int32 { + return Hash64(&i) +} + +func (i Int64) Compare(t Int64) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/Int8.go b/lang/Int8.go new file mode 100644 index 0000000..4d85df4 --- /dev/null +++ b/lang/Int8.go @@ -0,0 +1,44 @@ +package lang + +import "strconv" + +type Int8 int8 + +func (i Int8) AsInt8() int8 { + return int8(i) +} + +func (i Int8) String() string { + return strconv.FormatInt(int64(i), 10) +} + +func (i Int8) AsObject() Object { + return i +} + +func (i Int8) Equals(e Object) bool { + i2, ok := e.(Int8) + if !ok { + return false + } + return i == i2 +} + +func (i Int8) ToString() String { + return NewString(i.String()) +} + +func (i Int8) HashCode() int32 { + return int32(i) +} + +func (i Int8) Compare(t Int8) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/Int_test.go b/lang/Int_test.go new file mode 100644 index 0000000..66743c5 --- /dev/null +++ b/lang/Int_test.go @@ -0,0 +1,68 @@ +package lang + +import "testing" + +func TestInt_Compare(t *testing.T) { + type args struct { + t Int + } + tests := []struct { + name string + i Int + args args + want int + }{ + {"", 1, args{1}, 0}, + {"", 1, args{0}, -1}, + {"", 1, args{2}, 1}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.i.Compare(tt.args.t); got != tt.want { + t.Errorf("Compare() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestInt_Equals(t *testing.T) { + type args struct { + e Object + } + tests := []struct { + name string + i Int + args args + want bool + }{ + {"", 1, args{Int(1)}, true}, + {"", 1, args{Int(0)}, false}, + {"", 1, args{Int(2)}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.i.Equals(tt.args.e); got != tt.want { + t.Errorf("Equals() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestInt_String(t *testing.T) { + tests := []struct { + name string + i Int + want string + }{ + {"", 1, "1"}, + {"", 2, "2"}, + {"", 3, "3"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.i.String(); got != tt.want { + t.Errorf("String() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/lang/Lang.go b/lang/Lang.go index 67cf227..7194707 100644 --- a/lang/Lang.go +++ b/lang/Lang.go @@ -4,3 +4,11 @@ func Nil[T any]() T { var n T return n } + +func Len[T any](array []T) int { + return len(array) +} + +func Append[T any](slice []T, elems ...T) []T { + return append(slice, elems...) +} diff --git a/lang/Object.go b/lang/Object.go index b4c5501..90be351 100644 --- a/lang/Object.go +++ b/lang/Object.go @@ -1,8 +1,31 @@ package lang -type Object interface { - Equals(e Object) bool -} +import ( + "fmt" + "unsafe" +) + +type ( + AsObject interface { + AsObject() Object + } + + Equable interface { + Equals(o Object) bool + } + + Object interface { + AsObject() Object + Equals(o Object) bool + ToString() String + HashCode() int32 + } + + Any = Object + + BaseObject struct { + } +) func Equals(e Object, t Object) bool { if e == nil { @@ -10,3 +33,23 @@ func Equals(e Object, t Object) bool { } return e.Equals(t) } + +func NewBaseObject() BaseObject { + return BaseObject{} +} + +func (b *BaseObject) AsObject() Object { + return b +} + +func (b *BaseObject) Equals(o Object) bool { + return b == o +} + +func (b *BaseObject) ToString() String { + return NewString(fmt.Sprint(unsafe.Pointer(b))) +} + +func (b *BaseObject) HashCode() int32 { + return Hash64(b) +} diff --git a/lang/String.go b/lang/String.go new file mode 100644 index 0000000..bdd3daf --- /dev/null +++ b/lang/String.go @@ -0,0 +1,53 @@ +package lang + +type String struct { + string + hashCode int32 +} + +func NewString(str string) String { + return String{string: str} +} + +func (i String) AsString() string { + return i.string +} + +func (i String) String() string { + return i.string +} + +func (i String) AsObject() Object { + return i +} + +func (i String) Equals(e Object) bool { + i2, ok := e.(String) + if !ok { + return false + } + return i == i2 +} + +func (i String) ToString() String { + return i +} + +func (i String) HashCode() int32 { + if i.hashCode != 0 { + return i.hashCode + } + i.hashCode = HashString(i.string) + return i.hashCode +} + +func (i String) Compare(t String) int { + switch { + case i.string > t.string: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/String_test.go b/lang/String_test.go new file mode 100644 index 0000000..02ad49f --- /dev/null +++ b/lang/String_test.go @@ -0,0 +1,12 @@ +package lang + +import ( + "fmt" + "testing" +) + +func TestString_HashCode(t *testing.T) { + for i := 1000; i < 1100; i++ { + fmt.Println(Int(i).ToString().HashCode()) + } +} diff --git a/lang/StrongReference_test.go b/lang/StrongReference_test.go new file mode 100644 index 0000000..e62096e --- /dev/null +++ b/lang/StrongReference_test.go @@ -0,0 +1,63 @@ +package lang + +import ( + "fmt" + "github.com/tursom/GoCollections/util" + "reflect" + "testing" +) + +func TestStrongReference_ToString(t *testing.T) { + reference := util.NewStrongReference[Int](1) + fmt.Println(reference.ToString()) + fmt.Println(reference) +} + +func TestStrongReference_GetReference(t *testing.T) { + type fields struct { + reference Int + } + tests := []struct { + name string + fields fields + want Int + }{ + {"1", fields{reference: 1}, 1}, + {"2", fields{reference: 2}, 2}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := util.NewStrongReference(tt.fields.reference) + if got := r.GetReference(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetReference() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestStrongReference_SetReference(t *testing.T) { + type fields struct { + reference Int + } + type args struct { + reference Int + } + tests := []struct { + name string + fields fields + args args + want Int + }{ + {"1", fields{reference: 1}, args{2}, 2}, + {"2", fields{reference: 2}, args{3}, 3}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := util.NewStrongReference(tt.fields.reference) + r.SetReference(tt.args.reference) + if got := r.GetReference(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetReference() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/lang/UInt.go b/lang/UInt.go new file mode 100644 index 0000000..d932fe9 --- /dev/null +++ b/lang/UInt.go @@ -0,0 +1,44 @@ +package lang + +import "strconv" + +type UInt uint + +func (i UInt) AsUInt() uint { + return uint(i) +} + +func (i UInt) String() string { + return strconv.FormatUint(uint64(i), 10) +} + +func (i UInt) AsObject() Object { + return i +} + +func (i UInt) Equals(e Object) bool { + i2, ok := e.(UInt) + if !ok { + return false + } + return i == i2 +} + +func (i UInt) ToString() String { + return NewString(i.String()) +} + +func (i UInt) HashCode() int32 { + return Int64(i).HashCode() +} + +func (i UInt) Compare(t UInt) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/UInt16.go b/lang/UInt16.go new file mode 100644 index 0000000..6aba45e --- /dev/null +++ b/lang/UInt16.go @@ -0,0 +1,44 @@ +package lang + +import "strconv" + +type UInt16 uint16 + +func (i UInt16) AsUInt16() uint16 { + return uint16(i) +} + +func (i UInt16) String() string { + return strconv.FormatUint(uint64(i), 10) +} + +func (i UInt16) AsObject() Object { + return i +} + +func (i UInt16) Equals(e Object) bool { + i2, ok := e.(UInt16) + if !ok { + return false + } + return i == i2 +} + +func (i UInt16) ToString() String { + return NewString(i.String()) +} + +func (i UInt16) HashCode() int32 { + return int32(i) +} + +func (i UInt16) Compare(t UInt16) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/UInt32.go b/lang/UInt32.go new file mode 100644 index 0000000..fc0a030 --- /dev/null +++ b/lang/UInt32.go @@ -0,0 +1,44 @@ +package lang + +import "strconv" + +type UInt32 uint32 + +func (i UInt32) AsUInt32() uint32 { + return uint32(i) +} + +func (i UInt32) String() string { + return strconv.FormatUint(uint64(i), 10) +} + +func (i UInt32) AsObject() Object { + return i +} + +func (i UInt32) Equals(e Object) bool { + i2, ok := e.(UInt32) + if !ok { + return false + } + return i == i2 +} + +func (i UInt32) ToString() String { + return NewString(i.String()) +} + +func (i UInt32) HashCode() int32 { + return int32(i) +} + +func (i UInt32) Compare(t UInt32) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/UInt64.go b/lang/UInt64.go new file mode 100644 index 0000000..33f3ff1 --- /dev/null +++ b/lang/UInt64.go @@ -0,0 +1,44 @@ +package lang + +import "strconv" + +type UInt64 uint64 + +func (i UInt64) AsUInt64() uint64 { + return uint64(i) +} + +func (i UInt64) String() string { + return strconv.FormatUint(uint64(i), 10) +} + +func (i UInt64) AsObject() Object { + return i +} + +func (i UInt64) Equals(e Object) bool { + i2, ok := e.(UInt64) + if !ok { + return false + } + return i == i2 +} + +func (i UInt64) ToString() String { + return NewString(i.String()) +} + +func (i UInt64) HashCode() int32 { + return Int64(i).HashCode() +} + +func (i UInt64) Compare(t UInt64) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/UInt8.go b/lang/UInt8.go new file mode 100644 index 0000000..73f2248 --- /dev/null +++ b/lang/UInt8.go @@ -0,0 +1,46 @@ +package lang + +import "strconv" + +type UInt8 uint8 + +type Byte = UInt8 + +func (i UInt8) AsUInt8() uint8 { + return uint8(i) +} + +func (i UInt8) String() string { + return strconv.FormatUint(uint64(i), 10) +} + +func (i UInt8) AsObject() Object { + return i +} + +func (i UInt8) Equals(e Object) bool { + i2, ok := e.(UInt8) + if !ok { + return false + } + return i == i2 +} + +func (i UInt8) ToString() String { + return NewString(i.String()) +} + +func (i UInt8) HashCode() int32 { + return int32(i) +} + +func (i UInt8) Compare(t UInt8) int { + switch { + case i > t: + return 1 + case i == t: + return 0 + default: + return -1 + } +} diff --git a/lang/UInt_test.go b/lang/UInt_test.go new file mode 100644 index 0000000..97723ca --- /dev/null +++ b/lang/UInt_test.go @@ -0,0 +1,27 @@ +package lang + +import ( + "testing" +) + +func TestUInt_HashCode(t *testing.T) { + type Tests struct { + name string + i UInt + want int32 + } + var tests []Tests + for i := 0; i < 10; i++ { + // -i - 1 is ^i + // hash code of ^i equals i + tests = append(tests, Tests{"test -1", UInt(-i - 1), int32(i)}) + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.i.HashCode(); got != tt.want { + t.Errorf("HashCode() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/main.go b/main.go index d1df91d..7e057a7 100644 --- a/main.go +++ b/main.go @@ -9,11 +9,11 @@ import ( ) func main() { - _, err := exceptions.Try(func() (interface{}, exceptions.Exception) { + _, err := exceptions.Try(func() (any, exceptions.Exception) { panic("test") - }, func(r interface{}) (interface{}, exceptions.Exception) { + }, func(r any) (any, exceptions.Exception) { fmt.Println("recover from panic", r) - return nil, exceptions.NewIndexOutOfBound(fmt.Sprint(r), true) + return nil, exceptions.NewIndexOutOfBound(fmt.Sprint(r), nil) }) exceptions.Print(err) @@ -62,7 +62,7 @@ func main() { // fmt.Println(list) //} // - //_ = collections.LoopMutable(list, func(element interface{}, iterator collections.MutableIterator) (err exceptions.Exception) { + //_ = collections.LoopMutable(list, func(element any, iterator collections.MutableIterator) (err exceptions.Exception) { // if element.(int)&1 == 0 { // err = iterator.Remove() // } diff --git a/util/Reference.go b/util/Reference.go new file mode 100644 index 0000000..92fd4fb --- /dev/null +++ b/util/Reference.go @@ -0,0 +1,59 @@ +package util + +import "github.com/tursom/GoCollections/lang" + +type ( + Reference[R any] interface { + GetReference() R + } + MutableReference[R any] interface { + SetReference(reference R) + GetReference() R + } + StrongReference[R any] struct { + lang.BaseObject + reference R + } + NoReference[R any] struct { + lang.BaseObject + } +) + +func NewStrongReference[R any](reference R) *StrongReference[R] { + return &StrongReference[R]{ + reference: reference, + } +} + +func NewNoReference[R any]() *NoReference[R] { + return &NoReference[R]{} +} + +func (r *StrongReference[R]) Equals(o lang.Object) bool { + if r == o { + return true + } + if objectReference, ok := o.(Reference[R]); ok { + if reference, ok := any(r.reference).(lang.Equable); ok { + if referenceObject, ok := any(objectReference.GetReference()).(lang.Object); ok { + return reference.Equals(referenceObject) + } + } + } + return r == o +} + +func (r *StrongReference[R]) SetReference(reference R) { + r.reference = reference +} + +func (r *StrongReference[R]) GetReference() R { + return r.reference +} + +func (r *NoReference[R]) SetReference(_ R) { +} + +func (r *NoReference[R]) GetReference() R { + return lang.Nil[R]() +} diff --git a/util/Reference_test.go b/util/Reference_test.go new file mode 100644 index 0000000..cf04058 --- /dev/null +++ b/util/Reference_test.go @@ -0,0 +1,33 @@ +package util + +import ( + "github.com/tursom/GoCollections/lang" + "testing" +) + +func TestStrongReference_Equals(t *testing.T) { + type fields struct { + reference int + } + type args struct { + o lang.Object + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + {"1", fields{1}, args{NewStrongReference[int](1)}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := &StrongReference[int]{ + reference: tt.fields.reference, + } + if got := r.Equals(tt.args.o); got != tt.want { + t.Errorf("Equals() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/util/Utils.go b/util/Utils.go new file mode 100644 index 0000000..c7d8682 --- /dev/null +++ b/util/Utils.go @@ -0,0 +1 @@ +package util diff --git a/util/arrayList.go b/util/arrayList.go index abe9ba8..9c753b9 100644 --- a/util/arrayList.go +++ b/util/arrayList.go @@ -15,7 +15,7 @@ func (a *arrayList[T]) Iterator() collections.Iterator[T] { } func (a *arrayList[T]) Size() int { - return len(a.array) + return lang.Len(a.array) } func (a *arrayList[T]) IsEmpty() bool { @@ -44,7 +44,7 @@ type arrayListIterator[T lang.Object] struct { } func (a *arrayListIterator[T]) HasNext() bool { - return a.index < len(a.array) + return a.index < lang.Len(a.array) } func (a *arrayListIterator[T]) Next() (r T, err exceptions.Exception) {