Merge pull request #12 from gogf/master

pr from master
This commit is contained in:
HaiLaz 2021-11-19 09:56:02 +08:00 committed by GitHub
commit b81a1e7c9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1623 additions and 251 deletions

View File

@ -57,7 +57,8 @@ jobs:
run: | run: |
date date
find . -name "*.go" | xargs gofmt -w find . -name "*.go" | xargs gofmt -w
git diff --name-only --exit-code || exit 1 git diff --name-only --exit-code || if [ $? != 0 ];then echo "Notice: gofmt check failed,please gofmt before pr." && exit 1; fi
echo "gofmt check pass."
sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts
- name: Run i386 Arch Test - name: Run i386 Arch Test

View File

@ -179,10 +179,3 @@ func (j *Json) Dump() {
defer j.mu.RUnlock() defer j.mu.RUnlock()
gutil.Dump(*j.p) gutil.Dump(*j.p)
} }
// Export returns `j` as a string with more manually readable.
func (j *Json) Export() string {
j.mu.RLock()
defer j.mu.RUnlock()
return gutil.Export(*j.p, gutil.ExportOption{})
}

View File

@ -8,6 +8,7 @@ package g
import ( import (
"context" "context"
"io"
"github.com/gogf/gf/v2/container/gvar" "github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/internal/empty" "github.com/gogf/gf/v2/internal/empty"
@ -39,12 +40,22 @@ func Dump(values ...interface{}) {
gutil.Dump(values...) gutil.Dump(values...)
} }
// DumpTo writes variables `values` as a string in to `writer` with more manually readable
func DumpTo(writer io.Writer, value interface{}, option gutil.DumpOption) {
gutil.DumpTo(writer, value, option)
}
// DumpWithType acts like Dump, but with type information. // DumpWithType acts like Dump, but with type information.
// Also see Dump. // Also see Dump.
func DumpWithType(values ...interface{}) { func DumpWithType(values ...interface{}) {
gutil.DumpWithType(values...) gutil.DumpWithType(values...)
} }
// DumpWithOption returns variables `values` as a string with more manually readable.
func DumpWithOption(value interface{}, option gutil.DumpOption) {
gutil.DumpWithOption(value, option)
}
// Throw throws an exception, which can be caught by TryCatch function. // Throw throws an exception, which can be caught by TryCatch function.
func Throw(exception interface{}) { func Throw(exception interface{}) {
gutil.Throw(exception) gutil.Throw(exception)

View File

@ -7,6 +7,8 @@
package gres_test package gres_test
import ( import (
_ "github.com/gogf/gf/v2/os/gres/testdata/data"
"strings" "strings"
"testing" "testing"
@ -20,22 +22,26 @@ import (
func Test_PackToGoFile(t *testing.T) { func Test_PackToGoFile(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
srcPath := gdebug.TestDataPath("files") var (
goFilePath := gdebug.TestDataPath("testdata.go") srcPath = gdebug.TestDataPath("files")
pkgName := "testdata" goFilePath = gfile.TempDir(gtime.TimestampNanoStr(), "testdata.go")
err := gres.PackToGoFile(srcPath, goFilePath, pkgName) pkgName = "testdata"
err = gres.PackToGoFile(srcPath, goFilePath, pkgName)
)
t.Assert(err, nil) t.Assert(err, nil)
_ = gfile.Remove(goFilePath)
}) })
} }
func Test_Pack(t *testing.T) { func Test_Pack(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
srcPath := gdebug.TestDataPath("files") var (
data, err := gres.Pack(srcPath) srcPath = gdebug.TestDataPath("files")
data, err = gres.Pack(srcPath)
)
t.Assert(err, nil) t.Assert(err, nil)
r := gres.New() r := gres.New()
err = r.Add(string(data)) err = r.Add(string(data))
t.Assert(err, nil) t.Assert(err, nil)
t.Assert(r.Contains("files/"), true) t.Assert(r.Contains("files/"), true)
@ -44,9 +50,11 @@ func Test_Pack(t *testing.T) {
func Test_PackToFile(t *testing.T) { func Test_PackToFile(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
srcPath := gdebug.TestDataPath("files") var (
dstPath := gfile.TempDir(gtime.TimestampNanoStr()) srcPath = gdebug.TestDataPath("files")
err := gres.PackToFile(srcPath, dstPath) dstPath = gfile.TempDir(gtime.TimestampNanoStr())
err = gres.PackToFile(srcPath, dstPath)
)
t.Assert(err, nil) t.Assert(err, nil)
defer gfile.Remove(dstPath) defer gfile.Remove(dstPath)
@ -60,33 +68,42 @@ func Test_PackToFile(t *testing.T) {
func Test_PackMulti(t *testing.T) { func Test_PackMulti(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
srcPath := gdebug.TestDataPath("files") var (
goFilePath := gdebug.TestDataPath("data/data.go") srcPath = gdebug.TestDataPath("files")
pkgName := "data" goFilePath = gfile.TempDir(gtime.TimestampNanoStr(), "data.go")
array, err := gfile.ScanDir(srcPath, "*", false) pkgName = "data"
array, err = gfile.ScanDir(srcPath, "*", false)
)
t.Assert(err, nil) t.Assert(err, nil)
err = gres.PackToGoFile(strings.Join(array, ","), goFilePath, pkgName) err = gres.PackToGoFile(strings.Join(array, ","), goFilePath, pkgName)
t.Assert(err, nil) t.Assert(err, nil)
_ = gfile.Remove(goFilePath)
}) })
} }
func Test_PackWithPrefix1(t *testing.T) { func Test_PackWithPrefix1(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
srcPath := gdebug.TestDataPath("files") var (
goFilePath := gfile.TempDir("testdata.go") srcPath = gdebug.TestDataPath("files")
pkgName := "testdata" goFilePath = gfile.TempDir(gtime.TimestampNanoStr(), "testdata.go")
err := gres.PackToGoFile(srcPath, goFilePath, pkgName, "www/gf-site/test") pkgName = "testdata"
t.Assert(err, nil) err = gres.PackToGoFile(srcPath, goFilePath, pkgName, "www/gf-site/test")
)
t.AssertNil(err)
_ = gfile.Remove(goFilePath)
}) })
} }
func Test_PackWithPrefix2(t *testing.T) { func Test_PackWithPrefix2(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
srcPath := gdebug.TestDataPath("files") var (
goFilePath := gfile.TempDir("testdata.go") srcPath = gdebug.TestDataPath("files")
pkgName := "testdata" goFilePath = gfile.TempDir(gtime.TimestampNanoStr(), "testdata.go")
err := gres.PackToGoFile(srcPath, goFilePath, pkgName, "/var/www/gf-site/test") pkgName = "testdata"
err = gres.PackToGoFile(srcPath, goFilePath, pkgName, "/var/www/gf-site/test")
)
t.Assert(err, nil) t.Assert(err, nil)
_ = gfile.Remove(goFilePath)
}) })
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -7,6 +7,7 @@
package gview package gview
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
htmltpl "html/template" htmltpl "html/template"
@ -22,13 +23,15 @@ import (
) )
// buildInFuncDump implements build-in template function: dump // buildInFuncDump implements build-in template function: dump
func (view *View) buildInFuncDump(values ...interface{}) (result string) { func (view *View) buildInFuncDump(values ...interface{}) string {
result += "<!--\n" buffer := bytes.NewBuffer(nil)
buffer.WriteString("<!--\n")
for _, v := range values { for _, v := range values {
result += gutil.Export(v, gutil.ExportOption{WithoutType: true}) + "\n" gutil.DumpTo(buffer, v, gutil.DumpOption{})
buffer.WriteString("\n")
} }
result += "-->\n" buffer.WriteString("-->\n")
return result return buffer.String()
} }
// buildInFuncMap implements build-in template function: map // buildInFuncMap implements build-in template function: map

