times portada

packs2
DEV 3 years ago
parent 3d9cae23e7
commit 7669987b25

@ -0,0 +1,75 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package contexts
import "sync/atomic"
type (
Cancel struct {
active uint32
doneCh chan struct{}
}
)
func NewCancel() *Cancel {
return &Cancel{
active: 1,
doneCh: make(chan struct{}),
}
}
func (c *Cancel) Cancel() {
if atomic.CompareAndSwapUint32(&c.active,1,0) {
close(c.doneCh)
}
}
func (c *Cancel) Done() <-chan struct{} {
return c.doneCh }
func (c *Cancel) IsDone() bool {
return atomic.LoadUint32(&c.active) == 1 }
func (c *Cancel) Wait() {
<-c.doneCh }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -23,6 +23,14 @@
package slices
const (
NotFound = -1
)
func MakeSlice[T any](size, capacity int, creator func() T) []T {
rs := make([]T, size, capacity)
for i := 0; i < size; i++ {

@ -23,8 +23,13 @@
package slices
type String []string
func MakeString(size, capacity int) String {
return make(String, size, capacity)
}

@ -0,0 +1,108 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"sync/atomic"
"time"
)
type (
Chrono struct {
started int64
stopped int64
}
)
func NewChrono(str bool) *Chrono {
ch := &Chrono{}
if str {
ch.Start()
}
return ch
}
func (c *Chrono) Started() time.Time {
return time.Unix(0,atomic.LoadInt64(&c.started)) }
func (c *Chrono) Stopped() time.Time {
return time.Unix(0,atomic.LoadInt64(&c.stopped)) }
func (c *Chrono) Elapsed() time.Duration {
st := atomic.LoadInt64(&c.started)
if st == 0 {
return 0
}
sp := atomic.LoadInt64(&c.stopped)
if sp == 0 {
return time.Now().Sub(time.Unix(0, int64(st)))
}
return time.Duration(sp - st)
}
func (c *Chrono) Reset() {
atomic.StoreInt64(&c.started,0)
atomic.StoreInt64(&c.stopped,0)
}
func (c *Chrono) Start() (tm time.Time) {
tm = time.Now()
atomic.CompareAndSwapInt64(&c.started,0,tm.UnixNano())
return
}
func (c *Chrono) Stop() (tm time.Time) {
tm = time.Now()
atomic.CompareAndSwapInt64(&c.stopped,0,tm.UnixNano())
return
}
func (c *Chrono) SetTimes(str, stp time.Time) {
atomic.StoreInt64(&c.started,str.UnixNano())
atomic.StoreInt64(&c.stopped,str.UnixNano())
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,59 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"time"
)
type (
Chronometer interface {
Started() time.Time
Stopped() time.Time
Elapsed() time.Duration
}
)
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,82 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"strconv"
"time"
)
type (
DurationFormatter interface {
FormatDuration (dur time.Duration, dst []byte) []byte
}
FormatDurationFnc func (dur time.Duration, dst []byte) []byte
)
func (f FormatDurationFnc) FormatDuration (dur time.Duration, dst []byte) []byte { return f(dur,dst) }
func WrapDurationFormatterQuoted (dfm DurationFormatter, qte byte) DurationFormatter {
return FormatDurationFnc(func(tme time.Duration, dst []byte) []byte {
dst = append(dst, qte)
dst = dfm.FormatDuration(tme, dst)
return append(dst, qte)
})
}
func DurationMillis (dur time.Duration, dst []byte) []byte {
return strconv.AppendFloat(dst, float64(dur)/float64(time.Millisecond), 'f', -1, 64)
}
func DurationNanos(dur time.Duration, dst []byte) []byte {
return strconv.AppendInt(dst, int64(dur), 10) }
func DurationSecs(dur time.Duration, dst []byte) []byte {
return strconv.AppendFloat(dst, float64(dur)/float64(time.Second), 'f', -1, 64) }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,182 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"sync/atomic"
"time"
)
type (
Expiration struct {
timer *time.Timer
times Chrono
state uint32
source uint32
timeout int64
deadline int64
expireFn func()
}
)
func NewExpiration(tmo time.Duration, fnc func()) *Expiration {
ex := &Expiration{
times: *NewChrono(false),
state: uint32(TimerStateCreated),
source: uint32(ExpirationSourceSelf),
timeout: int64(tmo),
expireFn: fnc,
}
if tmo > 0 {
atomic.StoreUint32(&ex.source,uint32(ExpirationSourceTimer))
}
return ex
}
func (e *Expiration) Reset() {
e.times.Reset()
atomic.StoreUint32(&e.state ,uint32(TimerStateCreated))
atomic.StoreUint32(&e.source,uint32(ExpirationSourceSelf))
atomic.StoreInt64 (&e.timeout ,0)
atomic.StoreInt64 (&e.deadline,0)
if e.timer != nil {
if !e.timer.Stop() {
select {
case <- e.timer.C:
default:
}
}
}
}
func (e *Expiration) State() TimerState {
return TimerState(atomic.LoadUint32(&e.state)) }
func (e *Expiration) Chono() Chronometer {
return &e.times }
func (e *Expiration) Source() ExpirationSource {
return ExpirationSource(atomic.LoadUint32(&e.source)) }
func (e *Expiration) Timeout() time.Duration {
return time.Duration(atomic.LoadInt64(&e.timeout)) }
func (e *Expiration) Deadline() time.Time {
return time.Unix(0,atomic.LoadInt64(&e.deadline)) }
func (e *Expiration) Start(exp Expirer) error {
if !atomic.CompareAndSwapUint32(&e.state,uint32(TimerStateCreated),uint32(TimerStateStarted)) {
return G.ErrAlreadyStarted
}
st := e.times.Start()
to := time.Duration(atomic.LoadInt64(&e.timeout))
dl := st.Add(to)
if exp != nil {
pd, ph := exp.Deadline()
if ph {
if pd.Before(st) {
atomic.StoreUint32(&e.state ,uint32(TimerStateExpired))
atomic.StoreUint32(&e.source,uint32(ExpirationSourceParent))
return G.ErrExpired
}
if pd.Before(dl) {
atomic.StoreInt64 (&e.deadline,pd.UnixNano())
atomic.StoreUint32(&e.source ,uint32(ExpirationSourceParent))
return nil
}
}
}
if atomic.LoadUint32(&e.source) == uint32(ExpirationSourceTimer) {
atomic.StoreInt64 (&e.deadline,dl.UnixNano())
if e.timer == nil {
e.timer = time.NewTimer(to)
} else {
e.timer.Reset(to)
}
go func(ex *Expiration) {
select {
case <-ex.timer.C:
atomic.StoreUint32(&ex.state,uint32(TimerStateExpired))
ex.times.Stop()
if ex.expireFn != nil {
ex.expireFn()
}
return
}
}(e)
}
return nil
}
func (e *Expiration) Stop() error {
if !atomic.CompareAndSwapUint32(&e.state,uint32(TimerStateStarted), uint32(TimerStateStopped)) {
return G.ErrNotStarted
}
e.times.Stop()
if e.timer != nil && !e.timer.Stop() {
select {
case <-e.timer.C:
}
}
return nil
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,62 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
const (
//ExpirationSource
ExpirationSourceSelf ExpirationSource = iota
ExpirationSourceParent
ExpirationSourceTimer
)
type (
ExpirationSource uint32
)
func (c ExpirationSource) String() string {
switch c {
case ExpirationSourceSelf : return "self"
case ExpirationSourceParent : return "parent"
case ExpirationSourceTimer : return "timer"
default:
return "unknown"
}
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,57 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"time"
)
type (
Expirer interface {
Deadline() (time.Time, bool)
}
DeadlineFnc func() (time.Time, bool)
)
func (f DeadlineFnc) Deadline() (time.Time, bool) {
return f() }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,4 @@
module activething.com/go/gogog/core/times
go 1.20

@ -0,0 +1,71 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"activething.com/go/gogo/core/errs"
)
var (
G = struct {
ErrExpired errs.ErrCode
ErrTimeout errs.ErrCode
ErrIntervalInvalid errs.ErrCode
ErrNotStarted errs.ErrCode
ErrNotPaused errs.ErrCode
ErrAlreadyStarted errs.ErrCode
ErrTransitionInvalid errs.ErrCode
ErrTimerTaskInvalid errs.ErrCode
} {
ErrExpired: errs.ErrCode("expired"),
ErrTimeout: errs.ErrCode("timeout"),
ErrIntervalInvalid: errs.ErrCode("interval_invalid"),
ErrNotStarted: errs.ErrCode("not_started"),
ErrNotPaused: errs.ErrCode("not_paused"),
ErrAlreadyStarted: errs.ErrCode("already_started"),
ErrTransitionInvalid:errs.ErrCode("transition_invalid"),
ErrTimerTaskInvalid: errs.ErrCode("timer_task_invalid"),
}
)
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,174 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"activething.com/go/gogo/core/contexts"
"context"
"sync/atomic"
"time"
)
type (
Pulsar struct {
state uint32
pulse int64
err atomic.Value
cancel contexts.Cancel
workFn PulsarWorkFnc
}
PulsarWorkFnc func() error
)
func NewPulsar(pulse time.Duration, work PulsarWorkFnc) *Pulsar {
return &Pulsar{
state: uint32(TimerStateCreated),
cancel: *contexts.NewCancel(),
pulse: int64(pulse),
workFn: work,
}
}
func (p *Pulsar) State() TimerState {
return TimerState(atomic.LoadUint32(&p.state)) }
func (p *Pulsar) Pulse() time.Duration {
return time.Duration(atomic.LoadInt64(&p.pulse)) }
func (p *Pulsar) Err() error {
if v := p.err.Load(); v != nil {
return v.(error)
}
return nil
}
func (p *Pulsar) Start(ctx context.Context) error {
if !atomic.CompareAndSwapUint32(&p.state,uint32(TimerStateCreated),uint32(TimerStateStarted)) {
return G.ErrAlreadyStarted
}
to := atomic.LoadInt64(&p.pulse)
if to <= 0 {
atomic.StoreUint32(&p.state,uint32(TimerStateExpired))
return G.ErrIntervalInvalid
}
cx := ctx
if cx == nil {
cx = context.Background()
} else if ctx.Err() != nil {
atomic.StoreUint32(&p.state,uint32(TimerStateCanceled))
return context.Canceled
}
go func(pl *Pulsar, tk *time.Ticker, cx context.Context) {
EXIT:
for {
select {
case <-cx.Done():
atomic.StoreUint32(&pl.state,uint32(TimerStateCanceled))
break EXIT
case <-pl.cancel.Done():
break EXIT
case <-tk.C:
if TimerState(atomic.LoadUint32(&pl.state)) == TimerStateStarted {
if er := pl.workFn(); er != nil {
pl.err.Store(er)
atomic.StoreUint32(&pl.state,uint32(TimerStateCanceled))
break EXIT
}
}
}
}
tk.Stop()
pl.cancel.Cancel()
}(p, time.NewTicker(time.Duration(to)), cx)
return nil
}
func (p *Pulsar) Stop() error {
if atomic.CompareAndSwapUint32(&p.state,uint32(TimerStateStarted), uint32(TimerStateStopped)) ||
atomic.CompareAndSwapUint32(&p.state,uint32(TimerStatePaused), uint32(TimerStateStopped)) {
p.cancel.Cancel()
return nil
}
return G.ErrNotStarted
}
func (p *Pulsar) Pause() error {
if atomic.CompareAndSwapUint32(&p.state,uint32(TimerStateStarted), uint32(TimerStatePaused)) {
return nil
}
return G.ErrNotStarted
}
func (p *Pulsar) Continue() error {
if atomic.CompareAndSwapUint32(&p.state,uint32(TimerStatePaused), uint32(TimerStateStarted)) {
return nil
}
return G.ErrNotPaused
}
func (p *Pulsar) Done() <-chan struct{} {
return p.cancel.Done() }
func (p *Pulsar) Wait() {
<-p.cancel.Done() }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,149 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"strconv"
"time"
)
type (
TimeFormatter interface {
FormatTime (tme time.Time, dst []byte) []byte
}
FormatTimeFnc func (tme time.Time, dst []byte) []byte
)
func (f FormatTimeFnc) FormatTime (tme time.Time, dst []byte) []byte { return f(tme,dst) }
func WrapTimeFormatterQuoted (tmf TimeFormatter, qte byte) TimeFormatter {
return FormatTimeFnc(func(tme time.Time, dst []byte) []byte {
dst = append(dst, qte)
dst = tmf.FormatTime(tme, dst)
return append(dst, qte)
})
}
func TimeRFC3339Nano(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RFC3339Nano)
}
func TimeANSIC(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.ANSIC)
}
func TimeUnixDate(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.UnixDate)
}
func TimeRubyDate(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RubyDate)
}
func TimeRFC822(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RFC822)
}
func TimeRFC822Z(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RFC822Z) }
func TimeRFC850(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RFC850) }
func TimeRFC1123(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RFC1123) }
func TimeRFC1123Z(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RFC1123Z) }
func TimeRFC3339(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RFC3339) }
func TimeKitchen(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.Kitchen) }
func TimeISO8601(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, "2006-01-02T15:04:05.000Z0700") }
func TimeEpoch(tme time.Time, dst []byte) []byte {
return strconv.AppendFloat(dst, float64(tme.UnixNano())/float64(time.Second), 'f', -1, 64) }
func TimeEpochMillis(tme time.Time, dst []byte) []byte {
return strconv.AppendFloat(dst, float64(tme.UnixNano())/float64(time.Millisecond), 'f', -1, 64) }
func TimeStamp(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.Stamp) }
func TimeStampMilli(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.StampMilli) }
func TimeStampMicro(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.StampMicro) }
func TimeStampNano(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.StampNano) }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -2,11 +2,11 @@
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name options.go
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -21,14 +21,27 @@
// limitations under the License.
// ------------------------------------------------------------------------
package pjson
package times
import (
"time"
)
type (
Options struct {}
TimeTaskFnc func(now time.Time)
)
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
func (o *Options) reset () {}
*/

