package zordfsdb import ( "fmt" "os" "path" "strings" "time" abcex "g.arns.lt/zordsdavini/abcex/v4" ) type GetNodes interface { GetNodes() map[string]Node } type DB struct { Root string Nodes map[string]Node } type Node struct { Key string Value string Nodes map[string]Node Object bool List bool } func (db *DB) GetNodes() map[string]Node { return db.Nodes } func (node *Node) GetNodes() map[string]Node { return node.Nodes } func InitDB(root string) (DB, error) { db := DB{Root: root} err := db.Refresh() return db, err } func (db *DB) Refresh() error { db.Nodes = make(map[string]Node) files, err := os.ReadDir(db.Root) if err != nil { return err } for _, file := range files { node := Node{Key: file.Name()} node.Nodes = make(map[string]Node) if file.IsDir() { node, err = readDir(db.Root, node) if err != nil { return err } } else { b, err := os.ReadFile(path.Join(db.Root, file.Name())) if err != nil { return err } node.Value = strings.Trim(string(b), "\n") } db.Nodes[file.Name()] = node } return nil } func readDir(root string, node Node) (Node, error) { newRoot := path.Join(root, node.Key) files, err := os.ReadDir(newRoot) if err != nil { return node, err } for _, file := range files { child := Node{Key: file.Name()} child.Nodes = make(map[string]Node) if file.IsDir() { child, err = readDir(newRoot, child) if err != nil { return node, err } } else { b, err := os.ReadFile(path.Join(newRoot, file.Name())) if err != nil { return node, err } child.Value = strings.Trim(string(b), "\n") } node.Nodes[file.Name()] = child } node.FixType() return node, nil } func (node *Node) FixType() { node.List = false node.Object = false for _, child := range node.Nodes { if child.Object { node.List = true break } node.Object = true break } } func (db *DB) Keys(vpath string) []string { keys := []string{} fullPath := []string{db.Root} fullPath = append(fullPath, strings.Split(vpath, ".")...) root := path.Join(fullPath...) files, err := os.ReadDir(root) if err != nil { return keys } for _, file := range files { keys = append(keys, file.Name()) } return keys } func (db *DB) GetNode(vpath string) (Node, bool) { nodes := db.Nodes current := Node{} STEP_LOOP: for _, step := range strings.Split(vpath, ".") { for _, node := range nodes { if step == node.Key { nodes = node.Nodes current = node continue STEP_LOOP } } return current, false } return current, true } func (db *DB) Get(vpath string) (string, bool) { node, found := db.GetNode(vpath) if !found { return "", false } return node.Value, true } func (db *DB) Inc(vpath string) bool { fullPath := []string{db.Root} fullPath = append(fullPath, strings.Split(vpath, ".")...) val, found := db.Get(vpath) if !found { val = "0" } valAbc := abcex.Decode(val, abcex.BASE62) valAbc++ val = abcex.Encode(valAbc, abcex.BASE62) os.WriteFile(path.Join(fullPath...), []byte(string(val)), 0644) err := db.Refresh() if err != nil { return false } return true } func (db *DB) Dec(vpath string) bool { fullPath := []string{db.Root} fullPath = append(fullPath, strings.Split(vpath, ".")...) val, found := db.Get(vpath) if !found { val = "0" } valAbc := abcex.Decode(val, abcex.BASE62) valAbc-- val = abcex.Encode(valAbc, abcex.BASE62) os.WriteFile(path.Join(fullPath...), []byte(string(val)), 0644) err := db.Refresh() if err != nil { return false } return true } func (db *DB) Now(vpath string) bool { fullPath := []string{db.Root} fullPath = append(fullPath, strings.Split(vpath, ".")...) now := time.Now() formatted := now.Format(time.RFC3339) os.WriteFile(path.Join(fullPath...), []byte(formatted), 0644) err := db.Refresh() if err != nil { return false } return true } func (db *DB) Save(vpath string, value string) bool { fullPath := []string{db.Root} fullPath = append(fullPath, strings.Split(vpath, ".")...) err := os.WriteFile(path.Join(fullPath...), []byte(value), 0644) if err != nil { return false } err = db.Refresh() if err != nil { return false } return true } func (db *DB) Del(vpath string) bool { fullPath := []string{db.Root} fullPath = append(fullPath, strings.Split(vpath, ".")...) os.RemoveAll(path.Join(fullPath...)) err := db.Refresh() if err != nil { return false } return true } func (db *DB) CreateNode(vpath string) bool { fullPath := []string{db.Root} fullPath = append(fullPath, strings.Split(vpath, ".")...) err := os.Mkdir(path.Join(fullPath...), 0750) if err != nil { return false } err = db.Refresh() if err != nil { return false } return true } func (db *DB) AddObject(vpath string) (string, error) { fullPath := []string{db.Root} fullPath = append(fullPath, strings.Split(vpath, ".")...) root := path.Join(fullPath...) ids, err := os.ReadDir(root) if err != nil { return "", err } maxId := int64(0) notEmpty := false for _, id := range ids { idInt := abcex.Decode(id.Name(), abcex.BASE62) if maxId <= idInt { maxId = idInt notEmpty = true } } if notEmpty { maxId++ } fullPath = append(fullPath, abcex.Encode(maxId, abcex.BASE62)) fmt.Println(fullPath, maxId, abcex.Encode(maxId, abcex.BASE62)) err = os.Mkdir(path.Join(fullPath...), 0750) if err != nil { return "", err } err = db.Refresh() if err != nil { return "", err } return abcex.Encode(maxId, abcex.BASE62), nil }