View File

@ -8,7 +8,7 @@ package gview_test
import ( import (
"context" "context"
"io/ioutil" "fmt"
"os" "os"
"strings" "strings"
"testing" "testing"
@ -215,39 +215,39 @@ func Test_FuncNl2Br(t *testing.T) {
func Test_FuncInclude(t *testing.T) { func Test_FuncInclude(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
header := `<h1>HEADER</h1>` var (
main := `<h1>hello gf</h1>` header = `<h1>HEADER</h1>`
footer := `<h1>FOOTER</h1>` main = `<h1>hello gf</h1>`
layout := `{{include "header.html" .}} footer = `<h1>FOOTER</h1>`
layout = `{{include "header.html" .}}
{{include "main.html" .}} {{include "main.html" .}}
{{include "footer.html" .}}` {{include "footer.html" .}}`
templatePath := gfile.Pwd() + gfile.Separator + "template" templatePath = gfile.TempDir("template")
)
gfile.Mkdir(templatePath) gfile.Mkdir(templatePath)
defer gfile.Remove(templatePath) defer gfile.Remove(templatePath)
// headerFile, _ := gfile.Create(templatePath + gfile.Separator + "header.html")
err := ioutil.WriteFile(templatePath+gfile.Separator+"header.html", []byte(header), 0644) t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `header.html`), header))
if err != nil { t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `main.html`), main))
t.Error(err) t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `footer.html`), footer))
} t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `layout.html`), layout))
ioutil.WriteFile(templatePath+gfile.Separator+"main.html", []byte(main), 0644)
ioutil.WriteFile(templatePath+gfile.Separator+"footer.html", []byte(footer), 0644)
ioutil.WriteFile(templatePath+gfile.Separator+"layout.html", []byte(layout), 0644)
view := gview.New(templatePath) view := gview.New(templatePath)
result, err := view.Parse(context.TODO(), "notfound.html") result, err := view.Parse(context.TODO(), "notfound.html")
t.Assert(err != nil, true) t.AssertNE(err, nil)
t.Assert(result, ``) t.Assert(result, ``)
result, err = view.Parse(context.TODO(), "layout.html") result, err = view.Parse(context.TODO(), "layout.html")
t.Assert(err != nil, false) t.AssertNil(err)
t.Assert(result, `<h1>HEADER</h1> t.Assert(result, `<h1>HEADER</h1>
<h1>hello gf</h1> <h1>hello gf</h1>
<h1>FOOTER</h1>`) <h1>FOOTER</h1>`)
notfoundPath := templatePath + gfile.Separator + "template" + gfile.Separator + "notfound.html"
gfile.Mkdir(templatePath + gfile.Separator + "template") t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `notfound.html`), "notfound"))
gfile.Create(notfoundPath)
ioutil.WriteFile(notfoundPath, []byte("notfound"), 0644)
result, err = view.Parse(context.TODO(), "notfound.html") result, err = view.Parse(context.TODO(), "notfound.html")
t.Assert(err != nil, true) t.AssertNil(err)
t.Assert(result, ``) t.Assert(result, `notfound`)
}) })
} }
@ -411,6 +411,7 @@ func Test_BuildInFuncDump(t *testing.T) {
}) })
r, err := v.ParseContent(context.TODO(), "{{dump .}}") r, err := v.ParseContent(context.TODO(), "{{dump .}}")
t.Assert(err, nil) t.Assert(err, nil)
fmt.Println(r)
t.Assert(gstr.Contains(r, `"name": "john"`), true) t.Assert(gstr.Contains(r, `"name": "john"`), true)
t.Assert(gstr.Contains(r, `"score": 100`), true) t.Assert(gstr.Contains(r, `"score": 100`), true)
}) })

