Commit and run
This commit is contained in:
		
							
								
								
									
										267
									
								
								bolt_model.go
									
									
									
									
									
								
							
							
						
						
									
										267
									
								
								bolt_model.go
									
									
									
									
									
								
							| @@ -5,6 +5,7 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |   "bytes" | ||||||
|  |  | ||||||
| 	"github.com/boltdb/bolt" | 	"github.com/boltdb/bolt" | ||||||
| ) | ) | ||||||
| @@ -16,11 +17,17 @@ type BoltDB struct { | |||||||
| 	buckets []BoltBucket | 	buckets []BoltBucket | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type PathNode struct { | ||||||
|  |   name []byte | ||||||
|  |   dataType Datatype | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| BoltBucket is just a struct representation of a Bucket in the Bolt DB | BoltBucket is just a struct representation of a Bucket in the Bolt DB | ||||||
| */ | */ | ||||||
| type BoltBucket struct { | type BoltBucket struct { | ||||||
| 	name      string | 	name         []byte | ||||||
|  | 	nameDatatype Datatype | ||||||
| 	pairs        []BoltPair | 	pairs        []BoltPair | ||||||
| 	buckets      []BoltBucket | 	buckets      []BoltBucket | ||||||
| 	parent       *BoltBucket | 	parent       *BoltBucket | ||||||
| @@ -28,17 +35,52 @@ type BoltBucket struct { | |||||||
| 	errorFlag    bool | 	errorFlag    bool | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (b *BoltBucket) SetName(nm []byte) { | ||||||
|  |   b.name = nm | ||||||
|  |   for _, dtk := range dataTypeNameSlice { | ||||||
|  |     if _, err := datatypes[dtk].ToString(nm); err == nil { | ||||||
|  |       b.nameDatatype = datatypes[dtk] | ||||||
|  |       break | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| BoltPair is just a struct representation of a Pair in the Bolt DB | BoltPair is just a struct representation of a Pair in the Bolt DB | ||||||
| */ | */ | ||||||
| type BoltPair struct { | type BoltPair struct { | ||||||
| 	parent      *BoltBucket | 	parent      *BoltBucket | ||||||
| 	key      string | 	key         []byte | ||||||
| 	val      string | 	val         []byte | ||||||
| 	dataType *Datatype | 	keyDatatype Datatype | ||||||
|  | 	valDatatype Datatype | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) getGenericFromPath(path []string) (*BoltBucket, *BoltPair, error) { | func NewBoltPair(parent *BoltBucket, key, val []byte) *BoltPair { | ||||||
|  |   tp := BoltPair{ | ||||||
|  |     key:         key, | ||||||
|  |     val:         val, | ||||||
|  |   } | ||||||
|  |   for _, dtk := range dataTypeNameSlice { | ||||||
|  |     if _, err := datatypes[dtk].ToString(key); err == nil { | ||||||
|  |       tp.keyDatatype = datatypes[dtk] | ||||||
|  |       break | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   for _, dtk := range dataTypeNameSlice { | ||||||
|  |     if _, err := datatypes[dtk].ToString(val); err == nil { | ||||||
|  |       tp.valDatatype = datatypes[dtk] | ||||||
|  |       break | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return &tp | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (bd *BoltDB) getGenericFromStringPath(path []string) (*BoltBucket, *BoltPair, error) { | ||||||
|  |   return bd.getGenericFromPath(stringPathToBytePath(path)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (bd *BoltDB) getGenericFromPath(path []PathNode) (*BoltBucket, *BoltPair, error) { | ||||||
| 	// Check if 'path' leads to a pair | 	// Check if 'path' leads to a pair | ||||||
| 	p, err := bd.getPairFromPath(path) | 	p, err := bd.getPairFromPath(path) | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| @@ -53,19 +95,19 @@ func (bd *BoltDB) getGenericFromPath(path []string) (*BoltBucket, *BoltPair, err | |||||||
| 	return nil, nil, errors.New("Invalid Path") | 	return nil, nil, errors.New("Invalid Path") | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) getBucketFromPath(path []string) (*BoltBucket, error) { | func (bd *BoltDB) getBucketFromPath(path []PathNode) (*BoltBucket, error) { | ||||||
| 	if len(path) > 0 { | 	if len(path) > 0 { | ||||||
| 		// Find the BoltBucket with a path == path | 		// Find the BoltBucket with a path == path | ||||||
| 		var b *BoltBucket | 		var b *BoltBucket | ||||||
| 		var err error | 		var err error | ||||||
| 		// Find the root bucket | 		// Find the root bucket | ||||||
| 		b, err = memBolt.getBucket(path[0]) | 		b, err = memBolt.getBucket(path[0].name) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| 		if len(path) > 1 { | 		if len(path) > 1 { | ||||||
| 			for p := 1; p < len(path); p++ { | 			for p := 1; p < len(path); p++ { | ||||||
| 				b, err = b.getBucket(path[p]) | 				b, err = b.getBucket(path[p].name) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					return nil, err | 					return nil, err | ||||||
| 				} | 				} | ||||||
| @@ -76,7 +118,7 @@ func (bd *BoltDB) getBucketFromPath(path []string) (*BoltBucket, error) { | |||||||
| 	return nil, errors.New("Invalid Path") | 	return nil, errors.New("Invalid Path") | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) getPairFromPath(path []string) (*BoltPair, error) { | func (bd *BoltDB) getPairFromPath(path []PathNode) (*BoltPair, error) { | ||||||
| 	if len(path) <= 0 { | 	if len(path) <= 0 { | ||||||
| 		return nil, errors.New("No Path") | 		return nil, errors.New("No Path") | ||||||
| 	} | 	} | ||||||
| @@ -85,11 +127,11 @@ func (bd *BoltDB) getPairFromPath(path []string) (*BoltPair, error) { | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	// Found the bucket, pull out the pair | 	// Found the bucket, pull out the pair | ||||||
| 	p, err := b.getPair(path[len(path)-1]) | 	p, err := b.getPair(path[len(path)-1].name) | ||||||
| 	return p, err | 	return p, err | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) getVisibleItemCount(path []string) (int, error) { | func (bd *BoltDB) getVisibleItemCount(path []PathNode) (int, error) { | ||||||
| 	vis := 0 | 	vis := 0 | ||||||
| 	var retErr error | 	var retErr error | ||||||
| 	if len(path) == 0 { | 	if len(path) == 0 { | ||||||
| @@ -124,12 +166,12 @@ func (bd *BoltDB) getVisibleItemCount(path []string) (int, error) { | |||||||
| 	return vis, retErr | 	return vis, retErr | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) buildVisiblePathSlice() ([][]string, error) { | func (bd *BoltDB) buildVisiblePathSlice() ([][]PathNode, error) { | ||||||
| 	var retSlice [][]string | 	var retSlice [][]string | ||||||
| 	var retErr error | 	var retErr error | ||||||
| 	// The root path, recurse for root buckets | 	// The root path, recurse for root buckets | ||||||
| 	for i := range bd.buckets { | 	for i := range bd.buckets { | ||||||
| 		bktS, bktErr := bd.buckets[i].buildVisiblePathSlice([]string{}) | 		bktS, bktErr := bd.buckets[i].buildVisiblePathSlice([]PathNode{}) | ||||||
| 		if bktErr == nil { | 		if bktErr == nil { | ||||||
| 			retSlice = append(retSlice, bktS...) | 			retSlice = append(retSlice, bktS...) | ||||||
| 		} else { | 		} else { | ||||||
| @@ -140,7 +182,7 @@ func (bd *BoltDB) buildVisiblePathSlice() ([][]string, error) { | |||||||
| 	return retSlice, retErr | 	return retSlice, retErr | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) getPrevVisiblePath(path []string) []string { | func (bd *BoltDB) getPrevVisiblePath(path []PathNode) []PathNode { | ||||||
| 	visPaths, err := bd.buildVisiblePathSlice() | 	visPaths, err := bd.buildVisiblePathSlice() | ||||||
| 	if path == nil { | 	if path == nil { | ||||||
| 		if len(visPaths) > 0 { | 		if len(visPaths) > 0 { | ||||||
| @@ -152,7 +194,7 @@ func (bd *BoltDB) getPrevVisiblePath(path []string) []string { | |||||||
| 		for idx, pth := range visPaths { | 		for idx, pth := range visPaths { | ||||||
| 			isCurPath := true | 			isCurPath := true | ||||||
| 			for i := range path { | 			for i := range path { | ||||||
| 				if len(pth) <= i || path[i] != pth[i] { | 				if len(pth) <= i || !bytes.Equal(path[i].name, pth[i].name) { | ||||||
| 					isCurPath = false | 					isCurPath = false | ||||||
| 					break | 					break | ||||||
| 				} | 				} | ||||||
| @@ -164,7 +206,7 @@ func (bd *BoltDB) getPrevVisiblePath(path []string) []string { | |||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| func (bd *BoltDB) getNextVisiblePath(path []string) []string { | func (bd *BoltDB) getNextVisiblePath(path []PathNode) []PathNode { | ||||||
| 	visPaths, err := bd.buildVisiblePathSlice() | 	visPaths, err := bd.buildVisiblePathSlice() | ||||||
| 	if path == nil { | 	if path == nil { | ||||||
| 		if len(visPaths) > 0 { | 		if len(visPaths) > 0 { | ||||||
| @@ -176,7 +218,7 @@ func (bd *BoltDB) getNextVisiblePath(path []string) []string { | |||||||
| 		for idx, pth := range visPaths { | 		for idx, pth := range visPaths { | ||||||
| 			isCurPath := true | 			isCurPath := true | ||||||
| 			for i := range path { | 			for i := range path { | ||||||
| 				if len(pth) <= i || path[i] != pth[i] { | 				if len(pth) <= i || !bytes.Equal(path[i].name, pth[i].name) { | ||||||
| 					isCurPath = false | 					isCurPath = false | ||||||
| 					break | 					break | ||||||
| 				} | 				} | ||||||
| @@ -189,7 +231,7 @@ func (bd *BoltDB) getNextVisiblePath(path []string) []string { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) toggleOpenBucket(path []string) error { | func (bd *BoltDB) toggleOpenBucket(path []PathNode) error { | ||||||
| 	// Find the BoltBucket with a path == path | 	// Find the BoltBucket with a path == path | ||||||
| 	b, err := bd.getBucketFromPath(path) | 	b, err := bd.getBucketFromPath(path) | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| @@ -198,7 +240,7 @@ func (bd *BoltDB) toggleOpenBucket(path []string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) closeBucket(path []string) error { | func (bd *BoltDB) closeBucket(path []PathNode) error { | ||||||
| 	// Find the BoltBucket with a path == path | 	// Find the BoltBucket with a path == path | ||||||
| 	b, err := bd.getBucketFromPath(path) | 	b, err := bd.getBucketFromPath(path) | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| @@ -207,7 +249,7 @@ func (bd *BoltDB) closeBucket(path []string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) openBucket(path []string) error { | func (bd *BoltDB) openBucket(path []PathNode) error { | ||||||
| 	// Find the BoltBucket with a path == path | 	// Find the BoltBucket with a path == path | ||||||
| 	b, err := bd.getBucketFromPath(path) | 	b, err := bd.getBucketFromPath(path) | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| @@ -216,9 +258,9 @@ func (bd *BoltDB) openBucket(path []string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func (bd *BoltDB) getBucket(k string) (*BoltBucket, error) { | func (bd *BoltDB) getBucket(k []byte) (*BoltBucket, error) { | ||||||
| 	for i := range bd.buckets { | 	for i := range bd.buckets { | ||||||
| 		if bd.buckets[i].name == k { |     if bytes.Equal(bd.buckets[i].name, k) { | ||||||
| 			return &bd.buckets[i], nil | 			return &bd.buckets[i], nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -236,7 +278,7 @@ func (bd *BoltDB) syncOpenBuckets(shadow *BoltDB) { | |||||||
| 	// First test this bucket | 	// First test this bucket | ||||||
| 	for i := range bd.buckets { | 	for i := range bd.buckets { | ||||||
| 		for j := range shadow.buckets { | 		for j := range shadow.buckets { | ||||||
| 			if bd.buckets[i].name == shadow.buckets[j].name { |       if bytes.Equal(bd.buckets[i].name, shadow.buckets[j].name) { | ||||||
| 				bd.buckets[i].syncOpenBuckets(&shadow.buckets[j]) | 				bd.buckets[i].syncOpenBuckets(&shadow.buckets[j]) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -250,7 +292,7 @@ func (bd *BoltDB) refreshDatabase() *BoltDB { | |||||||
| 		return tx.ForEach(func(nm []byte, b *bolt.Bucket) error { | 		return tx.ForEach(func(nm []byte, b *bolt.Bucket) error { | ||||||
| 			bb, err := readBucket(b) | 			bb, err := readBucket(b) | ||||||
| 			if err == nil { | 			if err == nil { | ||||||
| 				bb.name = string(nm) |         bb.SetName(nm) | ||||||
| 				bb.expanded = false | 				bb.expanded = false | ||||||
| 				memBolt.buckets = append(memBolt.buckets, *bb) | 				memBolt.buckets = append(memBolt.buckets, *bb) | ||||||
| 				return nil | 				return nil | ||||||
| @@ -262,27 +304,40 @@ func (bd *BoltDB) refreshDatabase() *BoltDB { | |||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| GetPath returns the database path leading to this BoltBucket | GetStringName returns the name of the bucket after passing it through it's | ||||||
|  | Datatype ToString function | ||||||
| */ | */ | ||||||
| func (b *BoltBucket) GetPath() []string { | func (b *BoltBucket) GetStringName() string { | ||||||
| 	if b.parent != nil { |   ret, err := b.nameDatatype.ToString(b.name) | ||||||
| 		return append(b.parent.GetPath(), b.name) |   if err != nil { | ||||||
|  |     return stringify(b.name) | ||||||
|   } |   } | ||||||
| 	return []string{b.name} |   return ret | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| buildVisiblePathSlice builds a slice of string slices containing all visible paths in this bucket | GetPath returns the database path leading to this BoltBucket | ||||||
|  | */ | ||||||
|  | func (b *BoltBucket) GetPath() [][]byte { | ||||||
|  | 	if b.parent != nil { | ||||||
|  | 		return append(b.parent.GetPath(), b.name) | ||||||
|  | 	} | ||||||
|  | 	return [][]byte{b.name} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | buildVisiblePathSlice builds a slice of PathNode slices containing all visible paths in this bucket | ||||||
| The passed prefix is the path leading to the current bucket | The passed prefix is the path leading to the current bucket | ||||||
| */ | */ | ||||||
| func (b *BoltBucket) buildVisiblePathSlice(prefix []string) ([][]string, error) { | func (b *BoltBucket) buildVisiblePathSlice(prefix []PathNode) ([][]PathNode, error) { | ||||||
| 	var retSlice [][]string | 	var retSlice [][]PathNode | ||||||
| 	var retErr error | 	var retErr error | ||||||
| 	retSlice = append(retSlice, append(prefix, b.name)) |   bucketNode := PathNode{b.name, b.nameDatatype} | ||||||
|  | 	retSlice = append(retSlice, append(prefix, bucketNode)) | ||||||
| 	if b.expanded { | 	if b.expanded { | ||||||
| 		// Add subbuckets | 		// Add subbuckets | ||||||
| 		for i := range b.buckets { | 		for i := range b.buckets { | ||||||
| 			bktS, bktErr := b.buckets[i].buildVisiblePathSlice(append(prefix, b.name)) | 			bktS, bktErr := b.buckets[i].buildVisiblePathSlice(append(prefix, bucketNode)) | ||||||
| 			if bktErr != nil { | 			if bktErr != nil { | ||||||
| 				return retSlice, bktErr | 				return retSlice, bktErr | ||||||
| 			} | 			} | ||||||
| @@ -290,7 +345,7 @@ func (b *BoltBucket) buildVisiblePathSlice(prefix []string) ([][]string, error) | |||||||
| 		} | 		} | ||||||
| 		// Add pairs | 		// Add pairs | ||||||
| 		for i := range b.pairs { | 		for i := range b.pairs { | ||||||
| 			retSlice = append(retSlice, append(append(prefix, b.name), b.pairs[i].key)) | 			retSlice = append(retSlice, append(append(prefix, bucketNode, PathNode{b.pairs[i].key, b.pairs[i].keyDatatype}))) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return retSlice, retErr | 	return retSlice, retErr | ||||||
| @@ -301,7 +356,7 @@ func (b *BoltBucket) syncOpenBuckets(shadow *BoltBucket) { | |||||||
| 	b.expanded = shadow.expanded | 	b.expanded = shadow.expanded | ||||||
| 	for i := range b.buckets { | 	for i := range b.buckets { | ||||||
| 		for j := range shadow.buckets { | 		for j := range shadow.buckets { | ||||||
| 			if b.buckets[i].name == shadow.buckets[j].name { |       if bytes.Equal(b.buckets[i].name, shadow.buckets[j].name) { | ||||||
| 				b.buckets[i].syncOpenBuckets(&shadow.buckets[j]) | 				b.buckets[i].syncOpenBuckets(&shadow.buckets[j]) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -315,28 +370,50 @@ func (b *BoltBucket) openAllBuckets() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *BoltBucket) getBucket(k string) (*BoltBucket, error) { | func (b *BoltBucket) getBucket(k []byte) (*BoltBucket, error) { | ||||||
| 	for i := range b.buckets { | 	for i := range b.buckets { | ||||||
| 		if b.buckets[i].name == k { | 		if bytes.Equal(b.buckets[i].name, k) { | ||||||
| 			return &b.buckets[i], nil | 			return &b.buckets[i], nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return nil, errors.New("Bucket Not Found") | 	return nil, errors.New("Bucket Not Found") | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *BoltBucket) getPair(k string) (*BoltPair, error) { | func (b *BoltBucket) getPair(k []byte) (*BoltPair, error) { | ||||||
| 	for i := range b.pairs { | 	for i := range b.pairs { | ||||||
| 		if b.pairs[i].key == k { | 		if bytes.Equal(b.pairs[i].key, k) { | ||||||
| 			return &b.pairs[i], nil | 			return &b.pairs[i], nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return nil, errors.New("Pair Not Found") | 	return nil, errors.New("Pair Not Found") | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | GetStringKey returns the key of the pair after passing it through it's | ||||||
|  | Datatype ToString function | ||||||
|  | */ | ||||||
|  | func (p *BoltPair) GetStringKey() string { | ||||||
|  |   ret, err := p.keyDatatype.ToString(p.key) | ||||||
|  |   if err != nil { | ||||||
|  |     return stringify(p.key) | ||||||
|  |   } | ||||||
|  |   return ret | ||||||
|  | } | ||||||
|  | /* | ||||||
|  | GetStringVal returns the val of the pair after passing it through it's | ||||||
|  | Datatype ToString function | ||||||
|  | */ | ||||||
|  | func (p *BoltPair) GetStringVal() string { | ||||||
|  |   ret, err := p.valDatatype.ToString(p.val) | ||||||
|  |   if err != nil { | ||||||
|  |     return stringify(p.val) | ||||||
|  |   } | ||||||
|  |   return ret | ||||||
|  | } | ||||||
| /* | /* | ||||||
| GetPath Returns the path of the BoltPair | GetPath Returns the path of the BoltPair | ||||||
| */ | */ | ||||||
| func (p *BoltPair) GetPath() []string { | func (p *BoltPair) GetPath() [][]byte { | ||||||
| 	return append(p.parent.GetPath(), p.key) | 	return append(p.parent.GetPath(), p.key) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -347,7 +424,7 @@ func (p *BoltPair) GetPath() []string { | |||||||
|  * Mainly used for moving a bucket from one path to another |  * Mainly used for moving a bucket from one path to another | ||||||
|  * as in the 'renameBucket' function below. |  * as in the 'renameBucket' function below. | ||||||
|  */ |  */ | ||||||
| func addBucketFromBoltBucket(path []string, bb *BoltBucket) error { | func addBucketFromBoltBucket(path [][]byte, bb *BoltBucket) error { | ||||||
| 	if err := insertBucket(path, bb.name); err == nil { | 	if err := insertBucket(path, bb.name); err == nil { | ||||||
| 		bucketPath := append(path, bb.name) | 		bucketPath := append(path, bb.name) | ||||||
| 		for i := range bb.pairs { | 		for i := range bb.pairs { | ||||||
| @@ -364,7 +441,7 @@ func addBucketFromBoltBucket(path []string, bb *BoltBucket) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func deleteKey(path []string) error { | func deleteKey(path [][]byte) error { | ||||||
| 	if AppArgs.ReadOnly { | 	if AppArgs.ReadOnly { | ||||||
| 		return errors.New("DB is in Read-Only Mode") | 		return errors.New("DB is in Read-Only Mode") | ||||||
| 	} | 	} | ||||||
| @@ -373,13 +450,13 @@ func deleteKey(path []string) error { | |||||||
| 		// the rest are buckets leading to that key | 		// the rest are buckets leading to that key | ||||||
| 		if len(path) == 1 { | 		if len(path) == 1 { | ||||||
| 			// Deleting a root bucket | 			// Deleting a root bucket | ||||||
| 			return tx.DeleteBucket([]byte(path[0])) | 			return tx.DeleteBucket(path[0]) | ||||||
| 		} | 		} | ||||||
| 		b := tx.Bucket([]byte(path[0])) | 		b := tx.Bucket(path[0]) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			if len(path) > 1 { | 			if len(path) > 1 { | ||||||
| 				for i := range path[1 : len(path)-1] { | 				for i := range path[1 : len(path)-1] { | ||||||
| 					b = b.Bucket([]byte(path[i+1])) | 					b = b.Bucket(path[i+1]) | ||||||
| 					if b == nil { | 					if b == nil { | ||||||
| 						return errors.New("deleteKey: Invalid Path") | 						return errors.New("deleteKey: Invalid Path") | ||||||
| 					} | 					} | ||||||
| @@ -387,11 +464,11 @@ func deleteKey(path []string) error { | |||||||
| 			} | 			} | ||||||
| 			// Now delete the last key in the path | 			// Now delete the last key in the path | ||||||
| 			var err error | 			var err error | ||||||
| 			if deleteBkt := b.Bucket([]byte(path[len(path)-1])); deleteBkt == nil { | 			if deleteBkt := b.Bucket(path[len(path)-1]); deleteBkt == nil { | ||||||
| 				// Must be a pair | 				// Must be a pair | ||||||
| 				err = b.Delete([]byte(path[len(path)-1])) | 				err = b.Delete(path[len(path)-1]) | ||||||
| 			} else { | 			} else { | ||||||
| 				err = b.DeleteBucket([]byte(path[len(path)-1])) | 				err = b.DeleteBucket(path[len(path)-1]) | ||||||
| 			} | 			} | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| @@ -400,6 +477,8 @@ func deleteKey(path []string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Recursively read a bucket and pairs from the DB | ||||||
|  | // We assume all datatypes are string | ||||||
| func readBucket(b *bolt.Bucket) (*BoltBucket, error) { | func readBucket(b *bolt.Bucket) (*BoltBucket, error) { | ||||||
| 	bb := new(BoltBucket) | 	bb := new(BoltBucket) | ||||||
| 	b.ForEach(func(k, v []byte) error { | 	b.ForEach(func(k, v []byte) error { | ||||||
| @@ -407,21 +486,19 @@ func readBucket(b *bolt.Bucket) (*BoltBucket, error) { | |||||||
| 			tb, err := readBucket(b.Bucket(k)) | 			tb, err := readBucket(b.Bucket(k)) | ||||||
| 			tb.parent = bb | 			tb.parent = bb | ||||||
| 			if err == nil { | 			if err == nil { | ||||||
| 				tb.name = string(k) |         tb.SetName(k) | ||||||
| 				bb.buckets = append(bb.buckets, *tb) | 				bb.buckets = append(bb.buckets, *tb) | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			tp := BoltPair{key: string(k), val: string(v)} | 			bb.pairs = append(bb.pairs, *NewBoltPair(bb, k, v)) | ||||||
| 			tp.parent = bb |  | ||||||
| 			bb.pairs = append(bb.pairs, tp) |  | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
| 	}) | 	}) | ||||||
| 	return bb, nil | 	return bb, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func renameBucket(path []string, name string) error { | func renameBucket(path [][]byte, name []byte) error { | ||||||
| 	if name == path[len(path)-1] { | 	if bytes.Equal(name, path[len(path)-1]) { | ||||||
| 		// No change requested | 		// No change requested | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| @@ -429,11 +506,11 @@ func renameBucket(path []string, name string) error { | |||||||
| 	err := db.View(func(tx *bolt.Tx) error { | 	err := db.View(func(tx *bolt.Tx) error { | ||||||
| 		// len(b.path)-1 is the key we need to delete, | 		// len(b.path)-1 is the key we need to delete, | ||||||
| 		// the rest are buckets leading to that key | 		// the rest are buckets leading to that key | ||||||
| 		b := tx.Bucket([]byte(path[0])) | 		b := tx.Bucket(path[0]) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			if len(path) > 1 { | 			if len(path) > 1 { | ||||||
| 				for i := range path[1:len(path)] { | 				for i := range path[1:len(path)] { | ||||||
| 					b = b.Bucket([]byte(path[i+1])) | 					b = b.Bucket(path[i+1]) | ||||||
| 					if b == nil { | 					if b == nil { | ||||||
| 						return errors.New("renameBucket: Invalid Path") | 						return errors.New("renameBucket: Invalid Path") | ||||||
| 					} | 					} | ||||||
| @@ -462,7 +539,7 @@ func renameBucket(path []string, name string) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	// Rechristen our cached bucket | 	// Rechristen our cached bucket | ||||||
| 	bb.name = name |   bb.SetName(name) | ||||||
| 	// And re-add it | 	// And re-add it | ||||||
|  |  | ||||||
| 	parentPath := path[:len(path)-1] | 	parentPath := path[:len(path)-1] | ||||||
| @@ -472,29 +549,29 @@ func renameBucket(path []string, name string) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func updatePairKey(path []string, k string) error { | func updatePairKey(path [][]byte, k []byte) error { | ||||||
| 	if AppArgs.ReadOnly { | 	if AppArgs.ReadOnly { | ||||||
| 		return errors.New("DB is in Read-Only Mode") | 		return errors.New("DB is in Read-Only Mode") | ||||||
| 	} | 	} | ||||||
| 	err := db.Update(func(tx *bolt.Tx) error { | 	err := db.Update(func(tx *bolt.Tx) error { | ||||||
| 		// len(b.path)-1 is the key for the pair we're updating, | 		// len(b.path)-1 is the key for the pair we're updating, | ||||||
| 		// the rest are buckets leading to that key | 		// the rest are buckets leading to that key | ||||||
| 		b := tx.Bucket([]byte(path[0])) | 		b := tx.Bucket(path[0]) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			if len(path) > 0 { | 			if len(path) > 0 { | ||||||
| 				for i := range path[1 : len(path)-1] { | 				for i := range path[1 : len(path)-1] { | ||||||
| 					b = b.Bucket([]byte(path[i+1])) | 					b = b.Bucket(path[i+1]) | ||||||
| 					if b == nil { | 					if b == nil { | ||||||
| 						return errors.New("updatePairValue: Invalid Path") | 						return errors.New("updatePairValue: Invalid Path") | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			bk := []byte(path[len(path)-1]) | 			bk := path[len(path)-1] | ||||||
| 			v := b.Get(bk) | 			v := b.Get(bk) | ||||||
| 			err := b.Delete(bk) | 			err := b.Delete(bk) | ||||||
| 			if err == nil { | 			if err == nil { | ||||||
| 				// Old pair has been deleted, now add the new one | 				// Old pair has been deleted, now add the new one | ||||||
| 				err = b.Put([]byte(k), v) | 				err = b.Put(k, v) | ||||||
| 			} | 			} | ||||||
| 			// Now update the last key in the path | 			// Now update the last key in the path | ||||||
| 			return err | 			return err | ||||||
| @@ -504,25 +581,25 @@ func updatePairKey(path []string, k string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func updatePairValue(path []string, v string) error { | func updatePairValue(path [][]byte, v []byte) error { | ||||||
| 	if AppArgs.ReadOnly { | 	if AppArgs.ReadOnly { | ||||||
| 		return errors.New("DB is in Read-Only Mode") | 		return errors.New("DB is in Read-Only Mode") | ||||||
| 	} | 	} | ||||||
| 	err := db.Update(func(tx *bolt.Tx) error { | 	err := db.Update(func(tx *bolt.Tx) error { | ||||||
| 		// len(b.GetPath())-1 is the key for the pair we're updating, | 		// len(b.GetPath())-1 is the key for the pair we're updating, | ||||||
| 		// the rest are buckets leading to that key | 		// the rest are buckets leading to that key | ||||||
| 		b := tx.Bucket([]byte(path[0])) | 		b := tx.Bucket(path[0]) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			if len(path) > 0 { | 			if len(path) > 0 { | ||||||
| 				for i := range path[1 : len(path)-1] { | 				for i := range path[1 : len(path)-1] { | ||||||
| 					b = b.Bucket([]byte(path[i+1])) | 					b = b.Bucket(path[i+1]) | ||||||
| 					if b == nil { | 					if b == nil { | ||||||
| 						return errors.New("updatePairValue: Invalid Path") | 						return errors.New("updatePairValue: Invalid Path") | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			// Now update the last key in the path | 			// Now update the last key in the path | ||||||
| 			err := b.Put([]byte(path[len(path)-1]), []byte(v)) | 			err := b.Put(path[len(path)-1], v) | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		return errors.New("updatePairValue: Invalid Path") | 		return errors.New("updatePairValue: Invalid Path") | ||||||
| @@ -530,7 +607,7 @@ func updatePairValue(path []string, v string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func insertBucket(path []string, n string) error { | func insertBucket(path [][]byte, n []byte) error { | ||||||
| 	if AppArgs.ReadOnly { | 	if AppArgs.ReadOnly { | ||||||
| 		return errors.New("DB is in Read-Only Mode") | 		return errors.New("DB is in Read-Only Mode") | ||||||
| 	} | 	} | ||||||
| @@ -538,18 +615,18 @@ func insertBucket(path []string, n string) error { | |||||||
| 	err := db.Update(func(tx *bolt.Tx) error { | 	err := db.Update(func(tx *bolt.Tx) error { | ||||||
| 		if len(path) == 0 { | 		if len(path) == 0 { | ||||||
| 			// insert at root | 			// insert at root | ||||||
| 			_, err := tx.CreateBucket([]byte(n)) | 			_, err := tx.CreateBucket(n) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return fmt.Errorf("insertBucket: %s", err) | 				return fmt.Errorf("insertBucket: %s", err) | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			rootBucket, path := path[0], path[1:] | 			rootBucket, path := path[0], path[1:] | ||||||
| 			b := tx.Bucket([]byte(rootBucket)) | 			b := tx.Bucket(rootBucket) | ||||||
| 			if b != nil { | 			if b != nil { | ||||||
| 				for len(path) > 0 { | 				for len(path) > 0 { | ||||||
| 					tstBucket := "" | 					var tstBucket []byte | ||||||
| 					tstBucket, path = path[0], path[1:] | 					tstBucket, path = path[0], path[1:] | ||||||
| 					nB := b.Bucket([]byte(tstBucket)) | 					nB := b.Bucket(tstBucket) | ||||||
| 					if nB == nil { | 					if nB == nil { | ||||||
| 						// Not a bucket, if we're out of path, just move on | 						// Not a bucket, if we're out of path, just move on | ||||||
| 						if len(path) != 0 { | 						if len(path) != 0 { | ||||||
| @@ -560,7 +637,7 @@ func insertBucket(path []string, n string) error { | |||||||
| 						b = nB | 						b = nB | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				_, err := b.CreateBucket([]byte(n)) | 				_, err := b.CreateBucket(n) | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 			return fmt.Errorf("insertBucket: Invalid Path %s", rootBucket) | 			return fmt.Errorf("insertBucket: Invalid Path %s", rootBucket) | ||||||
| @@ -570,7 +647,7 @@ func insertBucket(path []string, n string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func insertPair(path []string, k string, v string) error { | func insertPair(path [][]byte, k []byte, v []byte) error { | ||||||
| 	if AppArgs.ReadOnly { | 	if AppArgs.ReadOnly { | ||||||
| 		return errors.New("DB is in Read-Only Mode") | 		return errors.New("DB is in Read-Only Mode") | ||||||
| 	} | 	} | ||||||
| @@ -581,17 +658,17 @@ func insertPair(path []string, k string, v string) error { | |||||||
| 			return errors.New("insertPair: Cannot insert pair at root") | 			return errors.New("insertPair: Cannot insert pair at root") | ||||||
| 		} | 		} | ||||||
| 		var err error | 		var err error | ||||||
| 		b := tx.Bucket([]byte(path[0])) | 		b := tx.Bucket(path[0]) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			if len(path) > 0 { | 			if len(path) > 0 { | ||||||
| 				for i := 1; i < len(path); i++ { | 				for i := 1; i < len(path); i++ { | ||||||
| 					b = b.Bucket([]byte(path[i])) | 					b = b.Bucket(path[i]) | ||||||
| 					if b == nil { | 					if b == nil { | ||||||
| 						return fmt.Errorf("insertPair: %s", err) | 						return fmt.Errorf("insertPair: %s", err) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			err := b.Put([]byte(k), []byte(v)) | 			err := b.Put(k, v) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return fmt.Errorf("insertPair: %s", err) | 				return fmt.Errorf("insertPair: %s", err) | ||||||
| 			} | 			} | ||||||
| @@ -601,21 +678,37 @@ func insertPair(path []string, k string, v string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func exportValue(path []string, fName string) error { | func stringPathToBytePath(path []string) [][]byte { | ||||||
|  |   var ret [][]byte | ||||||
|  |   for _, v := range path { | ||||||
|  |     ret = append(ret, []byte(v)) | ||||||
|  |   } | ||||||
|  |   return ret | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func bytePathToStringPath(path [][]byte) []string { | ||||||
|  |   var ret []string | ||||||
|  |   for _, v := range path { | ||||||
|  |     ret = append(ret, string(v)) | ||||||
|  |   } | ||||||
|  |   return ret | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func exportValue(path [][]byte, fName string) error { | ||||||
| 	return db.View(func(tx *bolt.Tx) error { | 	return db.View(func(tx *bolt.Tx) error { | ||||||
| 		// len(b.path)-1 is the key whose value we want to export | 		// len(b.path)-1 is the key whose value we want to export | ||||||
| 		// the rest are buckets leading to that key | 		// the rest are buckets leading to that key | ||||||
| 		b := tx.Bucket([]byte(path[0])) | 		b := tx.Bucket(path[0]) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			if len(path) > 1 { | 			if len(path) > 1 { | ||||||
| 				for i := range path[1 : len(path)-1] { | 				for i := range path[1 : len(path)-1] { | ||||||
| 					b = b.Bucket([]byte(path[i+1])) | 					b = b.Bucket(path[i+1]) | ||||||
| 					if b == nil { | 					if b == nil { | ||||||
| 						return errors.New("exportValue: Invalid Path: " + strings.Join(path, "/")) | 						return errors.New("exportValue: Invalid Path: " + strings.Join(bytePathToStringPath(path), "/")) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			bk := []byte(path[len(path)-1]) | 			bk := path[len(path)-1] | ||||||
| 			v := b.Get(bk) | 			v := b.Get(bk) | ||||||
| 			return writeToFile(fName, string(v)+"\n", os.O_CREATE|os.O_WRONLY|os.O_TRUNC) | 			return writeToFile(fName, string(v)+"\n", os.O_CREATE|os.O_WRONLY|os.O_TRUNC) | ||||||
| 		} | 		} | ||||||
| @@ -623,21 +716,21 @@ func exportValue(path []string, fName string) error { | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| func exportJSON(path []string, fName string) error { | func exportJSON(path [][]byte, fName string) error { | ||||||
| 	return db.View(func(tx *bolt.Tx) error { | 	return db.View(func(tx *bolt.Tx) error { | ||||||
| 		// len(b.path)-1 is the key whose value we want to export | 		// len(b.path)-1 is the key whose value we want to export | ||||||
| 		// the rest are buckets leading to that key | 		// the rest are buckets leading to that key | ||||||
| 		b := tx.Bucket([]byte(path[0])) | 		b := tx.Bucket(path[0]) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			if len(path) > 1 { | 			if len(path) > 1 { | ||||||
| 				for i := range path[1 : len(path)-1] { | 				for i := range path[1 : len(path)-1] { | ||||||
| 					b = b.Bucket([]byte(path[i+1])) | 					b = b.Bucket(path[i+1]) | ||||||
| 					if b == nil { | 					if b == nil { | ||||||
| 						return errors.New("exportValue: Invalid Path: " + strings.Join(path, "/")) | 						return errors.New("exportValue: Invalid Path: " + strings.Join(bytePathToStringPath(path), "/")) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			bk := []byte(path[len(path)-1]) | 			bk := path[len(path)-1] | ||||||
| 			if v := b.Get(bk); v != nil { | 			if v := b.Get(bk); v != nil { | ||||||
| 				return writeToFile(fName, "{\""+string(bk)+"\":\""+string(v)+"\"}", os.O_CREATE|os.O_WRONLY|os.O_TRUNC) | 				return writeToFile(fName, "{\""+string(bk)+"\":\""+string(v)+"\"}", os.O_CREATE|os.O_WRONLY|os.O_TRUNC) | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -1,37 +1,39 @@ | |||||||
| package main | package main | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  |   "fmt" | ||||||
| 	"encoding/binary" | 	"encoding/binary" | ||||||
| 	"errors" |  | ||||||
| 	"strconv" | 	"strconv" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Datatype_Uint64 manages the uint64 data type | // Datatype_Int manages the int data type | ||||||
| // All conversions just use the binary package | type Datatype_Int64 struct{} | ||||||
| type Datatype_Uint64 struct{} |  | ||||||
|  |  | ||||||
| func (t *Datatype_Uint64) Name() string { | func (t *Datatype_Int64) Name() string { | ||||||
| 	return "uint64" | 	return "int" | ||||||
| } | } | ||||||
|  |  | ||||||
| func (t *Datatype_Uint64) ToString(data []byte) (string, error) { | func (t *Datatype_Int64) ToString(data []byte) (string, error) { | ||||||
| 	ret, bt := binary.Uvarint(data) |   return fmt.Sprintf("%d", t.btoi(data)), nil | ||||||
| 	if bt == 0 { |  | ||||||
| 		return "", errors.New("Byte Buffer too small") |  | ||||||
| 	} else if bt < 0 { |  | ||||||
| 		return "", errors.New("Value larger than 64 bits") |  | ||||||
| 	} |  | ||||||
| 	return strconv.FormatUint(ret, 10), nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (t *Datatype_Uint64) FromString(val string) ([]byte, error) { | func (t *Datatype_Int64) FromString(val string) ([]byte, error) { | ||||||
| 	var err error |   v, err := strconv.ParseInt(val, 10, 64) | ||||||
| 	var u uint64 |  | ||||||
| 	buf := make([]byte, binary.MaxVarintLen64) |  | ||||||
| 	u, err = strconv.ParseUint(val, 10, 64) |  | ||||||
|   if err != nil { |   if err != nil { | ||||||
| 		return nil, err |     return []byte{}, err | ||||||
|   } |   } | ||||||
| 	binary.PutUvarint(buf, u) |   return t.itob(v), nil | ||||||
| 	return buf, nil | } | ||||||
|  |  | ||||||
|  | func (t *Datatype_Int64) itob(v int64) []byte { | ||||||
|  |   b := make([]byte, 8) | ||||||
|  |   binary.BigEndian.PutUint64(b, uint64(v)) | ||||||
|  |   return b | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Datatype_Int64) btoi(b []byte) int64 { | ||||||
|  |   if len(b) < 8 { | ||||||
|  |     return 0 | ||||||
|  |   } | ||||||
|  |   return int64(binary.BigEndian.Uint64(b)) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								datatype_uint.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								datatype_uint.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/binary" | ||||||
|  | 	"errors" | ||||||
|  | 	"strconv" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Datatype_Uint64 manages the uint64 data type | ||||||
|  | // All conversions just use the binary package | ||||||
|  | type Datatype_Uint64 struct{} | ||||||
|  |  | ||||||
|  | func (t *Datatype_Uint64) Name() string { | ||||||
|  | 	return "uint64" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Datatype_Uint64) ToString(data []byte) (string, error) { | ||||||
|  | 	ret, bt := binary.Uvarint(data) | ||||||
|  | 	if bt == 0 { | ||||||
|  | 		return "", errors.New("Byte Buffer too small") | ||||||
|  | 	} else if bt < 0 { | ||||||
|  | 		return "", errors.New("Value larger than 64 bits") | ||||||
|  | 	} | ||||||
|  | 	return strconv.FormatUint(ret, 10), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Datatype_Uint64) FromString(val string) ([]byte, error) { | ||||||
|  | 	var err error | ||||||
|  | 	var u uint64 | ||||||
|  | 	buf := make([]byte, binary.MaxVarintLen64) | ||||||
|  | 	u, err = strconv.ParseUint(val, 10, 64) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	binary.PutUvarint(buf, u) | ||||||
|  | 	return buf, nil | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								main.go
									
									
									
									
									
								
							| @@ -19,6 +19,7 @@ var db *bolt.DB | |||||||
| var memBolt *BoltDB | var memBolt *BoltDB | ||||||
|  |  | ||||||
| var datatypes map[string]Datatype | var datatypes map[string]Datatype | ||||||
|  | var dataTypeNameSlice []string | ||||||
|  |  | ||||||
| var currentFilename string | var currentFilename string | ||||||
|  |  | ||||||
| @@ -142,8 +143,10 @@ func initDataTypes() { | |||||||
| 	datatypes = make(map[string]Datatype) | 	datatypes = make(map[string]Datatype) | ||||||
| 	for _, t := range []Datatype{ | 	for _, t := range []Datatype{ | ||||||
| 		&Datatype_String{}, | 		&Datatype_String{}, | ||||||
|  | 		&Datatype_Int64{}, | ||||||
| 		&Datatype_Uint64{}, | 		&Datatype_Uint64{}, | ||||||
| 	} { | 	} { | ||||||
|  |     dataTypeNameSlice = append(dataTypeNameSlice, t.Name()) | ||||||
| 		datatypes[t.Name()] = t | 		datatypes[t.Name()] = t | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ type BrowserScreen struct { | |||||||
| 	leftViewPort   ViewPort | 	leftViewPort   ViewPort | ||||||
| 	rightViewPort  ViewPort | 	rightViewPort  ViewPort | ||||||
| 	queuedCommand  string | 	queuedCommand  string | ||||||
| 	currentPath    []string | 	currentPath    []PathNode | ||||||
| 	currentType    int | 	currentType    int | ||||||
| 	message        string | 	message        string | ||||||
| 	mode           BrowserMode | 	mode           BrowserMode | ||||||
| @@ -39,6 +39,8 @@ type BrowserScreen struct { | |||||||
|  |  | ||||||
| 	leftPaneBuffer  []Line | 	leftPaneBuffer  []Line | ||||||
| 	rightPaneBuffer []Line | 	rightPaneBuffer []Line | ||||||
|  |  | ||||||
|  |   niceLog []string | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -149,7 +151,7 @@ func (screen *BrowserScreen) handleBrowseKeyEvent(event termbox.Event) int { | |||||||
| 		screen.startInsertItemAtParent(typeBucket) | 		screen.startInsertItemAtParent(typeBucket) | ||||||
|  |  | ||||||
| 	} else if event.Ch == 'e' { | 	} else if event.Ch == 'e' { | ||||||
| 		b, p, _ := screen.db.getGenericFromPath(screen.currentPath) | 		b, p, _ := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			screen.setMessage("Cannot edit a bucket, did you mean to (r)ename?") | 			screen.setMessage("Cannot edit a bucket, did you mean to (r)ename?") | ||||||
| 		} else if p != nil { | 		} else if p != nil { | ||||||
| @@ -160,18 +162,18 @@ func (screen *BrowserScreen) handleBrowseKeyEvent(event termbox.Event) int { | |||||||
| 		screen.startRenameItem() | 		screen.startRenameItem() | ||||||
|  |  | ||||||
| 	} else if event.Key == termbox.KeyEnter { | 	} else if event.Key == termbox.KeyEnter { | ||||||
| 		b, p, _ := screen.db.getGenericFromPath(screen.currentPath) | 		b, p, _ := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			screen.db.toggleOpenBucket(screen.currentPath) | 			screen.db.toggleOpenBucket(stringPathToBytePath(screen.currentPath)) | ||||||
| 		} else if p != nil { | 		} else if p != nil { | ||||||
| 			screen.startEditItem() | 			screen.startEditItem() | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 	} else if event.Ch == 'l' || event.Key == termbox.KeyArrowRight { | 	} else if event.Ch == 'l' || event.Key == termbox.KeyArrowRight { | ||||||
| 		b, p, _ := screen.db.getGenericFromPath(screen.currentPath) | 		b, p, _ := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 		// Select the current item | 		// Select the current item | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			screen.db.toggleOpenBucket(screen.currentPath) | 			screen.db.toggleOpenBucket(stringPathToBytePath(screen.currentPath)) | ||||||
| 		} else if p != nil { | 		} else if p != nil { | ||||||
| 			screen.startEditItem() | 			screen.startEditItem() | ||||||
| 		} else { | 		} else { | ||||||
| @@ -180,19 +182,19 @@ func (screen *BrowserScreen) handleBrowseKeyEvent(event termbox.Event) int { | |||||||
|  |  | ||||||
| 	} else if event.Ch == 'h' || event.Key == termbox.KeyArrowLeft { | 	} else if event.Ch == 'h' || event.Key == termbox.KeyArrowLeft { | ||||||
| 		// If we are _on_ a bucket that's open, close it | 		// If we are _on_ a bucket that's open, close it | ||||||
| 		b, _, e := screen.db.getGenericFromPath(screen.currentPath) | 		b, _, e := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 		if e == nil && b != nil && b.expanded { | 		if e == nil && b != nil && b.expanded { | ||||||
| 			screen.db.closeBucket(screen.currentPath) | 			screen.db.closeBucket(stringPathToBytePath(screen.currentPath)) | ||||||
| 		} else { | 		} else { | ||||||
| 			if len(screen.currentPath) > 1 { | 			if len(screen.currentPath) > 1 { | ||||||
| 				parentBucket, err := screen.db.getBucketFromPath(screen.currentPath[:len(screen.currentPath)-1]) | 				parentBucket, err := screen.db.getBucketFromPath(stringPathToBytePath(screen.currentPath[:len(screen.currentPath)-1])) | ||||||
| 				if err == nil { | 				if err == nil { | ||||||
| 					screen.db.closeBucket(parentBucket.GetPath()) | 					screen.db.closeBucket(parentBucket.GetPath()) | ||||||
| 					// Figure out how far up we need to move the cursor | 					// Figure out how far up we need to move the cursor | ||||||
| 					screen.currentPath = parentBucket.GetPath() | 					screen.currentPath = bytePathToStringPath(parentBucket.GetPath()) | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				screen.db.closeBucket(screen.currentPath) | 				screen.db.closeBucket(stringPathToBytePath(screen.currentPath)) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -207,7 +209,24 @@ func (screen *BrowserScreen) handleBrowseKeyEvent(event termbox.Event) int { | |||||||
|  |  | ||||||
| 	} else if event.Ch == 't' { | 	} else if event.Ch == 't' { | ||||||
| 		// TODO: change the type of the pair value being viewed | 		// TODO: change the type of the pair value being viewed | ||||||
|  |     p, err := screen.db.getPairFromPath(stringPathToBytePath(screen.currentPath)) | ||||||
|  |     if err != nil { | ||||||
|  |       screen.setMessage("Cannot change pair type (did you mean 'T': Change pair key/bucket name type?)") | ||||||
|  |       return BrowserScreenIndex | ||||||
|  |     } | ||||||
|  |     p.valDatatype = findNextDatatype(p.valDatatype.Name()) | ||||||
|  |  | ||||||
|  |   } else if event.Ch == 'T' { | ||||||
|  |     b, p, err := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
|  |     if err != nil { | ||||||
|  |       screen.setMessage("Error reading path... Not sure what to do.") | ||||||
|  |       return BrowserScreenIndex | ||||||
|  |     } | ||||||
|  |     if b != nil { | ||||||
|  |       b.nameDatatype = findNextDatatype(b.nameDatatype.Name()) | ||||||
|  |     } else if p != nil { | ||||||
|  |       p.keyDatatype = findNextDatatype(p.keyDatatype.Name()) | ||||||
|  |     } | ||||||
| 	} | 	} | ||||||
| 	return BrowserScreenIndex | 	return BrowserScreenIndex | ||||||
| } | } | ||||||
| @@ -219,15 +238,15 @@ func (screen *BrowserScreen) handleInputKeyEvent(event termbox.Event) int { | |||||||
| 	} else { | 	} else { | ||||||
| 		screen.inputModal.HandleEvent(event) | 		screen.inputModal.HandleEvent(event) | ||||||
| 		if screen.inputModal.IsDone() { | 		if screen.inputModal.IsDone() { | ||||||
| 			b, p, _ := screen.db.getGenericFromPath(screen.currentPath) | 			b, p, _ := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 			if b != nil { | 			if b != nil { | ||||||
| 				if screen.mode == modeChangeKey { | 				if screen.mode == modeChangeKey { | ||||||
| 					newName := screen.inputModal.GetValue() | 					newName := screen.inputModal.GetValue() | ||||||
| 					if renameBucket(screen.currentPath, newName) != nil { | 					if renameBucket(stringPathToBytePath(screen.currentPath), []byte(newName)) != nil { | ||||||
| 						screen.setMessage("Error renaming bucket.") | 						screen.setMessage("Error renaming bucket.") | ||||||
| 					} else { | 					} else { | ||||||
| 						b.name = newName | 						b.name = []byte(newName) | ||||||
| 						screen.currentPath[len(screen.currentPath)-1] = b.name | 						screen.currentPath[len(screen.currentPath)-1] = newName | ||||||
| 						screen.setMessage("Bucket Renamed!") | 						screen.setMessage("Bucket Renamed!") | ||||||
| 						screen.refreshDatabase() | 						screen.refreshDatabase() | ||||||
| 					} | 					} | ||||||
| @@ -235,20 +254,20 @@ func (screen *BrowserScreen) handleInputKeyEvent(event termbox.Event) int { | |||||||
| 			} else if p != nil { | 			} else if p != nil { | ||||||
| 				if screen.mode == modeChangeKey { | 				if screen.mode == modeChangeKey { | ||||||
| 					newKey := screen.inputModal.GetValue() | 					newKey := screen.inputModal.GetValue() | ||||||
| 					if updatePairKey(screen.currentPath, newKey) != nil { | 					if updatePairKey(stringPathToBytePath(screen.currentPath), []byte(newKey)) != nil { | ||||||
| 						screen.setMessage("Error occurred updating Pair.") | 						screen.setMessage("Error occurred updating Pair.") | ||||||
| 					} else { | 					} else { | ||||||
| 						p.key = newKey | 						p.key = []byte(newKey) | ||||||
| 						screen.currentPath[len(screen.currentPath)-1] = p.key | 						screen.currentPath[len(screen.currentPath)-1] = newKey | ||||||
| 						screen.setMessage("Pair updated!") | 						screen.setMessage("Pair updated!") | ||||||
| 						screen.refreshDatabase() | 						screen.refreshDatabase() | ||||||
| 					} | 					} | ||||||
| 				} else if screen.mode == modeChangeVal { | 				} else if screen.mode == modeChangeVal { | ||||||
| 					newVal := screen.inputModal.GetValue() | 					newVal := screen.inputModal.GetValue() | ||||||
| 					if updatePairValue(screen.currentPath, newVal) != nil { | 					if updatePairValue(stringPathToBytePath(screen.currentPath), []byte(newVal)) != nil { | ||||||
| 						screen.setMessage("Error occurred updating Pair.") | 						screen.setMessage("Error occurred updating Pair.") | ||||||
| 					} else { | 					} else { | ||||||
| 						p.val = newVal | 						p.val = []byte(newVal) | ||||||
| 						screen.setMessage("Pair updated!") | 						screen.setMessage("Pair updated!") | ||||||
| 						screen.refreshDatabase() | 						screen.refreshDatabase() | ||||||
| 					} | 					} | ||||||
| @@ -267,7 +286,7 @@ func (screen *BrowserScreen) handleDeleteKeyEvent(event termbox.Event) int { | |||||||
| 		if screen.confirmModal.IsAccepted() { | 		if screen.confirmModal.IsAccepted() { | ||||||
| 			holdNextPath := screen.db.getNextVisiblePath(screen.currentPath) | 			holdNextPath := screen.db.getNextVisiblePath(screen.currentPath) | ||||||
| 			holdPrevPath := screen.db.getPrevVisiblePath(screen.currentPath) | 			holdPrevPath := screen.db.getPrevVisiblePath(screen.currentPath) | ||||||
| 			if deleteKey(screen.currentPath) == nil { | 			if deleteKey(stringPathToBytePath(screen.currentPath)) == nil { | ||||||
| 				screen.refreshDatabase() | 				screen.refreshDatabase() | ||||||
| 				// Move the current path endpoint appropriately | 				// Move the current path endpoint appropriately | ||||||
| 				//found_new_path := false | 				//found_new_path := false | ||||||
| @@ -312,7 +331,7 @@ func (screen *BrowserScreen) handleInsertKeyEvent(event termbox.Event) int { | |||||||
| 			screen.inputModal.Clear() | 			screen.inputModal.Clear() | ||||||
| 			var insertPath []string | 			var insertPath []string | ||||||
| 			if len(screen.currentPath) > 0 { | 			if len(screen.currentPath) > 0 { | ||||||
| 				_, p, e := screen.db.getGenericFromPath(screen.currentPath) | 				_, p, e := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 				if e != nil { | 				if e != nil { | ||||||
| 					screen.setMessage("Error Inserting new item. Invalid Path.") | 					screen.setMessage("Error Inserting new item. Invalid Path.") | ||||||
| 				} | 				} | ||||||
| @@ -331,9 +350,9 @@ func (screen *BrowserScreen) handleInsertKeyEvent(event termbox.Event) int { | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			parentB, _, _ := screen.db.getGenericFromPath(insertPath) | 			parentB, _, _ := screen.db.getGenericFromStringPath(insertPath) | ||||||
| 			if screen.mode&modeInsertBucket == modeInsertBucket { | 			if screen.mode&modeInsertBucket == modeInsertBucket { | ||||||
| 				err := insertBucket(insertPath, newVal) | 				err := insertBucket(stringPathToBytePath(insertPath), []byte(newVal)) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					screen.setMessage(fmt.Sprintf("%s => %s", err, insertPath)) | 					screen.setMessage(fmt.Sprintf("%s => %s", err, insertPath)) | ||||||
| 				} else { | 				} else { | ||||||
| @@ -347,7 +366,7 @@ func (screen *BrowserScreen) handleInsertKeyEvent(event termbox.Event) int { | |||||||
| 				screen.mode = modeBrowse | 				screen.mode = modeBrowse | ||||||
| 				screen.inputModal.Clear() | 				screen.inputModal.Clear() | ||||||
| 			} else if screen.mode&modeInsertPair == modeInsertPair { | 			} else if screen.mode&modeInsertPair == modeInsertPair { | ||||||
| 				err := insertPair(insertPath, newVal, "") | 				err := insertPair(stringPathToBytePath(insertPath), []byte(newVal), []byte{}) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					screen.setMessage(fmt.Sprintf("%s => %s", err, insertPath)) | 					screen.setMessage(fmt.Sprintf("%s => %s", err, insertPath)) | ||||||
| 					screen.refreshDatabase() | 					screen.refreshDatabase() | ||||||
| @@ -374,12 +393,12 @@ func (screen *BrowserScreen) handleExportKeyEvent(event termbox.Event) int { | |||||||
| 	} else { | 	} else { | ||||||
| 		screen.inputModal.HandleEvent(event) | 		screen.inputModal.HandleEvent(event) | ||||||
| 		if screen.inputModal.IsDone() { | 		if screen.inputModal.IsDone() { | ||||||
| 			b, p, _ := screen.db.getGenericFromPath(screen.currentPath) | 			b, p, _ := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 			fileName := screen.inputModal.GetValue() | 			fileName := screen.inputModal.GetValue() | ||||||
| 			if screen.mode&modeExportValue == modeExportValue { | 			if screen.mode&modeExportValue == modeExportValue { | ||||||
| 				// Exporting the value | 				// Exporting the value | ||||||
| 				if p != nil { | 				if p != nil { | ||||||
| 					if err := exportValue(screen.currentPath, fileName); err != nil { | 					if err := exportValue(stringPathToBytePath(screen.currentPath), fileName); err != nil { | ||||||
| 						//screen.setMessage("Error Exporting to file " + fileName + ".") | 						//screen.setMessage("Error Exporting to file " + fileName + ".") | ||||||
| 						screen.setMessage(err.Error()) | 						screen.setMessage(err.Error()) | ||||||
| 					} else { | 					} else { | ||||||
| @@ -388,7 +407,7 @@ func (screen *BrowserScreen) handleExportKeyEvent(event termbox.Event) int { | |||||||
| 				} | 				} | ||||||
| 			} else if screen.mode&modeExportJSON == modeExportJSON { | 			} else if screen.mode&modeExportJSON == modeExportJSON { | ||||||
| 				if b != nil || p != nil { | 				if b != nil || p != nil { | ||||||
| 					if exportJSON(screen.currentPath, fileName) != nil { | 					if exportJSON(stringPathToBytePath(screen.currentPath), fileName) != nil { | ||||||
| 						screen.setMessage("Error Exporting to file " + fileName + ".") | 						screen.setMessage("Error Exporting to file " + fileName + ".") | ||||||
| 					} else { | 					} else { | ||||||
| 						screen.setMessage("Value exported to file: " + fileName) | 						screen.setMessage("Value exported to file: " + fileName) | ||||||
| @@ -583,7 +602,15 @@ func (screen *BrowserScreen) drawLeftPane(style Style) { | |||||||
|  |  | ||||||
| func (screen *BrowserScreen) buildRightPane(style Style) { | func (screen *BrowserScreen) buildRightPane(style Style) { | ||||||
| 	screen.rightPaneBuffer = nil | 	screen.rightPaneBuffer = nil | ||||||
| 	b, p, err := screen.db.getGenericFromPath(screen.currentPath) |   screen.niceLog = []string{} | ||||||
|  |  | ||||||
|  |   var logstr string | ||||||
|  |   for _, v := range screen.currentPath { | ||||||
|  |     logstr = fmt.Sprintf("%s / %s", logstr, stringify([]byte(v))) | ||||||
|  |   } | ||||||
|  |   screen.niceLog = append(screen.niceLog, logstr) | ||||||
|  |  | ||||||
|  | 	b, p, err := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			screen.rightPaneBuffer = append(screen.rightPaneBuffer, | 			screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
| @@ -596,12 +623,12 @@ func (screen *BrowserScreen) buildRightPane(style Style) { | |||||||
| 			screen.rightPaneBuffer = append(screen.rightPaneBuffer, | 			screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
| 				Line{fmt.Sprintf("Path: %s", strings.Join(stringifyPath(p.GetPath()), " → ")), style.defaultFg, style.defaultBg}) | 				Line{fmt.Sprintf("Path: %s", strings.Join(stringifyPath(p.GetPath()), " → ")), style.defaultFg, style.defaultBg}) | ||||||
| 			screen.rightPaneBuffer = append(screen.rightPaneBuffer, | 			screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
| 				Line{fmt.Sprintf("Key: %s", stringify([]byte(p.key))), style.defaultFg, style.defaultBg}) | 				Line{fmt.Sprintf("Key (%s): %s", p.keyDatatype.Name(), stringify([]byte(p.key))), style.defaultFg, style.defaultBg}) | ||||||
|  |  | ||||||
| 			value := strings.Split(string(formatValue([]byte(p.val))), "\n") | 			value := strings.Split(string(formatValue([]byte(p.val))), "\n") | ||||||
| 			if len(value) == 1 { | 			if len(value) == 1 { | ||||||
| 				screen.rightPaneBuffer = append(screen.rightPaneBuffer, | 				screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
| 					Line{fmt.Sprintf("Value: %s", value[0]), style.defaultFg, style.defaultBg}) | 					Line{fmt.Sprintf("Value (%s): %s", p.valDatatype.Name(), value[0]), style.defaultFg, style.defaultBg}) | ||||||
| 			} else { | 			} else { | ||||||
| 				screen.rightPaneBuffer = append(screen.rightPaneBuffer, | 				screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
| 					Line{"Value:", style.defaultFg, style.defaultBg}) | 					Line{"Value:", style.defaultFg, style.defaultBg}) | ||||||
| @@ -613,10 +640,18 @@ func (screen *BrowserScreen) buildRightPane(style Style) { | |||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		screen.rightPaneBuffer = append(screen.rightPaneBuffer, | 		screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
| 			Line{fmt.Sprintf("Path: %s", strings.Join(stringifyPath(screen.currentPath), " → ")), style.defaultFg, style.defaultBg}) | 			Line{fmt.Sprintf("Path: %s", strings.Join(stringifyStringPath(screen.currentPath), " → ")), style.defaultFg, style.defaultBg}) | ||||||
| 		screen.rightPaneBuffer = append(screen.rightPaneBuffer, | 		screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
| 			Line{err.Error(), termbox.ColorRed, termbox.ColorBlack}) | 			Line{err.Error(), termbox.ColorRed, termbox.ColorBlack}) | ||||||
| 	} | 	} | ||||||
|  |   screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
|  |       Line{"", style.defaultFg, style.defaultBg}) | ||||||
|  |   screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
|  |       Line{"== Log ==", style.defaultBg, style.defaultFg}) | ||||||
|  |   for _, v := range screen.niceLog { | ||||||
|  |     screen.rightPaneBuffer = append(screen.rightPaneBuffer, | ||||||
|  |         Line{v, style.defaultFg, style.defaultBg}) | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| func (screen *BrowserScreen) drawRightPane(style Style) { | func (screen *BrowserScreen) drawRightPane(style Style) { | ||||||
| @@ -673,32 +708,32 @@ func formatValueJSON(val []byte) ([]byte, error) { | |||||||
| func (screen *BrowserScreen) bucketToLines(bkt *BoltBucket, style Style) []Line { | func (screen *BrowserScreen) bucketToLines(bkt *BoltBucket, style Style) []Line { | ||||||
| 	var ret []Line | 	var ret []Line | ||||||
| 	bfg, bbg := style.defaultFg, style.defaultBg | 	bfg, bbg := style.defaultFg, style.defaultBg | ||||||
| 	if comparePaths(screen.currentPath, bkt.GetPath()) { | 	if comparePaths(screen.currentPath, bytePathToStringPath(bkt.GetPath())) { | ||||||
| 		bfg, bbg = style.cursorFg, style.cursorBg | 		bfg, bbg = style.cursorFg, style.cursorBg | ||||||
| 	} | 	} | ||||||
| 	bktPrefix := strings.Repeat(" ", len(bkt.GetPath())*2) | 	bktPrefix := strings.Repeat(" ", len(bkt.GetPath())*2) | ||||||
| 	if bkt.expanded { | 	if bkt.expanded { | ||||||
| 		ret = append(ret, Line{bktPrefix + "- " + stringify([]byte(bkt.name)), bfg, bbg}) | 		ret = append(ret, Line{bktPrefix + "- " + bkt.GetStringName(), bfg, bbg}) | ||||||
| 		for i := range bkt.buckets { | 		for i := range bkt.buckets { | ||||||
| 			ret = append(ret, screen.bucketToLines(&bkt.buckets[i], style)...) | 			ret = append(ret, screen.bucketToLines(&bkt.buckets[i], style)...) | ||||||
| 		} | 		} | ||||||
| 		for _, bp := range bkt.pairs { | 		for _, bp := range bkt.pairs { | ||||||
| 			pfg, pbg := style.defaultFg, style.defaultBg | 			pfg, pbg := style.defaultFg, style.defaultBg | ||||||
| 			if comparePaths(screen.currentPath, bp.GetPath()) { | 			if comparePaths(screen.currentPath, bytePathToStringPath(bp.GetPath())) { | ||||||
| 				pfg, pbg = style.cursorFg, style.cursorBg | 				pfg, pbg = style.cursorFg, style.cursorBg | ||||||
| 			} | 			} | ||||||
| 			prPrefix := strings.Repeat(" ", len(bp.GetPath())*2) | 			prPrefix := strings.Repeat(" ", len(bp.GetPath())*2) | ||||||
| 			pairString := fmt.Sprintf("%s%s: %s", prPrefix, stringify([]byte(bp.key)), stringify([]byte(bp.val))) | 			pairString := fmt.Sprintf("%s%s: %s", prPrefix, bp.GetStringKey(), bp.GetStringVal()) | ||||||
| 			ret = append(ret, Line{pairString, pfg, pbg}) | 			ret = append(ret, Line{pairString, pfg, pbg}) | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		ret = append(ret, Line{bktPrefix + "+ " + stringify([]byte(bkt.name)), bfg, bbg}) | 		ret = append(ret, Line{bktPrefix + "+ " + bkt.GetStringName(), bfg, bbg}) | ||||||
| 	} | 	} | ||||||
| 	return ret | 	return ret | ||||||
| } | } | ||||||
|  |  | ||||||
| func (screen *BrowserScreen) startDeleteItem() bool { | func (screen *BrowserScreen) startDeleteItem() bool { | ||||||
| 	b, p, e := screen.db.getGenericFromPath(screen.currentPath) | 	b, p, e := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 	if e == nil { | 	if e == nil { | ||||||
| 		w, h := termbox.Size() | 		w, h := termbox.Size() | ||||||
| 		inpW, inpH := (w / 2), 6 | 		inpW, inpH := (w / 2), 6 | ||||||
| @@ -719,7 +754,7 @@ func (screen *BrowserScreen) startDeleteItem() bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (screen *BrowserScreen) startEditItem() bool { | func (screen *BrowserScreen) startEditItem() bool { | ||||||
| 	_, p, e := screen.db.getGenericFromPath(screen.currentPath) | 	_, p, e := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 	if e == nil { | 	if e == nil { | ||||||
| 		w, h := termbox.Size() | 		w, h := termbox.Size() | ||||||
| 		inpW, inpH := (w / 2), 6 | 		inpW, inpH := (w / 2), 6 | ||||||
| @@ -727,7 +762,7 @@ func (screen *BrowserScreen) startEditItem() bool { | |||||||
| 		mod := termboxUtil.CreateInputModal("", inpX, inpY, inpW, inpH, termbox.ColorWhite, termbox.ColorBlack) | 		mod := termboxUtil.CreateInputModal("", inpX, inpY, inpW, inpH, termbox.ColorWhite, termbox.ColorBlack) | ||||||
| 		if p != nil { | 		if p != nil { | ||||||
| 			mod.SetTitle(termboxUtil.AlignText(fmt.Sprintf("Input new value for '%s'", p.key), inpW, termboxUtil.AlignCenter)) | 			mod.SetTitle(termboxUtil.AlignText(fmt.Sprintf("Input new value for '%s'", p.key), inpW, termboxUtil.AlignCenter)) | ||||||
| 			mod.SetValue(p.val) | 			mod.SetValue(p.GetStringVal()) | ||||||
| 		} | 		} | ||||||
| 		mod.Show() | 		mod.Show() | ||||||
| 		screen.inputModal = mod | 		screen.inputModal = mod | ||||||
| @@ -738,18 +773,18 @@ func (screen *BrowserScreen) startEditItem() bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (screen *BrowserScreen) startRenameItem() bool { | func (screen *BrowserScreen) startRenameItem() bool { | ||||||
| 	b, p, e := screen.db.getGenericFromPath(screen.currentPath) | 	b, p, e := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 	if e == nil { | 	if e == nil { | ||||||
| 		w, h := termbox.Size() | 		w, h := termbox.Size() | ||||||
| 		inpW, inpH := (w / 2), 6 | 		inpW, inpH := (w / 2), 6 | ||||||
| 		inpX, inpY := ((w / 2) - (inpW / 2)), ((h / 2) - inpH) | 		inpX, inpY := ((w / 2) - (inpW / 2)), ((h / 2) - inpH) | ||||||
| 		mod := termboxUtil.CreateInputModal("", inpX, inpY, inpW, inpH, termbox.ColorWhite, termbox.ColorBlack) | 		mod := termboxUtil.CreateInputModal("", inpX, inpY, inpW, inpH, termbox.ColorWhite, termbox.ColorBlack) | ||||||
| 		if b != nil { | 		if b != nil { | ||||||
| 			mod.SetTitle(termboxUtil.AlignText(fmt.Sprintf("Rename Bucket '%s' to:", b.name), inpW, termboxUtil.AlignCenter)) | 			mod.SetTitle(termboxUtil.AlignText(fmt.Sprintf("Rename Bucket '%s' to:", b.GetStringName()), inpW, termboxUtil.AlignCenter)) | ||||||
| 			mod.SetValue(b.name) | 			mod.SetValue(b.GetStringName()) | ||||||
| 		} else if p != nil { | 		} else if p != nil { | ||||||
| 			mod.SetTitle(termboxUtil.AlignText(fmt.Sprintf("Rename Key '%s' to:", p.key), inpW, termboxUtil.AlignCenter)) | 			mod.SetTitle(termboxUtil.AlignText(fmt.Sprintf("Rename Key '%s' to:", p.GetStringKey()), inpW, termboxUtil.AlignCenter)) | ||||||
| 			mod.SetValue(p.key) | 			mod.SetValue(p.GetStringKey()) | ||||||
| 		} | 		} | ||||||
| 		mod.Show() | 		mod.Show() | ||||||
| 		screen.inputModal = mod | 		screen.inputModal = mod | ||||||
| @@ -778,7 +813,7 @@ func (screen *BrowserScreen) startInsertItemAtParent(tp BoltType) bool { | |||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		var insPath string | 		var insPath string | ||||||
| 		_, p, e := screen.db.getGenericFromPath(screen.currentPath[:len(screen.currentPath)-1]) | 		_, p, e := screen.db.getGenericFromStringPath(screen.currentPath[:len(screen.currentPath)-1]) | ||||||
| 		if e == nil && p != nil { | 		if e == nil && p != nil { | ||||||
| 			insPath = strings.Join(screen.currentPath[:len(screen.currentPath)-2], " → ") + " → " | 			insPath = strings.Join(screen.currentPath[:len(screen.currentPath)-2], " → ") + " → " | ||||||
| 		} else { | 		} else { | ||||||
| @@ -821,7 +856,7 @@ func (screen *BrowserScreen) startInsertItem(tp BoltType) bool { | |||||||
| 	//mod.SetInputWrap(true) | 	//mod.SetInputWrap(true) | ||||||
| 	screen.inputModal = mod | 	screen.inputModal = mod | ||||||
| 	var insPath string | 	var insPath string | ||||||
| 	_, p, e := screen.db.getGenericFromPath(screen.currentPath) | 	_, p, e := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 	if e == nil && p != nil { | 	if e == nil && p != nil { | ||||||
| 		insPath = strings.Join(screen.currentPath[:len(screen.currentPath)-1], " → ") + " → " | 		insPath = strings.Join(screen.currentPath[:len(screen.currentPath)-1], " → ") + " → " | ||||||
| 	} else { | 	} else { | ||||||
| @@ -853,7 +888,7 @@ func (screen *BrowserScreen) startInsertItem(tp BoltType) bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (screen *BrowserScreen) startExportValue() bool { | func (screen *BrowserScreen) startExportValue() bool { | ||||||
| 	_, p, e := screen.db.getGenericFromPath(screen.currentPath) | 	_, p, e := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 	if e == nil && p != nil { | 	if e == nil && p != nil { | ||||||
| 		w, h := termbox.Size() | 		w, h := termbox.Size() | ||||||
| 		inpW, inpH := (w / 2), 6 | 		inpW, inpH := (w / 2), 6 | ||||||
| @@ -871,7 +906,7 @@ func (screen *BrowserScreen) startExportValue() bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (screen *BrowserScreen) startExportJSON() bool { | func (screen *BrowserScreen) startExportJSON() bool { | ||||||
| 	b, p, e := screen.db.getGenericFromPath(screen.currentPath) | 	b, p, e := screen.db.getGenericFromStringPath(screen.currentPath) | ||||||
| 	if e == nil { | 	if e == nil { | ||||||
| 		w, h := termbox.Size() | 		w, h := termbox.Size() | ||||||
| 		inpW, inpH := (w / 2), 6 | 		inpW, inpH := (w / 2), 6 | ||||||
| @@ -918,6 +953,23 @@ func (screen *BrowserScreen) refreshDatabase() { | |||||||
| 	screen.db.syncOpenBuckets(shadowDB) | 	screen.db.syncOpenBuckets(shadowDB) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func findNextDatatype(curr string) Datatype { | ||||||
|  |   var first Datatype | ||||||
|  |   var found bool | ||||||
|  |   for k, v := range datatypes { | ||||||
|  |     if first == nil { | ||||||
|  |       first = v | ||||||
|  |     } | ||||||
|  |     if found { | ||||||
|  |       return v | ||||||
|  |     } | ||||||
|  |     if k == curr { | ||||||
|  |       found = true | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return first | ||||||
|  | } | ||||||
|  |  | ||||||
| func comparePaths(p1, p2 []string) bool { | func comparePaths(p1, p2 []string) bool { | ||||||
| 	return strings.Join(p1, " → ") == strings.Join(p2, " → ") | 	return strings.Join(p1, " → ") == strings.Join(p2, " → ") | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								stringify.go
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								stringify.go
									
									
									
									
									
								
							| @@ -31,9 +31,14 @@ func stringify(v []byte) string { | |||||||
| 	return fmt.Sprintf("%x", v) | 	return fmt.Sprintf("%x", v) | ||||||
| } | } | ||||||
|  |  | ||||||
| func stringifyPath(path []string) []string { | func stringifyStringPath(path []string) []string { | ||||||
| 	for k, v := range path { |   return stringifyPath(stringPathToBytePath(path)) | ||||||
| 		path[k] = stringify([]byte(v)) | } | ||||||
| 	} |  | ||||||
| 	return path | func stringifyPath(path [][]byte) []string { | ||||||
|  |   var ret []string | ||||||
|  | 	for _, v := range path { | ||||||
|  | 		ret = append(ret, stringify(v)) | ||||||
|  | 	} | ||||||
|  | 	return ret | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user