mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
adding gres
This commit is contained in:
@ -8,5 +8,5 @@ import (
|
||||
|
||||
func main() {
|
||||
gres.Dump()
|
||||
g.Dump(gres.Scan("/", "*"))
|
||||
g.Dump(gres.Scan("/r", "*", true))
|
||||
}
|
||||
|
||||
2
.example/os/gres/testdata/testdata.go
vendored
2
.example/os/gres/testdata/testdata.go
vendored
File diff suppressed because one or more lines are too long
@ -80,28 +80,28 @@ func (tree *AVLTree) Sets(data map[interface{}]interface{}) {
|
||||
func (tree *AVLTree) Search(key interface{}) (value interface{}, found bool) {
|
||||
tree.mu.RLock()
|
||||
defer tree.mu.RUnlock()
|
||||
if n := tree.doSearch(key); n != nil {
|
||||
return n.Value, true
|
||||
if node, found := tree.doSearch(key); found {
|
||||
return node.Value, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// doSearch searches the tree with given <key>.
|
||||
// Second return parameter <found> is true if key was found, otherwise false.
|
||||
func (tree *AVLTree) doSearch(key interface{}) *AVLTreeNode {
|
||||
n := tree.root
|
||||
for n != nil {
|
||||
cmp := tree.comparator(key, n.Key)
|
||||
func (tree *AVLTree) doSearch(key interface{}) (node *AVLTreeNode, found bool) {
|
||||
node = tree.root
|
||||
for node != nil {
|
||||
cmp := tree.comparator(key, node.Key)
|
||||
switch {
|
||||
case cmp == 0:
|
||||
return n
|
||||
return node, true
|
||||
case cmp < 0:
|
||||
n = n.children[0]
|
||||
node = node.children[0]
|
||||
case cmp > 0:
|
||||
n = n.children[1]
|
||||
node = node.children[1]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Get searches the node in the tree by <key> and returns its value or nil if key is not found in tree.
|
||||
@ -122,8 +122,8 @@ func (tree *AVLTree) Get(key interface{}) (value interface{}) {
|
||||
func (tree *AVLTree) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
|
||||
tree.mu.Lock()
|
||||
defer tree.mu.Unlock()
|
||||
if n := tree.doSearch(key); n != nil {
|
||||
return n.Value
|
||||
if node, found := tree.doSearch(key); found {
|
||||
return node.Value
|
||||
}
|
||||
if f, ok := value.(func() interface{}); ok {
|
||||
value = f()
|
||||
@ -451,7 +451,8 @@ func (tree *AVLTree) IteratorAsc(f func(key, value interface{}) bool) {
|
||||
func (tree *AVLTree) IteratorAscFrom(key interface{}, f func(key, value interface{}) bool) {
|
||||
tree.mu.RLock()
|
||||
defer tree.mu.RUnlock()
|
||||
tree.doIteratorAsc(tree.doSearch(key), f)
|
||||
node, _ := tree.doSearch(key)
|
||||
tree.doIteratorAsc(node, f)
|
||||
}
|
||||
|
||||
func (tree *AVLTree) doIteratorAsc(node *AVLTreeNode, f func(key, value interface{}) bool) {
|
||||
@ -474,7 +475,8 @@ func (tree *AVLTree) IteratorDesc(f func(key, value interface{}) bool) {
|
||||
func (tree *AVLTree) IteratorDescFrom(key interface{}, f func(key, value interface{}) bool) {
|
||||
tree.mu.RLock()
|
||||
defer tree.mu.RUnlock()
|
||||
tree.doIteratorDesc(tree.doSearch(key), f)
|
||||
node, _ := tree.doSearch(key)
|
||||
tree.doIteratorDesc(node, f)
|
||||
}
|
||||
|
||||
func (tree *AVLTree) doIteratorDesc(node *AVLTreeNode, f func(key, value interface{}) bool) {
|
||||
|
||||
@ -142,7 +142,7 @@ func (tree *RedBlackTree) Get(key interface{}) (value interface{}) {
|
||||
func (tree *RedBlackTree) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
|
||||
tree.mu.Lock()
|
||||
defer tree.mu.Unlock()
|
||||
if node := tree.doSearch(key); node != nil {
|
||||
if node, found := tree.doSearch(key); found {
|
||||
return node.Value
|
||||
}
|
||||
if f, ok := value.(func() interface{}); ok {
|
||||
@ -253,8 +253,8 @@ func (tree *RedBlackTree) Contains(key interface{}) bool {
|
||||
// doRemove removes the node from the tree by <key> without mutex.
|
||||
func (tree *RedBlackTree) doRemove(key interface{}) (value interface{}) {
|
||||
child := (*RedBlackTreeNode)(nil)
|
||||
node := tree.doSearch(key)
|
||||
if node == nil {
|
||||
node, found := tree.doSearch(key)
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
value = node.Value
|
||||
@ -472,7 +472,8 @@ func (tree *RedBlackTree) IteratorAsc(f func(key, value interface{}) bool) {
|
||||
func (tree *RedBlackTree) IteratorAscFrom(key interface{}, f func(key, value interface{}) bool) {
|
||||
tree.mu.RLock()
|
||||
defer tree.mu.RUnlock()
|
||||
tree.doIteratorAsc(tree.doSearch(key), f)
|
||||
node, _ := tree.doSearch(key)
|
||||
tree.doIteratorAsc(node, f)
|
||||
}
|
||||
|
||||
func (tree *RedBlackTree) doIteratorAsc(node *RedBlackTreeNode, f func(key, value interface{}) bool) {
|
||||
@ -512,7 +513,8 @@ func (tree *RedBlackTree) IteratorDesc(f func(key, value interface{}) bool) {
|
||||
func (tree *RedBlackTree) IteratorDescFrom(key interface{}, f func(key, value interface{}) bool) {
|
||||
tree.mu.RLock()
|
||||
defer tree.mu.RUnlock()
|
||||
tree.doIteratorDesc(tree.doSearch(key), f)
|
||||
node, _ := tree.doSearch(key)
|
||||
tree.doIteratorDesc(node, f)
|
||||
}
|
||||
|
||||
func (tree *RedBlackTree) doIteratorDesc(node *RedBlackTreeNode, f func(key, value interface{}) bool) {
|
||||
@ -570,8 +572,8 @@ func (tree *RedBlackTree) Print() {
|
||||
func (tree *RedBlackTree) Search(key interface{}) (value interface{}, found bool) {
|
||||
tree.mu.RLock()
|
||||
defer tree.mu.RUnlock()
|
||||
node := tree.doSearch(key)
|
||||
if node != nil {
|
||||
node, found := tree.doSearch(key)
|
||||
if found {
|
||||
return node.Value, true
|
||||
}
|
||||
return nil, false
|
||||
@ -629,20 +631,20 @@ func (tree *RedBlackTree) output(node *RedBlackTreeNode, prefix string, isTail b
|
||||
|
||||
// doSearch searches the tree with given <key> without mutex.
|
||||
// It returns the node if found or otherwise nil.
|
||||
func (tree *RedBlackTree) doSearch(key interface{}) *RedBlackTreeNode {
|
||||
node := tree.root
|
||||
func (tree *RedBlackTree) doSearch(key interface{}) (node *RedBlackTreeNode, found bool) {
|
||||
node = tree.root
|
||||
for node != nil {
|
||||
compare := tree.comparator(key, node.Key)
|
||||
switch {
|
||||
case compare == 0:
|
||||
return node
|
||||
return node, true
|
||||
case compare < 0:
|
||||
node = node.left
|
||||
case compare > 0:
|
||||
node = node.right
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return node, false
|
||||
}
|
||||
|
||||
func (node *RedBlackTreeNode) grandparent() *RedBlackTreeNode {
|
||||
|
||||
@ -20,21 +20,45 @@ func init() {
|
||||
)
|
||||
|
||||
var (
|
||||
// Default resource object.
|
||||
defaultResource = New()
|
||||
)
|
||||
|
||||
// Add unpacks and adds the <content> into the default resource object.
|
||||
// The unnecessary parameter <prefix> indicates the prefix
|
||||
// for each file storing into current resource object.
|
||||
func Add(content []byte, prefix ...string) error {
|
||||
return defaultResource.Add(content, prefix...)
|
||||
}
|
||||
|
||||
// Load loads, unpacks and adds the data from <path> into the default resource object.
|
||||
// The unnecessary parameter <prefix> indicates the prefix
|
||||
// for each file storing into current resource object.
|
||||
func Load(path string, prefix ...string) error {
|
||||
return defaultResource.Load(path, prefix...)
|
||||
}
|
||||
|
||||
// Get returns the file with given path.
|
||||
func Get(path string) *File {
|
||||
return defaultResource.Get(path)
|
||||
}
|
||||
|
||||
// Contains checks whether the <path> exists in the default resource object.
|
||||
func Contains(path string) bool {
|
||||
return defaultResource.Contains(path)
|
||||
}
|
||||
|
||||
// Scan returns the files under the given path, the parameter <path> should be a folder type.
|
||||
//
|
||||
// The pattern parameter <pattern> supports multiple file name patterns,
|
||||
// using the ',' symbol to separate multiple patterns.
|
||||
//
|
||||
// It scans directory recursively if given parameter <recursive> is true.
|
||||
func Scan(path string, pattern string, recursive ...bool) []*File {
|
||||
return defaultResource.Scan(path, pattern, recursive...)
|
||||
}
|
||||
|
||||
// Dump prints the files of the default resource object.
|
||||
func Dump() {
|
||||
defaultResource.Dump()
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ package gres
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
@ -46,3 +47,13 @@ func (f *File) Content() ([]byte, error) {
|
||||
func (f *File) FileInfo() os.FileInfo {
|
||||
return f.zipFile.FileInfo()
|
||||
}
|
||||
|
||||
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
|
||||
func (f *File) MarshalJSON() ([]byte, error) {
|
||||
info := f.FileInfo()
|
||||
return json.Marshal(map[string]interface{}{
|
||||
"name": f.Name(),
|
||||
"size": info.Size(),
|
||||
"time": info.ModTime(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -16,6 +16,9 @@ import (
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
)
|
||||
|
||||
// Pack packs the path specified by <srcPath> into bytes.
|
||||
// The unnecessary parameter <keyPrefix> indicates the prefix for each file
|
||||
// packed into the result bytes.
|
||||
func Pack(srcPath string, keyPrefix ...string) ([]byte, error) {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
err := gcompress.ZipPathWriter(srcPath, buffer, keyPrefix...)
|
||||
@ -25,6 +28,9 @@ func Pack(srcPath string, keyPrefix ...string) ([]byte, error) {
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// PackToFile packs the path specified by <srcPath> to target file <dstPath>.
|
||||
// The unnecessary parameter <keyPrefix> indicates the prefix for each file
|
||||
// packed into the result bytes.
|
||||
func PackToFile(srcPath, dstPath string, keyPrefix ...string) error {
|
||||
data, err := Pack(srcPath, keyPrefix...)
|
||||
if err != nil {
|
||||
@ -33,6 +39,11 @@ func PackToFile(srcPath, dstPath string, keyPrefix ...string) error {
|
||||
return gfile.PutBytes(dstPath, data)
|
||||
}
|
||||
|
||||
// PackToGoFile packs the path specified by <srcPath> to target go file <goFilePath>
|
||||
// with given package name <pkgName>.
|
||||
//
|
||||
// The unnecessary parameter <keyPrefix> indicates the prefix for each file
|
||||
// packed into the result bytes.
|
||||
func PackToGoFile(srcPath, goFilePath, pkgName string, keyPrefix ...string) error {
|
||||
data, err := Pack(srcPath, keyPrefix...)
|
||||
if err != nil {
|
||||
@ -43,6 +54,7 @@ func PackToGoFile(srcPath, goFilePath, pkgName string, keyPrefix ...string) erro
|
||||
)
|
||||
}
|
||||
|
||||
// Unpack unpacks the content specified by <path> to []*File.
|
||||
func Unpack(path string) ([]*File, error) {
|
||||
realPath, err := gfile.Search(path)
|
||||
if err != nil {
|
||||
@ -51,6 +63,7 @@ func Unpack(path string) ([]*File, error) {
|
||||
return UnpackContent(gfile.GetBytes(realPath))
|
||||
}
|
||||
|
||||
// UnpackContent unpacks the content to []*File.
|
||||
func UnpackContent(content []byte) ([]*File, error) {
|
||||
reader, err := zip.NewReader(bytes.NewReader(content), int64(len(content)))
|
||||
if err != nil {
|
||||
|
||||
@ -23,6 +23,7 @@ const (
|
||||
gDEFAULT_TREE_M = 100
|
||||
)
|
||||
|
||||
// New creates and returns a new resource object.
|
||||
func New() *Resource {
|
||||
return &Resource{
|
||||
tree: gtree.NewBTree(gDEFAULT_TREE_M, func(v1, v2 interface{}) int {
|
||||
@ -31,6 +32,9 @@ func New() *Resource {
|
||||
}
|
||||
}
|
||||
|
||||
// Add unpacks and adds the <content> into current resource object.
|
||||
// The unnecessary parameter <prefix> indicates the prefix
|
||||
// for each file storing into current resource object.
|
||||
func (r *Resource) Add(content []byte, prefix ...string) error {
|
||||
files, err := UnpackContent(content)
|
||||
if err != nil {
|
||||
@ -46,6 +50,9 @@ func (r *Resource) Add(content []byte, prefix ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load loads, unpacks and adds the data from <path> into current resource object.
|
||||
// The unnecessary parameter <prefix> indicates the prefix
|
||||
// for each file storing into current resource object.
|
||||
func (r *Resource) Load(path string, prefix ...string) error {
|
||||
realPath, err := gfile.Search(path)
|
||||
if err != nil {
|
||||
@ -54,6 +61,7 @@ func (r *Resource) Load(path string, prefix ...string) error {
|
||||
return r.Add(gfile.GetBytes(realPath), prefix...)
|
||||
}
|
||||
|
||||
// Get returns the file with given path.
|
||||
func (r *Resource) Get(path string) *File {
|
||||
result := r.tree.Get(path)
|
||||
if result != nil {
|
||||
@ -62,6 +70,17 @@ func (r *Resource) Get(path string) *File {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Contains checks whether the <path> exists in current resource object.
|
||||
func (r *Resource) Contains(path string) bool {
|
||||
return r.Get(path) != nil
|
||||
}
|
||||
|
||||
// Scan returns the files under the given path, the parameter <path> should be a folder type.
|
||||
//
|
||||
// The pattern parameter <pattern> supports multiple file name patterns,
|
||||
// using the ',' symbol to separate multiple patterns.
|
||||
//
|
||||
// It scans directory recursively if given parameter <recursive> is true.
|
||||
func (r *Resource) Scan(path string, pattern string, recursive ...bool) []*File {
|
||||
if path != "/" {
|
||||
path = strings.TrimRight(path, "/\\")
|
||||
@ -80,7 +99,7 @@ func (r *Resource) Scan(path string, pattern string, recursive ...bool) []*File
|
||||
}
|
||||
if len(recursive) == 0 || !recursive[0] {
|
||||
if strings.IndexByte(name[length:], '/') != -1 {
|
||||
return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, p := range patterns {
|
||||
@ -94,10 +113,11 @@ func (r *Resource) Scan(path string, pattern string, recursive ...bool) []*File
|
||||
return files
|
||||
}
|
||||
|
||||
// Dump prints the files of current resource object.
|
||||
func (r *Resource) Dump() {
|
||||
r.tree.Iterator(func(key, value interface{}) bool {
|
||||
fmt.Printf("%7s %s\n", gfile.FormatSize(value.(*File).FileInfo().Size()), key)
|
||||
return true
|
||||
})
|
||||
fmt.Printf("TOTAL %d FILES", r.tree.Size())
|
||||
fmt.Printf("TOTAL FILES: %d\n", r.tree.Size())
|
||||
}
|
||||
|
||||
@ -7,11 +7,12 @@
|
||||
package gres_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/os/gres"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Export(t *testing.T) {
|
||||
@ -19,7 +20,7 @@ func Test_Export(t *testing.T) {
|
||||
srcPath := gfile.Dir(gdebug.CallerFilePath()) + "/testdata/files"
|
||||
goFilePath := gfile.Dir(gdebug.CallerFilePath()) + "/testdata/testdata.go"
|
||||
pkgName := "testdata"
|
||||
err := gres.Export(srcPath, goFilePath, pkgName)
|
||||
err := gres.PackToGoFile(srcPath, goFilePath, pkgName)
|
||||
gtest.Assert(err, nil)
|
||||
})
|
||||
}
|
||||
|
||||
4
os/gres/testdata/files/root/css/style.css
vendored
Normal file
4
os/gres/testdata/files/root/css/style.css
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
* {
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
BIN
os/gres/testdata/files/root/image/logo.png
vendored
Normal file
BIN
os/gres/testdata/files/root/image/logo.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
9
os/gres/testdata/files/root/index.html
vendored
Normal file
9
os/gres/testdata/files/root/index.html
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="/css/style.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div><img src="image/logo.png"></div>
|
||||
This is the index from gres.
|
||||
</body>
|
||||
</html>
|
||||
2
os/gres/testdata/testdata.go
vendored
2
os/gres/testdata/testdata.go
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user