View File

@ -94,7 +94,7 @@ func CaseKebabScreaming(s string) string {
} }
// CaseDelimited converts a string to snake.case.delimited. // CaseDelimited converts a string to snake.case.delimited.
func CaseDelimited(s string, del uint8) string { func CaseDelimited(s string, del byte) string {
return CaseDelimitedScreaming(s, del, false) return CaseDelimitedScreaming(s, del, false)
} }

View File

@ -7,8 +7,9 @@
package gstr package gstr
import ( import (
"github.com/gogf/gf/v2/util/gconv"
"strings" "strings"
"github.com/gogf/gf/v2/util/gconv"
) )
// CompareVersion compares `a` and `b` as standard GNU version. // CompareVersion compares `a` and `b` as standard GNU version.
@ -71,12 +72,18 @@ func CompareVersion(a, b string) int {
// v4.20.0+incompatible // v4.20.0+incompatible
// etc. // etc.
func CompareVersionGo(a, b string) int { func CompareVersionGo(a, b string) int {
a = Trim(a)
b = Trim(b)
if a != "" && a[0] == 'v' { if a != "" && a[0] == 'v' {
a = a[1:] a = a[1:]
} }
if b != "" && b[0] == 'v' { if b != "" && b[0] == 'v' {
b = b[1:] b = b[1:]
} }
var (
rawA = a
rawB = b
)
if Count(a, "-") > 1 { if Count(a, "-") > 1 {
if i := PosR(a, "-"); i > 0 { if i := PosR(a, "-"); i > 0 {
a = a[:i] a = a[:i]
@ -108,6 +115,7 @@ func CompareVersionGo(a, b string) int {
if len(array1) <= 3 && len(array2) > 3 { if len(array1) <= 3 && len(array2) > 3 {
return 1 return 1
} }
diff = len(array2) - len(array1) diff = len(array2) - len(array1)
for i := 0; i < diff; i++ { for i := 0; i < diff; i++ {
array1 = append(array1, "0") array1 = append(array1, "0")
@ -128,5 +136,13 @@ func CompareVersionGo(a, b string) int {
return -1 return -1
} }
} }
// Specially in Golang:
// "v4.20.1+incompatible" < "v4.20.1"
if Contains(rawA, "incompatible") {
return -1
}
if Contains(rawB, "incompatible") {
return 1
}
return 0 return 0
} }

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@ func Test_CompareVersionGo(t *testing.T) {
t.AssertEQ(gstr.CompareVersionGo("1.0.0", "v1.0.0"), 0) t.AssertEQ(gstr.CompareVersionGo("1.0.0", "v1.0.0"), 0)
t.AssertEQ(gstr.CompareVersionGo("v0.0.0-20190626092158-b2ccc519800e", "0.0.0-20190626092158"), 0) t.AssertEQ(gstr.CompareVersionGo("v0.0.0-20190626092158-b2ccc519800e", "0.0.0-20190626092158"), 0)
t.AssertEQ(gstr.CompareVersionGo("v0.0.0-20190626092159-b2ccc519800e", "0.0.0-20190626092158"), 1) t.AssertEQ(gstr.CompareVersionGo("v0.0.0-20190626092159-b2ccc519800e", "0.0.0-20190626092158"), 1)
t.AssertEQ(gstr.CompareVersionGo("v4.20.0+incompatible", "4.20.0"), 0) t.AssertEQ(gstr.CompareVersionGo("v4.20.0+incompatible", "4.20.0"), -1)
t.AssertEQ(gstr.CompareVersionGo("v4.20.0+incompatible", "4.20.1"), -1) t.AssertEQ(gstr.CompareVersionGo("v4.20.0+incompatible", "4.20.1"), -1)
// Note that this comparison a < b. // Note that this comparison a < b.
t.AssertEQ(gstr.CompareVersionGo("v1.12.2-0.20200413154443-b17e3a6804fa", "v1.12.2"), -1) t.AssertEQ(gstr.CompareVersionGo("v1.12.2-0.20200413154443-b17e3a6804fa", "v1.12.2"), -1)

View File

@ -27,19 +27,17 @@ type iMarshalJSON interface {
MarshalJSON() ([]byte, error) MarshalJSON() ([]byte, error)
} }
// ExportOption specifies the behavior of function Export. // DumpOption specifies the behavior of function Export.
type ExportOption struct { type DumpOption struct {
WithoutType bool // WithoutType specifies exported content has no type information. WithType bool // WithType specifies dumping content with type information.
} }
// Dump prints variables `values` to stdout with more manually readable. // Dump prints variables `values` to stdout with more manually readable.
func Dump(values ...interface{}) { func Dump(values ...interface{}) {
for _, value := range values { for _, value := range values {
if s := Export(value, ExportOption{ DumpWithOption(value, DumpOption{
WithoutType: true, WithType: false,
}); s != "" { })
fmt.Println(s)
}
} }
} }
@ -47,37 +45,35 @@ func Dump(values ...interface{}) {
// Also see Dump. // Also see Dump.
func DumpWithType(values ...interface{}) { func DumpWithType(values ...interface{}) {
for _, value := range values { for _, value := range values {
if s := Export(value, ExportOption{ DumpWithOption(value, DumpOption{
WithoutType: false, WithType: true,
}); s != "" { })
fmt.Println(s)
}
} }
} }
// Export returns variables `values` as a string with more manually readable. // DumpWithOption returns variables `values` as a string with more manually readable.
func Export(value interface{}, option ExportOption) string { func DumpWithOption(value interface{}, option DumpOption) {
buffer := bytes.NewBuffer(nil) buffer := bytes.NewBuffer(nil)
ExportTo(buffer, value, ExportOption{ DumpTo(buffer, value, DumpOption{
WithoutType: option.WithoutType, WithType: option.WithType,
}) })
return buffer.String() fmt.Println(buffer.String())
} }
// ExportTo writes variables `values` as a string in to `writer` with more manually readable // DumpTo writes variables `values` as a string in to `writer` with more manually readable
func ExportTo(writer io.Writer, value interface{}, option ExportOption) { func DumpTo(writer io.Writer, value interface{}, option DumpOption) {
buffer := bytes.NewBuffer(nil) buffer := bytes.NewBuffer(nil)
doExport(value, "", buffer, doExportOption{ doDump(value, "", buffer, doDumpOption{
WithoutType: option.WithoutType, WithType: option.WithType,
}) })
_, _ = writer.Write(buffer.Bytes()) _, _ = writer.Write(buffer.Bytes())
} }
type doExportOption struct { type doDumpOption struct {
WithoutType bool WithType bool
} }
func doExport(value interface{}, indent string, buffer *bytes.Buffer, option doExportOption) { func doDump(value interface{}, indent string, buffer *bytes.Buffer, option doDumpOption) {
if value == nil { if value == nil {
buffer.WriteString(`<nil>`) buffer.WriteString(`<nil>`)
return return
@ -89,186 +85,284 @@ func doExport(value interface{}, indent string, buffer *bytes.Buffer, option doE
newIndent = indent + dumpIndent newIndent = indent + dumpIndent
) )
reflectTypeName = strings.ReplaceAll(reflectTypeName, `[]uint8`, `[]byte`) reflectTypeName = strings.ReplaceAll(reflectTypeName, `[]uint8`, `[]byte`)
if option.WithoutType { if !option.WithType {
reflectTypeName = "" reflectTypeName = ""
} }
for reflectKind == reflect.Ptr { for reflectKind == reflect.Ptr {
reflectValue = reflectValue.Elem() reflectValue = reflectValue.Elem()
reflectKind = reflectValue.Kind() reflectKind = reflectValue.Kind()
} }
var (
exportInternalInput = doDumpInternalInput{
Value: value,
Indent: indent,
NewIndent: newIndent,
Buffer: buffer,
Option: option,
ReflectValue: reflectValue,
ReflectTypeName: reflectTypeName,
}
)
switch reflectKind { switch reflectKind {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
if b, ok := value.([]byte); ok { doDumpSlice(exportInternalInput)
if option.WithoutType {
buffer.WriteString(fmt.Sprintf(`"%s"`, gstr.AddSlashes(string(b))))
} else {
buffer.WriteString(fmt.Sprintf(
`%s(%d) "%s"`,
reflectTypeName,
len(reflectValue.String()),
string(b),
))
}
return
}
if reflectValue.Len() == 0 {
if option.WithoutType {
buffer.WriteString("[]")
} else {
buffer.WriteString(fmt.Sprintf("%s(0) []", reflectTypeName))
}
return
}
if option.WithoutType {
buffer.WriteString("[\n")
} else {
buffer.WriteString(fmt.Sprintf("%s(%d) [\n", reflectTypeName, reflectValue.Len()))
}
for i := 0; i < reflectValue.Len(); i++ {
buffer.WriteString(newIndent)
doExport(reflectValue.Index(i).Interface(), newIndent, buffer, option)
buffer.WriteString(",\n")
}
buffer.WriteString(fmt.Sprintf("%s]", indent))
case reflect.Map: case reflect.Map:
var ( doDumpMap(exportInternalInput)
mapKeys = reflectValue.MapKeys()
)
if len(mapKeys) == 0 {
if option.WithoutType {
buffer.WriteString("{}")
} else {
buffer.WriteString(fmt.Sprintf("%s(0) {}", reflectTypeName))
}
return
}
var (
maxSpaceNum = 0
tmpSpaceNum = 0
mapKeyStr = ""
)
for _, key := range mapKeys {
tmpSpaceNum = len(fmt.Sprintf(`%v`, key.Interface()))
if tmpSpaceNum > maxSpaceNum {
maxSpaceNum = tmpSpaceNum
}
}
if option.WithoutType {
buffer.WriteString("{\n")
} else {
buffer.WriteString(fmt.Sprintf("%s(%d) {\n", reflectTypeName, len(mapKeys)))
}
for _, mapKey := range mapKeys {
tmpSpaceNum = len(fmt.Sprintf(`%v`, mapKey.Interface()))
if mapKey.Kind() == reflect.String {
mapKeyStr = fmt.Sprintf(`"%v"`, mapKey.Interface())
} else {
mapKeyStr = fmt.Sprintf(`%v`, mapKey.Interface())
}
if option.WithoutType {
buffer.WriteString(fmt.Sprintf(
"%s%v:%s",
newIndent,
mapKeyStr,
strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1),
))
} else {
buffer.WriteString(fmt.Sprintf(
"%s%s(%v):%s",
newIndent,
mapKey.Type().String(),
mapKeyStr,
strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1),
))
}
doExport(reflectValue.MapIndex(mapKey).Interface(), newIndent, buffer, option)
buffer.WriteString(",\n")
}
buffer.WriteString(fmt.Sprintf("%s}", indent))
case reflect.Struct: case reflect.Struct:
structFields, _ := structs.Fields(structs.FieldsInput{ doDumpStruct(exportInternalInput)
Pointer: value,
RecursiveOption: structs.RecursiveOptionEmbeddedNoTag,
})
if len(structFields) == 0 {
var (
structContentStr = ""
attributeCountStr = "0"
)
if v, ok := value.(iString); ok {
structContentStr = v.String()
} else if v, ok := value.(iMarshalJSON); ok {
b, _ := v.MarshalJSON()
structContentStr = string(b)
}
if structContentStr == "" {
structContentStr = "{}"
} else {
structContentStr = fmt.Sprintf(`"%s"`, gstr.AddSlashes(structContentStr))
attributeCountStr = fmt.Sprintf(`%d`, len(structContentStr)-2)
}
if option.WithoutType {
buffer.WriteString(structContentStr)
} else {
buffer.WriteString(fmt.Sprintf(
"%s(%s) %s",
reflectTypeName,
attributeCountStr,
structContentStr,
))
}
return
}
var (
maxSpaceNum = 0
tmpSpaceNum = 0
)
for _, field := range structFields {
tmpSpaceNum = len(field.Name())
if tmpSpaceNum > maxSpaceNum {
maxSpaceNum = tmpSpaceNum
}
}
if option.WithoutType {
buffer.WriteString("{\n")
} else {
buffer.WriteString(fmt.Sprintf("%s(%d) {\n", reflectTypeName, len(structFields)))
}
for _, field := range structFields {
tmpSpaceNum = len(fmt.Sprintf(`%v`, field.Name()))
buffer.WriteString(fmt.Sprintf(
"%s%s:%s",
newIndent,
field.Name(),
strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1),
))
doExport(field.Value.Interface(), newIndent, buffer, option)
buffer.WriteString(",\n")
}
buffer.WriteString(fmt.Sprintf("%s}", indent))
case reflect.String: case reflect.String:
s, _ := value.(string) doDumpString(exportInternalInput)
if option.WithoutType {
buffer.WriteString(fmt.Sprintf(`"%v"`, gstr.AddSlashes(s))) case reflect.Bool:
if reflectValue.Bool() {
buffer.WriteString(`true`)
} else { } else {
buffer.WriteString(fmt.Sprintf( buffer.WriteString(`false`)
`%s(%d) "%v"`,
reflectTypeName,
len(reflectValue.String()),
gstr.AddSlashes(s),
))
} }
case
reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64,
reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64,
reflect.Float32,
reflect.Float64,
reflect.Complex64,
reflect.Complex128:
doDumpNumber(exportInternalInput)
case reflect.Chan:
buffer.WriteString(`<chan>`)
case reflect.Func:
buffer.WriteString(`<func>`)
default: default:
if option.WithoutType { doDumpDefault(exportInternalInput)
buffer.WriteString(fmt.Sprintf("%v", value))
} else {
buffer.WriteString(fmt.Sprintf("%s(%v)", reflectTypeName, value))
}
} }
} }
type doDumpInternalInput struct {
Value interface{}
Indent string
NewIndent string
Buffer *bytes.Buffer
Option doDumpOption
ReflectValue reflect.Value
ReflectTypeName string
}
func doDumpSlice(in doDumpInternalInput) {
if b, ok := in.Value.([]byte); ok {
if !in.Option.WithType {
in.Buffer.WriteString(fmt.Sprintf(`"%s"`, addSlashesForString(string(b))))
} else {
in.Buffer.WriteString(fmt.Sprintf(
`%s(%d) "%s"`,
in.ReflectTypeName,
len(string(b)),
string(b),
))
}
return
}
if in.ReflectValue.Len() == 0 {
if !in.Option.WithType {
in.Buffer.WriteString("[]")
} else {
in.Buffer.WriteString(fmt.Sprintf("%s(0) []", in.ReflectTypeName))
}
return
}
if !in.Option.WithType {
in.Buffer.WriteString("[\n")
} else {
in.Buffer.WriteString(fmt.Sprintf("%s(%d) [\n", in.ReflectTypeName, in.ReflectValue.Len()))
}
for i := 0; i < in.ReflectValue.Len(); i++ {
in.Buffer.WriteString(in.NewIndent)
doDump(in.ReflectValue.Index(i).Interface(), in.NewIndent, in.Buffer, in.Option)
in.Buffer.WriteString(",\n")
}
in.Buffer.WriteString(fmt.Sprintf("%s]", in.Indent))
}
func doDumpMap(in doDumpInternalInput) {
var (
mapKeys = in.ReflectValue.MapKeys()
)
if len(mapKeys) == 0 {
if !in.Option.WithType {
in.Buffer.WriteString("{}")
} else {
in.Buffer.WriteString(fmt.Sprintf("%s(0) {}", in.ReflectTypeName))
}
return
}
var (
maxSpaceNum = 0
tmpSpaceNum = 0
mapKeyStr = ""
)
for _, key := range mapKeys {
tmpSpaceNum = len(fmt.Sprintf(`%v`, key.Interface()))
if tmpSpaceNum > maxSpaceNum {
maxSpaceNum = tmpSpaceNum
}
}
if !in.Option.WithType {
in.Buffer.WriteString("{\n")
} else {
in.Buffer.WriteString(fmt.Sprintf("%s(%d) {\n", in.ReflectTypeName, len(mapKeys)))
}
for _, mapKey := range mapKeys {
tmpSpaceNum = len(fmt.Sprintf(`%v`, mapKey.Interface()))
if mapKey.Kind() == reflect.String {
mapKeyStr = fmt.Sprintf(`"%v"`, mapKey.Interface())
} else {
mapKeyStr = fmt.Sprintf(`%v`, mapKey.Interface())
}
if !in.Option.WithType {
in.Buffer.WriteString(fmt.Sprintf(
"%s%v:%s",
in.NewIndent,
mapKeyStr,
strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1),
))
} else {
in.Buffer.WriteString(fmt.Sprintf(
"%s%s(%v):%s",
in.NewIndent,
mapKey.Type().String(),
mapKeyStr,
strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1),
))
}
doDump(in.ReflectValue.MapIndex(mapKey).Interface(), in.NewIndent, in.Buffer, in.Option)
in.Buffer.WriteString(",\n")
}
in.Buffer.WriteString(fmt.Sprintf("%s}", in.Indent))
}
func doDumpStruct(in doDumpInternalInput) {
structFields, _ := structs.Fields(structs.FieldsInput{
Pointer: in.Value,
RecursiveOption: structs.RecursiveOptionEmbedded,
})
if len(structFields) == 0 {
var (
structContentStr = ""
attributeCountStr = "0"
)
if v, ok := in.Value.(iString); ok {
structContentStr = v.String()
} else if v, ok := in.Value.(iMarshalJSON); ok {
b, _ := v.MarshalJSON()
structContentStr = string(b)
}
if structContentStr == "" {
structContentStr = "{}"
} else {
structContentStr = fmt.Sprintf(`"%s"`, addSlashesForString(structContentStr))
attributeCountStr = fmt.Sprintf(`%d`, len(structContentStr)-2)
}
if !in.Option.WithType {
in.Buffer.WriteString(structContentStr)
} else {
in.Buffer.WriteString(fmt.Sprintf(
"%s(%s) %s",
in.ReflectTypeName,
attributeCountStr,
structContentStr,
))
}
return
}
var (
maxSpaceNum = 0
tmpSpaceNum = 0
)
for _, field := range structFields {
tmpSpaceNum = len(field.Name())
if tmpSpaceNum > maxSpaceNum {
maxSpaceNum = tmpSpaceNum
}
}
if !in.Option.WithType {
in.Buffer.WriteString("{\n")
} else {
in.Buffer.WriteString(fmt.Sprintf("%s(%d) {\n", in.ReflectTypeName, len(structFields)))
}
for _, field := range structFields {
tmpSpaceNum = len(fmt.Sprintf(`%v`, field.Name()))
in.Buffer.WriteString(fmt.Sprintf(
"%s%s:%s",
in.NewIndent,
field.Name(),
strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1),
))
doDump(field.Value.Interface(), in.NewIndent, in.Buffer, in.Option)
in.Buffer.WriteString(",\n")
}
in.Buffer.WriteString(fmt.Sprintf("%s}", in.Indent))
}
func doDumpNumber(in doDumpInternalInput) {
if v, ok := in.Value.(iString); ok {
s := v.String()
if !in.Option.WithType {
in.Buffer.WriteString(fmt.Sprintf(`"%v"`, addSlashesForString(s)))
} else {
in.Buffer.WriteString(fmt.Sprintf(
`%s(%d) "%v"`,
in.ReflectTypeName,
len(s),
addSlashesForString(s),
))
}
} else {
doDumpDefault(in)
}
}
func doDumpString(in doDumpInternalInput) {
s := in.ReflectValue.String()
if !in.Option.WithType {
in.Buffer.WriteString(fmt.Sprintf(`"%v"`, addSlashesForString(s)))
} else {
in.Buffer.WriteString(fmt.Sprintf(
`%s(%d) "%v"`,
in.ReflectTypeName,
len(s),
addSlashesForString(s),
))
}
}
func doDumpDefault(in doDumpInternalInput) {
s := fmt.Sprintf("%v", in.Value)
s = gstr.Trim(s, `<>`)
if !in.Option.WithType {
in.Buffer.WriteString(s)
} else {
in.Buffer.WriteString(fmt.Sprintf("%s(%s)", in.ReflectTypeName, s))
}
}
func addSlashesForString(s string) string {
return gstr.ReplaceByMap(s, map[string]string{
`"`: `\"`,
"\r": `\r`,
"\t": `\t`,
"\n": `\n`,
})
}