Преглед на файлове

SVI Добавление типа Int

SVI преди 6 месеца
родител
ревизия
101034c7ec

+ 66 - 25
v3/kc/safe_int/safe_int.go

@@ -3,28 +3,29 @@ package safe_int
 
 import (
 	"fmt"
-	"os"
-	"strconv"
 	"sync"
 
+	"gitp78su.ipnodns.ru/svi/kern/v3/krn/kint"
 	. "gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
 )
 
 // safeInt -- потокобезопасное целое
 type safeInt struct {
 	sync.RWMutex
-	val int
+	val Int
 }
 
 // NewSafeInt -- возвращает новое потокобезопасное целое
-func NewSafeInt() ISafeInt {
-	sf := &safeInt{}
+func NewSafeInt(val int) ISafeInt {
+	sf := &safeInt{
+		val: kint.NewInt(val),
+	}
 	return sf
 }
 
-// NewSafeIntFromStr -- возвращает новое потокобезоппсное целое из строки
+// NewSafeIntFromStr -- возвращает новое потокобезопасное целое из строки
 func NewSafeIntFromStr(strVal string) Result[ISafeInt] {
-	sf := NewSafeInt()
+	sf := NewSafeInt(0)
 	res := sf.FromStr(strVal)
 	if res.IsErr() {
 		err := fmt.Errorf("NewSafeIntFromStr(): in parse str(%v), err=\n\t%w", strVal, res.Err())
@@ -33,9 +34,9 @@ func NewSafeIntFromStr(strVal string) Result[ISafeInt] {
 	return NewOk(sf)
 }
 
-// NewSafeIntGetenv -- возвращает новое потокобезоппсное целое из окружения
+// NewSafeIntGetenv -- возвращает новое потокобезопасное целое из окружения
 func NewSafeIntGetenv(env string) Result[ISafeInt] {
-	sf := NewSafeInt()
+	sf := NewSafeInt(0)
 	res := sf.Getenv(env)
 	if res.IsErr() {
 		err := fmt.Errorf("NewSafeIntGetenv(): in parse env(%v), err=\n\t%w", env, res.Err())
@@ -44,46 +45,86 @@ func NewSafeIntGetenv(env string) Result[ISafeInt] {
 	return NewOk(sf)
 }
 
+// FromBool -- устанавливает значение из булева значения
+func (sf *safeInt) FromBool(val bool) int {
+	sf.Lock()
+	defer sf.Unlock()
+	return sf.val.FromBool(val)
+}
+
 // Get -- возвращает хранимое целое
 func (sf *safeInt) Get() int {
 	sf.RLock()
 	defer sf.RUnlock()
-	return sf.val
+	return sf.val.Get()
+}
+
+// Dec -- уменьшает значение на 1
+func (sf *safeInt) Dec() {
+	sf.Lock()
+	defer sf.Unlock()
+	sf.val.Dec()
+}
+
+// Inc -- увеличивает значение на 1
+func (sf *safeInt) Inc() {
+	sf.Lock()
+	defer sf.Unlock()
+	sf.val.Inc()
 }
 
 // Set -- устанавливает целое
 func (sf *safeInt) Set(val int) {
 	sf.Lock()
 	defer sf.Unlock()
-	sf.val = val
+	sf.val.Set(val)
 }
 
 // Reset -- сбрасывает целое
 func (sf *safeInt) Reset() {
 	sf.Lock()
 	defer sf.Unlock()
-	sf.val = 0
+	sf.val.Reset()
 }
 
 // FromStr -- получает число из строки
 func (sf *safeInt) FromStr(strVal string) Result[int] {
-	iVal, err := strconv.Atoi(strVal)
-	if err != nil {
-		return NewErr[int](fmt.Errorf("safeInt.FromStr(): vak(%v) bad, err=\n\t%w", strVal, err))
-	}
 	sf.Lock()
 	defer sf.Unlock()
-	sf.val = iVal
-	return NewOk(sf.val)
+	return sf.val.FromStr(strVal)
+}
+
+// FromByte -- получает число из среза байт
+func (sf *safeInt) FromByte(binData []byte) Result[int] {
+	sf.Lock()
+	defer sf.Unlock()
+	return sf.val.FromByte(binData)
+}
+
+// ToByte -- конвертирует число в срез байт
+func (sf *safeInt) ToByte() []byte {
+	sf.RLock()
+	defer sf.RUnlock()
+	return sf.val.ToByte()
+}
+
+// ToBool -- конвертирует число в bool
+func (sf *safeInt) ToBool() bool {
+	sf.RLock()
+	defer sf.RUnlock()
+	return sf.val.ToBool()
+}
+
+// ToStr -- конвертирует число в строку
+func (sf *safeInt) ToStr() string {
+	sf.RLock()
+	defer sf.RUnlock()
+	return sf.val.ToStr()
 }
 
 // Getenv -- получает значение из окружения
 func (sf *safeInt) Getenv(env string) Result[int] {
-	strVal := os.Getenv(env)
-	res := sf.FromStr(strVal)
-	if res.IsErr() {
-		err := fmt.Errorf("safeInt.Getenv(): from env %v, err=\n\t%w", env, res.Err())
-		return NewErr[int](err)
-	}
-	return res
+	sf.Lock()
+	defer sf.Unlock()
+	return sf.val.Getenv(env)
 }

+ 82 - 12
v3/kc/safe_int/safe_int_test.go

@@ -16,13 +16,83 @@ func TestSafeInt(t *testing.T) {
 	sf := &tester{
 		t: t,
 	}
-	sf.new()
-	sf.newGetenv()
-	sf.newFromStr()
-	sf.set()
-	sf.reset()
-	sf.fromStr()
-	sf.getEnv()
+	{
+		sf.new()
+		sf.newGetenv()
+		sf.newFromStr()
+		sf.set()
+		sf.reset()
+		sf.fromStr()
+		sf.getEnv()
+	}
+	{
+		sf.inc()
+		sf.dec()
+		sf.fromBool()
+		sf.toBool()
+		sf.toStr()
+		sf.byte()
+	}
+}
+
+func (sf *tester) byte() {
+	sf.t.Log("byte")
+	res := NewSafeInt(1234)
+	binData := res.ToByte()
+	if len(binData) != 8 {
+		sf.t.Fatalf("byte(): len val(%v)!='123''", len(binData))
+	}
+	resVal := res.FromByte(binData)
+	resVal.Hassert("from []byte")
+	val := resVal.Val()
+	if val != 1234 {
+		sf.t.Fatalf("byte(): val(%v)!=1234", val)
+	}
+}
+
+func (sf *tester) toStr() {
+	sf.t.Log("toStr")
+	res := NewSafeInt(123)
+	val := res.ToStr()
+	if val != "123" {
+		sf.t.Fatalf("dec(): val(%v)!='123''", val)
+	}
+}
+
+func (sf *tester) toBool() {
+	sf.t.Log("toBool")
+	res := NewSafeInt(0)
+	val := res.ToBool()
+	if val {
+		sf.t.Fatalf("toBool(): val(%v)!=false", val)
+	}
+}
+
+func (sf *tester) fromBool() {
+	sf.t.Log("fromBool")
+	res := NewSafeInt(12)
+	val := res.FromBool(true)
+	if val != -1 {
+		sf.t.Fatalf("fromBool(): val(%v)!=-1", val)
+	}
+}
+
+func (sf *tester) dec() {
+	sf.t.Log("dec")
+	res := NewSafeInt(10)
+	res.Dec()
+	if val := res.Get(); val != 9 {
+		sf.t.Fatalf("dec(): val(%v)!=9", val)
+	}
+}
+
+func (sf *tester) inc() {
+	sf.t.Log("inc")
+	res := NewSafeInt(52)
+	res.Inc()
+	if val := res.Get(); val != 53 {
+		sf.t.Fatalf("inc(): val(%v)!=53", val)
+	}
 }
 
 // Получает целое из строки
@@ -70,7 +140,7 @@ func (sf *tester) getEnvGood1() {
 	sf.t.Log("getEnvGood1")
 	os.Unsetenv("TEST_VAL")
 	os.Setenv("TEST_VAL", "45")
-	val := NewSafeInt()
+	val := NewSafeInt(0)
 	res := val.Getenv("TEST_VAL")
 	if res.IsErr() {
 		sf.t.Fatalf("getEnvGood1(): err=%v", res.Err())
@@ -85,7 +155,7 @@ func (sf *tester) getEnvBad1() {
 	sf.t.Log("getEnvBad1")
 	os.Unsetenv("TEST_VAL")
 	os.Setenv("TEST_VAL", "")
-	val := NewSafeInt()
+	val := NewSafeInt(0)
 	res := val.Getenv("TEST_VAL")
 	if res.IsOk() {
 		sf.t.Fatalf("getEnvBad1(): res==ok")
@@ -101,7 +171,7 @@ func (sf *tester) fromStr() {
 
 func (sf *tester) fromStrGood1() {
 	sf.t.Log("fromStrGood1")
-	val := NewSafeInt()
+	val := NewSafeInt(0)
 	res := val.FromStr("45")
 	if res.IsErr() {
 		sf.t.Fatalf("fromStrGood1(): err=%v", res.Err())
@@ -114,7 +184,7 @@ func (sf *tester) fromStrGood1() {
 // Строка не число
 func (sf *tester) fromStrBad1() {
 	sf.t.Log("fromStrBad1")
-	val := NewSafeInt()
+	val := NewSafeInt(0)
 	res := val.FromStr(" ")
 	if res.IsOk() {
 		sf.t.Fatalf("fromStrBad1(): res==ok")
@@ -150,7 +220,7 @@ func (sf *tester) set() {
 // Создаёт потокобезопасный булевый признак
 func (sf *tester) new() {
 	sf.t.Log("new")
-	sf.si = NewSafeInt()
+	sf.si = NewSafeInt(0)
 	if sf.si == nil {
 		sf.t.Fatalf("new(): ISafeInt==nil")
 	}

+ 3 - 3
v3/kern.go

@@ -152,9 +152,9 @@ func NewSafeBoolReact() ISafeBoolReact {
 }
 
 // NewSafeInt -- возвращает новую потокобезопасную целочисленную переменную
-func NewSafeInt() ISafeInt {
-	val := safe_int.NewSafeInt()
-	return val
+func NewSafeInt(val int) ISafeInt {
+	val_ := safe_int.NewSafeInt(val)
+	return val_
 }
 
 // NewLocalCtx -- возвращает новый локальный контекст

+ 1 - 1
v3/kern_test.go

@@ -129,7 +129,7 @@ func (sf *tester) new() {
 		if boolReact == nil {
 			sf.t.Fatalf("new(): ISafeBoolReact==nil")
 		}
-		safeInt := NewSafeInt()
+		safeInt := NewSafeInt(12)
 		if safeInt == nil {
 			sf.t.Fatalf("new(): ISafeInt==nil")
 		}

+ 113 - 0
v3/krn/kint/kint.go

@@ -0,0 +1,113 @@
+// package kint -- целочисленная переменная ядра
+package kint
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"os"
+	"strconv"
+
+	. "gitp78su.ipnodns.ru/svi/kern/v3/kc/helpers"
+	. "gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
+)
+
+// Целочисленная переменная ядра
+type KernInt struct {
+	val int
+}
+
+// NewInt -- возвращает новое целое ядра
+func NewInt(val int) Int {
+	sf := &KernInt{
+		val: val,
+	}
+	return sf
+}
+
+// Get -- возвращает хранимое значение потокобезопасной переменной
+func (sf *KernInt) Get() int {
+	return sf.val
+}
+
+// Set -- устанавливает хранимое потокобезопасное значение
+func (sf *KernInt) Set(val int) {
+	sf.val = val
+}
+
+// Inc -- увеличивает на единицу
+func (sf *KernInt) Inc() {
+	sf.val++
+}
+
+// Dec -- уменьшает на единицу
+func (sf *KernInt) Dec() {
+	sf.val--
+}
+
+// Reset -- сбрасывает хранимое потокобезопасное значение
+func (sf *KernInt) Reset() {
+	sf.val = 0
+}
+
+// FromStr -- устанавливает значение из строки
+func (sf *KernInt) FromStr(strVal string) Result[int] {
+	iVal, err := strconv.Atoi(strVal)
+	if err != nil {
+		return NewErr[int](fmt.Errorf("KInt.FromStr(): vak(%v) bad, err=\n\t%w", strVal, err))
+	}
+	sf.val = iVal
+	return NewOk(iVal)
+}
+
+// ToStr -- возвращает как строку
+func (sf *KernInt) ToStr() string {
+	return fmt.Sprint(sf.val)
+}
+
+// FromByte -- устанавливает значение из байтов (BigEndian, net order)
+func (sf *KernInt) FromByte(binData []byte) Result[int] {
+	lenBin := len(binData)
+	if lenBin < 8 {
+		return NewErr[int](fmt.Errorf("KInt.FromByte(): len(%v) bytes shorts", lenBin))
+	}
+	var signed int64
+	buf := bytes.NewReader(binData)
+	err := binary.Read(buf, binary.BigEndian, &signed)
+	Hassert(err == nil, "KernInt.FromByte(): in read []byte, err=\n\t%w", err)
+	sf.val = int(signed)
+	return NewOk(sf.val)
+}
+
+// ToByte -- возвращает как срез байт
+func (sf *KernInt) ToByte() []byte {
+	buf := make([]byte, 8)
+	binary.BigEndian.PutUint64(buf, uint64(sf.val))
+	return buf
+}
+
+// FromBool -- устанавливает значение из булева
+func (sf *KernInt) FromBool(isVal bool) int {
+	if isVal {
+		sf.val = -1
+		return -1
+	}
+	sf.val = 0
+	return 0
+}
+
+// ToBool -- возвращает как булево значение
+func (sf *KernInt) ToBool() bool {
+	return sf.val != 0
+}
+
+// Getenv -- устанавливает значение из окружения
+func (sf *KernInt) Getenv(env string) Result[int] {
+	strVal := os.Getenv(env)
+	res := sf.FromStr(strVal)
+	if res.IsErr() {
+		err := fmt.Errorf("safeInt.Getenv(): from env %v, err=\n\t%w", env, res.Err())
+		return NewErr[int](err)
+	}
+	return NewOk(sf.val)
+}

+ 114 - 0
v3/krn/kint/kint_test.go

@@ -0,0 +1,114 @@
+package kint
+
+import (
+	"os"
+	"testing"
+)
+
+type tester struct {
+	t *testing.T
+}
+
+func TestKInt(t *testing.T) {
+	sf := &tester{
+		t: t,
+	}
+	sf.new()
+}
+
+// новый KInt
+func (sf *tester) new() {
+	sf.t.Log("new")
+	val := NewInt(12)
+	if val == nil {
+		sf.t.Fatalf("new(): val==nil")
+	}
+	val0 := val.Get()
+	if val0 != 12 {
+		sf.t.Fatalf("new(): val0=%v !12", val0)
+	}
+	val.Set(14)
+	if val.Get() != 14 {
+		sf.t.Fatalf("new(): val=%v !14", val.Get())
+	}
+	val.Reset()
+	if val.Get() != 0 {
+		sf.t.Fatalf("new(): val=%v !0", val.Get())
+	}
+	resStr := val.FromStr("26")
+	if val.Get() != 26 {
+		sf.t.Fatalf("new(): val=%v !26", val.Get())
+	}
+	resStr.Hassert("bad convert")
+
+	resStr = val.FromStr("k26")
+	if val.Get() != 26 {
+		sf.t.Fatalf("new(): val=%v !26", val.Get())
+	}
+	if !resStr.IsErr() {
+		sf.t.Fatalf("new(): err==nil")
+	}
+	strVal := val.ToStr()
+	if strVal != "26" {
+		sf.t.Fatalf("new(): val=%v !26", strVal)
+	}
+	binData := val.ToByte()
+	if len(binData) != 8 {
+		sf.t.Fatalf("new(): len=%v !8", len(binData))
+	}
+	resInt := val.FromByte(binData)
+	resInt.Hassert("FromByte")
+
+	binData = binData[:2]
+	resInt = val.FromByte(binData)
+	if !resStr.IsErr() {
+		sf.t.Fatalf("new(): err==nil")
+	}
+
+	resInt = val.FromByte([]byte("travolta"))
+	if !resStr.IsErr() {
+		sf.t.Fatalf("new(): err==nil")
+	}
+
+	valBool := val.FromBool(true)
+	if valBool != -1 {
+		sf.t.Fatalf("new(): isVal==false")
+	}
+
+	valBool = val.FromBool(false)
+	if valBool != 0 {
+		sf.t.Fatalf("new(): isVal==true")
+	}
+	val.Set(3)
+	isBool := val.ToBool()
+	if !isBool {
+		sf.t.Fatalf("new(): isBool==false")
+	}
+
+	_ = os.Unsetenv("TEST_VAL")
+	_ = os.Setenv("TEST_VAL", "57")
+	resInt = val.Getenv("TEST_VAL")
+	resInt.Hassert("get env")
+	if resInt.Val() != 57 {
+		sf.t.Fatalf("new(): isVal==true")
+	}
+
+	_ = os.Unsetenv("TEST_VAL")
+	_ = os.Setenv("TEST_VAL", "u578")
+	resInt = val.Getenv("TEST_VAL")
+	if resInt.IsOk() {
+		sf.t.Fatalf("new(): ok==true")
+	}
+	if val.Get() != 57 {
+		sf.t.Fatalf("new(): val=%v !57", val.Get())
+	}
+
+	val.Inc()
+	if val.Get() != 58 {
+		sf.t.Fatalf("new(): val=%v !58", val.Get())
+	}
+	val.Dec()
+	if val.Get() != 57 {
+		sf.t.Fatalf("new(): val=%v !57", val.Get())
+	}
+}

+ 1 - 2
v3/krn/kmodule/kmodule.go

@@ -35,11 +35,10 @@ func NewKernelModule(name AModuleName) IKernelModule {
 		ctx:       local_ctx.NewLocalCtx(kCtx.Ctx()),
 		name:      name,
 		bus:       kbus_local.GetKernelBusLocal(),
-		timePhase: safe_int.NewSafeInt(),
+		timePhase: safe_int.NewSafeInt(1000), // 1000 msec
 		strLive:   safe_string.NewSafeString(),
 		stat:      mod_stat.NewModStat(name),
 	}
-	sf.timePhase.Set(1000) // 1000 msec
 	go sf.sigLive()
 	return sf
 }

+ 1 - 2
v3/krn/kmodule/mod_stat/mod_stat.go

@@ -35,10 +35,9 @@ func NewModStat(name AModuleName) *ModStat {
 		statSec:    mod_stat_sec.NewModStatSec(),
 		statMin:    mod_stat_day.NewModStatDay(),
 		statDay:    mod_stat_day.NewModStatDay(),
-		timeMinute: safe_int.NewSafeInt(),
+		timeMinute: safe_int.NewSafeInt(60 * 1000),
 		name:       name,
 	}
-	sf.timeMinute.Set(60 * 1000)
 	go sf.eventMinute()
 	return sf
 }

+ 29 - 0
v3/krn/ktypes/ikernel_int.go

@@ -0,0 +1,29 @@
+package ktypes
+
+// Int -- целочисленный тип ядра
+type Int interface {
+	// Get -- возвращает хранимое значение потокобезопасной переменной
+	Get() int
+	// Set -- устанавливает хранимое потокобезопасное значение
+	Set(int)
+	// Reset -- сбрасывает хранимое потокобезопасное значение
+	Reset()
+	// Inc -- увеличивает число на 1
+	Inc()
+	// Dec -- уменьшает число на 1
+	Dec()
+	// FromStr -- устанавливает значение из строки
+	FromStr(string) Result[int]
+	// ToStr -- возвращает как строку
+	ToStr() string
+	// FromByte -- устанавливает значение из байтов
+	FromByte([]byte) Result[int]
+	// ToByte -- возвращает как срез байт
+	ToByte() []byte
+	// FromBool -- устанавливает значение из булева
+	FromBool(bool) int
+	// ToBool -- возвращает как булево значение
+	ToBool() bool
+	// Getenv -- устанавливает значение из окружения
+	Getenv(string) Result[int]
+}

+ 5 - 10
v3/krn/ktypes/isafe_int.go

@@ -2,14 +2,9 @@ package ktypes
 
 // ISafeInt -- интерфейс к потокобезопасной переменной
 type ISafeInt interface {
-	// Get -- возвращает хранимое значение потокобезопасной переменной
-	Get() int
-	// Set -- устанавливает хранимое потокобезопасное значение
-	Set(int)
-	// Reset -- сбрасывает хранимое потокобезопасное значение
-	Reset()
-	// FromStr -- устанавливет значение из строки
-	FromStr(string) Result[int]
-	// Getenv -- устанавливает зачение из окружения
-	Getenv(string) Result[int]
+	Int
+	// Lock -- захватывает переменную
+	Lock()
+	// Unlock -- отпускает переменную
+	Unlock()
 }