@ -0,0 +1,190 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"activething.com/go/gogo/core/opts"
"container/heap"
"context"
"sync/atomic"
"time"
)
const (
timerQueueLen = 4096
timerQueueTime = time.Hour * 86400
)
type (
TimerQueue struct {
heap TimerTaskHeap
state uint32
pushCh chan *TimerTask
ctx context.Context
ctxCancelFn context.CancelFunc
nextTask *time.Time
timer *time.Timer
}
)
func NewTimerQueue(options ... opts.OptionFnc[TimerQueue]) *TimerQueue {
tq := &TimerQueue{
heap : TimerTaskHeap{},
state: uint32(TimerStateCreated),
}
heap.Init(&tq.heap)
opts.Apply(tq, options ...)
if tq.pushCh == nil {
tq.pushCh = make(chan *TimerTask, timerQueueLen)
}
return tq
}
func (q *TimerQueue) State() TimerState {
return TimerState(atomic.LoadUint32(&q.state)) }
func (q *TimerQueue) Start(ctx context.Context) error {
if !atomic.CompareAndSwapUint32(&q.state,uint32(TimerStateCreated),uint32(TimerStateStarted)) {
// error already started
return G.ErrAlreadyStarted
}
if q.timer == nil {
q.timer = time.NewTimer(timerQueueTime)
} else {
q.timer.Reset(timerQueueTime)
}
q.ctx, q.ctxCancelFn = context.WithCancel(ctx)
go func(qu *TimerQueue, cx context.Context) {
ts := make([]*TimerTask, 0, 10)
EXIT:
for {
select {
//--
case <-cx.Done():
atomic.CompareAndSwapUint32(&qu.state,uint32(TimerStateStarted),uint32(TimerStateCanceled))
break EXIT
//--
case nw := <-qu.timer.C:
ts = ts[:0]
for ix, ln := 0, qu.heap.Len(); ix < ln; ix++ {
pk := qu.heap[0]
if pk.RunAt.Before(nw) {
pp := heap.Pop(&qu.heap).(*TimerTask)
ts = append(ts, pp)
continue
}
break
}
if len(ts) > 0 {
go func(tm time.Time, tk []*TimerTask) {
for _, tt := range tk {
tt.TaskFn(tm)
}
}(nw, ts)
}
if qu.heap.Len() > 0 {
nr := qu.heap[0].RunAt
qu.nextTask = &nr
qu.timer.Reset(nr.Sub(time.Now()))
} else {
qu.timer.Stop()
qu.nextTask = nil
}
//--
case tt := <-q.pushCh:
heap.Push(&q.heap, tt)
if qu.nextTask == nil || qu.nextTask.After(tt.RunAt) {
if qu.nextTask != nil && !qu.timer.Stop() {
<-qu.timer.C
}
qu.timer.Reset(tt.RunAt.Sub(time.Now()))
qu.nextTask = &tt.RunAt
}
}
}
if !q.timer.Stop() {
<-qu.timer.C
}
qu.heap.Reset()
}(q, q.ctx)
return nil
}
func (q *TimerQueue) Stop() error {
if atomic.CompareAndSwapUint32(&q.state,uint32(TimerStateStarted),uint32(TimerStateCanceled)) {
q.ctxCancelFn()
return nil
}
return G.ErrNotStarted
}
func (q *TimerQueue) Push(rat time.Time, fnc TimeTaskFnc) error {
switch {
case rat.Before(time.Now()):
return G.ErrExpired
case fnc == nil:
return G.ErrTimerTaskInvalid
case TimerState(atomic.LoadUint32(&q.state)) != TimerStateStarted:
return G.ErrNotStarted
default:
select {
case q.pushCh <- NewTimerTask(rat, fnc):
return nil
case <-q.ctx.Done():
return context.Canceled
}
}
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,81 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
const (
//Enum values for TimerState
TimerStateCreated TimerState = 1 << iota
TimerStateStarted
TimerStatePaused
TimerStateExpired
TimerStateStopped
TimerStateCanceled
timerStateActive = TimerStateStarted + TimerStatePaused
)
type (
TimerState uint32
)
func (t TimerState) String() string {
switch t {
case TimerStateCreated:
return "created"
case TimerStateStarted:
return "started"
case TimerStatePaused:
return "paused"
case TimerStateExpired:
return "expired"
case TimerStateStopped:
return "stopped"
case TimerStateCanceled:
return "canceled"
default:
return "unknown"
}
}
func (t TimerState) IsActive() bool {
return t != timerStateActive }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,60 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
import (
"time"
)
type (
TimerTask struct {
RunAt time.Time
TaskFn TimeTaskFnc
}
)
func NewTimerTask(time time.Time, task TimeTaskFnc) *TimerTask {
return &TimerTask{
RunAt: time,
TaskFn: task,
}
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,86 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package times
type (
TimerTaskHeap []*TimerTask
)
func (h *TimerTaskHeap) Reset() {
*h = (*h)[:0] }
func (h *TimerTaskHeap) PushTimerTask(ele *TimerTask) {
if ele != nil {
*h = append(*h, ele)
}
}
func (h *TimerTaskHeap) PopTimerTask() *TimerTask {
th := *h
if ln := len(th); ln > 0 {
tt := th[ln-1]
*h = th[:ln-1]
return tt
}
return nil
}
func (h TimerTaskHeap) Len() int {
return len(h) }
func (h TimerTaskHeap) Less(i, j int) bool {
return h[i].RunAt.Before(h[j].RunAt) }
func (h TimerTaskHeap) Swap(i, j int) {
h[i], h[j] = h[j], h[i] }
func (h *TimerTaskHeap) Push(ele interface{}) {
h.PushTimerTask(ele.(*TimerTask)) }
func (h *TimerTaskHeap) Pop() interface{} {
return h.PopTimerTask() }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -12,6 +12,7 @@ use (
./core/opts
./core/syncs
./core/results
./core/times
./core/crypts
./packs

@ -27,7 +27,7 @@ import "time"
type (
PackListBuilder interface {
ListPackBuilder interface {
Error () error
@ -55,9 +55,9 @@ type (
ItemDate (value time.Time, flags Flags)
ItemList (builder func(PackListBuilder, Flags), flags Flags)
ItemMap (builder func(PackMapBuilder, Flags), flags Flags)
ItemObject(builder func(PackObjectBuilder,Flags), flags Flags)
ItemList (builder func(ListPackBuilder, Flags), flags Flags)
ItemMap (builder func(MapPackBuilder, Flags), flags Flags)
ItemObject(builder func(ObjectPackBuilder,Flags), flags Flags)
}
)

@ -27,7 +27,7 @@ import "time"
type (
PackMapBuilder interface {
MapPackBuilder interface {
KeyValueAny (key any, value any, flags Flags)
@ -53,9 +53,9 @@ type (
KeyValueDate (key any, value time.Time, flags Flags)
KeyValueList (key any, builder func(PackListBuilder, Flags), flags Flags)
KeyValueMap (key any, builder func(PackMapBuilder, Flags), flags Flags)
KeyValueObject(key any, builder func(PackObjectBuilder,Flags), flags Flags)
KeyValueList (key any, builder func(ListPackBuilder, Flags), flags Flags)
KeyValueMap (key any, builder func(MapPackBuilder, Flags), flags Flags)
KeyValueObject(key any, builder func(ObjectPackBuilder,Flags), flags Flags)
}

@ -27,7 +27,7 @@ import "time"
type (
PackObjectBuilder interface {
ObjectPackBuilder interface {
Error () error
@ -55,9 +55,9 @@ type (
FieldDate (name string, value time.Time, flags Flags)
FieldList (name string, builder func(PackListBuilder, Flags), flags Flags)
FieldMap (name string, builder func(PackMapBuilder, Flags), flags Flags)
FieldObject(name string, builder func(PackObjectBuilder,Flags), flags Flags)
FieldList (name string, builder func(ListPackBuilder, Flags), flags Flags)
FieldMap (name string, builder func(MapPackBuilder, Flags), flags Flags)
FieldObject(name string, builder func(ObjectPackBuilder,Flags), flags Flags)
}
)

@ -56,13 +56,13 @@ func (p *Packer) ItemFloat64 (value float64, flags packs.Flags){ p.addItem(func
func (p *Packer) ItemDate (value time.Time, flags packs.Flags) { p.addItem(func(){ packDate(p.state,value,flags); p.state.Inc() })}
func (p *Packer) ItemList (builder func(packs.PackListBuilder, packs.Flags), flags packs.Flags) {
func (p *Packer) ItemList (builder func(packs.ListPackBuilder, packs.Flags), flags packs.Flags) {
p.addItem(func(){ p.PackList(builder,flags) }) }
func (p *Packer) ItemMap (builder func(packs.PackMapBuilder, packs.Flags), flags packs.Flags) {
func (p *Packer) ItemMap (builder func(packs.MapPackBuilder, packs.Flags), flags packs.Flags) {
p.addItem(func(){ p.PackMap(builder,flags) }) }
func (p *Packer) ItemObject(builder func(packs.PackObjectBuilder, packs.Flags), flags packs.Flags) {
func (p *Packer) ItemObject(builder func(packs.ObjectPackBuilder, packs.Flags), flags packs.Flags) {
p.addItem(func(){ p.PackObject(builder,flags) }) }

@ -65,15 +65,15 @@ func (p *Packer) KeyValueDate (key any, value time.Time, flags packs.Flags){
func (p *Packer) KeyValueList (key any, builder func(packs.PackListBuilder, packs.Flags), flags packs.Flags) {
func (p *Packer) KeyValueList (key any, builder func(packs.ListPackBuilder, packs.Flags), flags packs.Flags) {
p.addKeyValue(key,func(){ p.PackList(builder, flags) }) }
func (p *Packer) KeyValueMap (key any, builder func(packs.PackMapBuilder, packs.Flags), flags packs.Flags) {
func (p *Packer) KeyValueMap (key any, builder func(packs.MapPackBuilder, packs.Flags), flags packs.Flags) {
p.addKeyValue(key,func(){ p.PackMap(builder, flags) }) }
func (p *Packer) KeyValueObject (key any, builder func(packs.PackObjectBuilder,packs.Flags), flags packs.Flags) {
func (p *Packer) KeyValueObject (key any, builder func(packs.ObjectPackBuilder,packs.Flags), flags packs.Flags) {
p.addKeyValue(key,func(){ p.PackObject(builder, flags) }) }

@ -85,15 +85,15 @@ func (p *Packer) FieldDate (name string, value time.Time,flags packs.Flags) {
p.addField(name,func(){ p.PackDate(value, flags) })
}
func (p *Packer) FieldList (name string, builder func(packs.PackListBuilder,packs.Flags), flags packs.Flags) {
func (p *Packer) FieldList (name string, builder func(packs.ListPackBuilder,packs.Flags), flags packs.Flags) {
p.addField(name,func(){ p.PackList(builder, flags) })
}
func (p *Packer) FieldMap (name string, builder func(packs.PackMapBuilder, packs.Flags), flags packs.Flags) {
func (p *Packer) FieldMap (name string, builder func(packs.MapPackBuilder, packs.Flags), flags packs.Flags) {
p.addField(name,func(){ p.PackMap(builder, flags) })
}
func (p *Packer) FieldObject (name string, builder func(packs.PackObjectBuilder,packs.Flags), flags packs.Flags) {
func (p *Packer) FieldObject (name string, builder func(packs.ObjectPackBuilder,packs.Flags), flags packs.Flags) {
p.addField(name,func(){ p.PackObject(builder, flags) })
}

@ -45,7 +45,6 @@ type (
Packer struct {
state *packs.State
dirty bool
Options
}
)
@ -81,7 +80,6 @@ func (p *Packer) Error () error {
func (p *Packer) Reset () {
p.state.Reset()
p.Options.reset()
p.dirty = false
}
@ -189,15 +187,15 @@ func (p *Packer) PackFloat64 (value float64, flags packs.Flags) { packFloatStrin
func (p *Packer) PackDate (value time.Time, flags packs.Flags) { packDate(p.state,value,flags) }
func (p *Packer) PackList (builder func(packs.PackListBuilder, packs.Flags), flags packs.Flags) {
func (p *Packer) PackList (builder func(packs.ListPackBuilder, packs.Flags), flags packs.Flags) {
p.packCompound('[',']',builder==nil,func(pk *Packer, fl packs.Flags){ builder(pk,fl) },flags)
}
func (p *Packer) PackMap (builder func(packs.PackMapBuilder, packs.Flags), flags packs.Flags) {
func (p *Packer) PackMap (builder func(packs.MapPackBuilder, packs.Flags), flags packs.Flags) {
p.packCompound('{','}',builder==nil,func(pk *Packer, fl packs.Flags){ builder(pk,fl) },flags)
}
func (p *Packer) PackObject(builder func(packs.PackObjectBuilder, packs.Flags), flags packs.Flags) {
func (p *Packer) PackObject(builder func(packs.ObjectPackBuilder, packs.Flags), flags packs.Flags) {
p.packCompound('{','}',builder==nil,func(pk *Packer, fl packs.Flags){ builder(pk,fl) },flags)
}

@ -52,9 +52,9 @@ type (
PackDate (value time.Time, flags Flags)
PackList (flags Flags, builder func(PackListBuilder, Flags))
PackMap (flags Flags, builder func(PackMapBuilder, Flags))
PackObject(flags Flags, builder func(PackObjectBuilder,Flags))
PackList (flags Flags, builder func(ListPackBuilder, Flags))
PackMap (flags Flags, builder func(MapPackBuilder, Flags))
PackObject(flags Flags, builder func(ObjectPackBuilder,Flags))
}
)

@ -31,23 +31,24 @@ import (
type (
MatchersRepo struct {
Builder struct {
sync.RWMutex
matchers map[string]Matcher
}
MatchersRepoFnc func (repo *MatchersRepo)
BuilderFnc func (repo *Builder)
)
func NewMatchersRepo (options ...opts.OptionFnc[MatchersRepo]) *MatchersRepo {
return opts.Apply(&MatchersRepo{ matchers: make(map[string]Matcher)}) }
func NewBuilder(options ...opts.OptionFnc[Builder]) *Builder {
return opts.Apply(&Builder{ matchers: make(map[string]Matcher)}, options...)
}
func (r *MatchersRepo) GetMatcher (name string) (m Matcher) {
func (r *Builder) GetMatcher (name string) (m Matcher) {
r.RLock()
m, _ = r.matchers[name]
r.RUnlock()
@ -55,7 +56,7 @@ func (r *MatchersRepo) GetMatcher (name string) (m Matcher) {
}
func (r *MatchersRepo) SetMatcher (name string, matcher Matcher) {
func (r *Builder) SetMatcher (name string, matcher Matcher) {
r.Lock()
if matcher == nil {
delete(r.matchers,name)
@ -70,7 +71,7 @@ func (r *MatchersRepo) SetMatcher (name string, matcher Matcher) {
func (r *MatchersRepo) BuildMatcher (data []byte) (Matcher,error) {
func (r *Builder) BuildMatcher (data []byte) (Matcher,error) {
data = data[1:len(data)-1]
if len(data) == 0 {
return nil,G.ErrInvalidMatcher

@ -1,44 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name matcher_builder.go
// Created by DEV
// Modified 17/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package matches
type (
MatcherBuilder interface {
BuildMatcher (value []byte) (Matcher,error)
}
BuildMatcherFnc func (value []byte)(Matcher, error)
)
func (f BuildMatcherFnc) BuildMatcher (value []byte) (Matcher,error) {
return f(value) }

@ -1,26 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name token_builder.go
// Created by DEV
// Modified 18/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package tokens

@ -58,6 +58,7 @@ var (
ErrInvalidTopicLen errs.ErrCode
ErrInvalidToken errs.ErrCode
ErrInvalidTokenLen errs.ErrCode
ErrInvalidMatcher errs.ErrCode
}{
@ -65,6 +66,7 @@ var (
ErrInvalidTopicLen : errs.ErrCode ("sapis:tokens.invalid-topic-len"),
ErrInvalidToken : errs.ErrCode ("sapis:tokens.invalid-token"),
ErrInvalidTokenLen : errs.ErrCode ("sapis:tokens.invalid-token-len"),
ErrInvalidMatcher : errs.ErrCode ("sapis:tokens.invalid-matcher"),
}

@ -28,29 +28,29 @@ package tokens
type (
TokenInvalid struct {
InvalidToken struct {
/*embedded*/ error
source []byte
}
)
func NewTokenInvalid(err error, src []byte) *TokenInvalid {
return &TokenInvalid{
func NewInvalidToken(err error, src []byte) *InvalidToken {
return &InvalidToken{
error: err,
source: src,
}
}
func (_ TokenInvalid) Kind() TokenKind {
func (_ InvalidToken) Kind() TokenKind {
return TokenKindInvalid }
func (_ TokenInvalid) Match(_ []byte) bool {
func (_ InvalidToken) Match(_ []byte) bool {
return false }
func (t TokenInvalid) Source() []byte {
func (t InvalidToken) Source() []byte {
return t.source }

@ -26,19 +26,19 @@ package tokens
type TokenLiteral []byte
type LiteralToken []byte
func (t TokenLiteral) Kind () TokenKind {
func (t LiteralToken) Kind () TokenKind {
return TokenKindLiteral }
func (t TokenLiteral) Match(target []byte) bool {
func (t LiteralToken) Match(target []byte) bool {
return string(t) == string(target) }
func (t TokenLiteral) Source() []byte {
func (t LiteralToken) Source() []byte {
return t }

@ -28,7 +28,7 @@ import "activething.com/go/gogo/sapis/matches"
type (
TokenMatcher struct {
MatcherToken struct {
source []byte
MatchFn matches.MatchFnc
}
@ -36,23 +36,23 @@ type (
func NewTokenMatcher(mfn matches.MatchFnc, src []byte) *TokenMatcher {
return &TokenMatcher{
func NewMatcherToken(mfn matches.MatchFnc, src []byte) *MatcherToken {
return &MatcherToken{
MatchFn: mfn,
source: src,
}
}
func (_ TokenMatcher) Kind() TokenKind {
func (_ MatcherToken) Kind() TokenKind {
return TokenKindMatcher }
func (t TokenMatcher) Match(val []byte) bool {
func (t MatcherToken) Match(val []byte) bool {
return t.MatchFn(val) }
func (t TokenMatcher) Source() []byte {
func (t MatcherToken) Source() []byte {
return t.source }

@ -28,19 +28,19 @@ package tokens
type (
TokenRelative struct{}
RelativeToken struct{}
)
func (_ TokenRelative) Kind() TokenKind {
func (_ RelativeToken) Kind() TokenKind {
return TokenKindRelative }
func (_ TokenRelative) Match(_ []byte) bool {
func (_ RelativeToken) Match(_ []byte) bool {
return true }
func (t TokenRelative) Source() []byte {
func (t RelativeToken) Source() []byte {
return nil }

@ -39,3 +39,5 @@ type (
)

@ -26,8 +26,8 @@ package tokens
const (
// TokenKind enum values
//
//TokenKind enum values
TokenKindNone TokenKind = 0
TokenKindLiteral TokenKind = 1
TokenKindWildcard TokenKind = 2
@ -35,9 +35,9 @@ const (
TokenKindRelative TokenKind = 8
TokenKindInvalid TokenKind = 128
//
// TokenKind compund values
//
//TokenKind compund values
TokenKindAny = TokenKindRelative | TokenKindWildcard
TokenKindTopic = TokenKindLiteral | TokenKindMatcher | TokenKindAny
TokenKindMatchable = TokenKindLiteral | TokenKindMatcher

@ -0,0 +1,185 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name token_builder.go
// Created by DEV
// Modified 18/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package tokens
import (
"activething.com/go/gogo/core/opts"
"activething.com/go/gogo/sapis/matches"
)
type (
Tokenizer struct {
TokenizerOptions
matcher matches.Builder
}
)
func NewTokenizer(options ...opts.OptionFnc[TokenizerOptions]) *Tokenizer {
return &Tokenizer{
TokenizerOptions: *NewBuilderOptions(options...),
matcher : *matches.NewBuilder(),
}
}
func (b *Tokenizer) Tokenize (topic []byte, allows TokenKind)([]Token,TokenKind) {
ln := len(topic)
if ln < b.TopicMinLen || ln > b.TopicMaxLen {
return []Token{*(NewInvalidToken(G.ErrInvalidTopicLen,topic))},TokenKindInvalid
}
ls := [topicMaxTokens]Token{}
tt := TokenKindNone
var m,c,x int
for i:=0; i<ln; i++ {
switch topic[i] {
case b.MatchIni: m++
case b.MatchEnd: m--
case b.Sep:
if m != 0 {
continue
}
if c >= b.MaxTokens {
ls[c]=*(NewInvalidToken(G.ErrInvalidTopicLen,topic[x:]))
return ls[:c+1],tt | TokenKindInvalid
}
ls[c] = b.MakeToken(topic[x:i])
tk := ls[c].Kind()
if tk == TokenKindRelative {
ls[c] = *NewInvalidToken(G.ErrInvalidToken,topic[x:i])
} else if tk&allows != 0 {
tt |= TokenKindInvalid
} else {
tt |= ls[c].Kind()
}
x = i + 1
c++
}
}
if m != 0 {
ls[c] = *NewInvalidToken(G.ErrInvalidTopic,topic[x:])
} else {
ls[c] = b.MakeToken(topic[x:])
}
return ls[:c+1], tt | ls[c].Kind()
}
func (b *Tokenizer) MakeToken(source []byte) Token {
ln := len(source)
if ln < b.TokenMinLen || ln > b.TokenMaxLen {
return *(NewInvalidToken(G.ErrInvalidTokenLen,source))
}
if ln == 1 {
switch source[0] {
case b.Wildcard: return WildcardToken{}
case b.Relative: return RelativeToken{}
case b.MatchIni,
b.MatchEnd: return *(NewInvalidToken(G.ErrInvalidTokenLen,source))
}
}
if source[0] != b.MatchIni {
return LiteralToken(source)
}
if source[ln-1] != b.MatchEnd || ln > b.TokenMinLen+2 {
m,e := b.matcher.BuildMatcher(source)
if e != nil {
return *NewInvalidToken(G.ErrInvalidMatcher.WithCause(e),source)
}
return *NewMatcherToken(m.Match,source)
}
return *NewInvalidToken(G.ErrInvalidMatcher,source)
}
func (b *Tokenizer) Split (topic []byte, allows TokenKind) ([][]byte,TokenKind) {
var ms, ps, x int
var tk, pk TokenKind
ln := len(topic)
ar := [topicMaxTokens][]byte{}
for i := 0; i < ln; i++ {
switch topic[i] {
case b.MatchIni:
ms++
case b.MatchEnd:
ms--
case b.Sep:
if ms == 0 {
ar[ps] = topic[x:i]
if pk = b.TokenKind(ar[ps]); pk&allows == 0 {
return nil, TokenKindInvalid
}
tk |= pk
x = i + 1
ps++
}
}
}
ar[ps] = topic[x:]
if pk = b.TokenKind(ar[ps]); pk&allows == 0 {
return nil, TokenKindInvalid
}
tk |= pk
return ar[:ps+1], tk
}
func (b *Tokenizer) TokenKind(Token []byte) TokenKind {
ln := len(Token)
if ln < b.TokenMinLen || ln > b.TokenMaxLen {
return TokenKindInvalid
}
if ln == 1 {
switch Token[0] {
case b.Wildcard: return TokenKindWildcard
case b.Relative: return TokenKindRelative
case b.MatchIni,
b.MatchEnd: return TokenKindInvalid
}
}
if Token[0] == b.MatchIni {
if Token[ln-1] == b.MatchEnd {
return TokenKindMatcher
}
return TokenKindInvalid
}
return TokenKindLiteral
}

@ -27,7 +27,7 @@ import "activething.com/go/gogo/core/opts"
type (
BuilderOptions struct {
TokenizerOptions struct {
Sep byte
Wildcard byte
Relative byte
@ -37,28 +37,32 @@ type (
TokenMinLen int
TokenMaxLen int
TopicMinLen int
TopicMaxLen int
TopicMinTokens int
TopicMaxTokens int
TopicMaxLen int
MinTokens int
MaxTokens int
}
)
func NewBuilderOptions (options ... opts.OptionFnc[BuilderOptions]) *BuilderOptions {
return opts.Apply(&BuilderOptions{
func NewBuilderOptions (options ... opts.OptionFnc[TokenizerOptions]) *TokenizerOptions {
op := opts.Apply(&TokenizerOptions{
Sep : tokenSep,
Wildcard : tokenWildcard,
Relative : tokenRelative,
MatchIni : tokenMatchIni,
MatchEnd : tokenMatchEnd,
TokenMinLen: tokenMinLen,
TokenMaxLen: tokenMaxLen,
TopicMinLen: topicMinLen,
TopicMaxLen: topicMaxLen,
TopicMinTokens: topicMinTokens,
TopicMaxTokens: topicMaxTokens,
TokenMinLen: tokenMinLen,
TokenMaxLen: tokenMaxLen,
TopicMinLen: topicMinLen,
TopicMaxLen: topicMaxLen,
MinTokens: topicMinTokens,
MaxTokens: topicMaxTokens,
}, options ...)
if op.MinTokens > topicMaxTokens {
op.MinTokens = topicMinTokens
}
return op
}

@ -0,0 +1,105 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name topic.go
// Created by DEV
// Modified 18/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package tokens
type (
Topic struct {
kind TokenKind
source []byte
tokens []Token
}
)
func NewTopic(builder *Tokenizer, topic []byte, allows TokenKind) *Topic {
tp := &Topic{ source: topic }
tp.tokens, tp.kind = builder.Tokenize(topic, allows)
return tp
}
func (t Topic) Len() int {
return len(t.tokens) }
func (t Topic) Kind() TokenKind {
return t.kind }
func (t Topic) Source() []byte {
return t.source }
func (t Topic) Tokens() []Token {
return t.tokens }
func (t Topic) String() string {
return string(t.source) }
func (t Topic) Match(subject [][]byte) bool {
if t.kind.HasInvalid() {
return false
}
ln := len(t.tokens)
ls := len(subject)
if ln != ls {
if ln > ls {
return false
}
if !t.kind.HasRelative() {
return false
}
}
for i := 0; i < ln; i++ {
if t.tokens[i].Kind()&TokenKindMatchable != 0 {
if !t.tokens[i].Match(subject[i]) {
return false
}
}
}
return true
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,111 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name topic_list.go
// Created by DEV
// Modified 18/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package tokens
import (
"activething.com/go/gogo/core/slices"
"bytes"
)
type (
TopicList []Topic
)
func (s TopicList) Match(subject [][]byte) bool {
for i, l := 0, len(subject); i < l; i++ {
if s[i].Match(subject) {
return true
}
}
return false
}
func (s TopicList) Exists(topic []byte) int {
ln := len(s)
if ln > 0 {
for i := 0; i < ln; i++ {
if bytes.Equal(s[i].source, topic) {
return i
}
}
}
return slices.NotFound
}
func (s TopicList) Len() int {
return len(s) }
func (s TopicList) Less(i, j int) bool {
li, lj := len(s[i].tokens), len(s[j].tokens)
if li < lj {
return true
}
if lj < li {
return false
}
if s[i].kind.HasRelative() && !s[j].kind.HasRelative() {
return true
} else if s[j].kind.HasRelative() {
return false
}
// Comparators token count
ci, cj := 0, 0
for x := 0; i < li; i++ {
if s[i].tokens[x].Kind().HasMatchable() {
ci++
}
if s[j].tokens[x].Kind().HasMatchable() {
cj++
}
}
return ci > cj
}
func (s TopicList) Swap(i, j int) {
s[i], s[j] = s[j], s[i] }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -28,19 +28,19 @@ package tokens
type (
TokenWildcard struct{}
WildcardToken struct{}
)
func (_ TokenWildcard) Kind() TokenKind {
func (_ WildcardToken) Kind() TokenKind {
return TokenKindWildcard }
func (_ TokenWildcard) Match(_ []byte) bool {
func (_ WildcardToken) Match(_ []byte) bool {
return true }
func (t TokenWildcard) Source() []byte {
func (t WildcardToken) Source() []byte {
return nil }
/*
Loading…
Cancel
Save

Powered by TurnKey Linux.