mirror of
https://gitee.com/johng/gf.git
synced 2024-12-04 05:07:44 +08:00
非test文件 恢复 原样
This commit is contained in:
parent
d305d25935
commit
80cf3e833b
@ -17,17 +17,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Separator char for hierarchical data access.
|
// Separator char for hierarchical data access.
|
||||||
gDEFAULT_SPLIT_CHAR = '.'
|
gDEFAULT_SPLIT_CHAR = '.'
|
||||||
)
|
)
|
||||||
|
|
||||||
// The customized JSON struct.
|
// The customized JSON struct.
|
||||||
type Json struct {
|
type Json struct {
|
||||||
mu *rwmutex.RWMutex
|
mu *rwmutex.RWMutex
|
||||||
p *interface{} // Pointer for hierarchical data access, it's the root of data in default.
|
p *interface{} // Pointer for hierarchical data access, it's the root of data in default.
|
||||||
c byte // Char separator('.' in default).
|
c byte // Char separator('.' in default).
|
||||||
vc bool // Violence Check(false in default), which is used to access data
|
vc bool // Violence Check(false in default), which is used to access data
|
||||||
// when the hierarchical data key contains separator char.
|
// when the hierarchical data key contains separator char.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set <value> by <pattern>.
|
// Set <value> by <pattern>.
|
||||||
@ -35,306 +35,300 @@ type Json struct {
|
|||||||
// 1. If value is nil and removed is true, means deleting this value;
|
// 1. If value is nil and removed is true, means deleting this value;
|
||||||
// 2. It's quite complicated in hierarchical data search, node creating and data assignment;
|
// 2. It's quite complicated in hierarchical data search, node creating and data assignment;
|
||||||
func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||||
array := strings.Split(pattern, string(j.c))
|
array := strings.Split(pattern, string(j.c))
|
||||||
length := len(array)
|
length := len(array)
|
||||||
value = j.convertValue(value)
|
value = j.convertValue(value)
|
||||||
// 初始化判断
|
// 初始化判断
|
||||||
if *j.p == nil {
|
if *j.p == nil {
|
||||||
if gstr.IsNumeric(array[0]) {
|
if gstr.IsNumeric(array[0]) {
|
||||||
*j.p = make([]interface{}, 0)
|
*j.p = make([]interface{}, 0)
|
||||||
} else {
|
} else {
|
||||||
*j.p = make(map[string]interface{})
|
*j.p = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var pparent *interface{} = nil // 父级元素项(设置时需要根据子级的内容确定数据类型,所以必须记录父级)
|
var pparent *interface{} = nil // 父级元素项(设置时需要根据子级的内容确定数据类型,所以必须记录父级)
|
||||||
var pointer *interface{} = j.p // 当前操作层级项
|
var pointer *interface{} = j.p // 当前操作层级项
|
||||||
j.mu.Lock()
|
j.mu.Lock()
|
||||||
defer j.mu.Unlock()
|
defer j.mu.Unlock()
|
||||||
for i := 0; i < length; i++ {
|
for i:= 0; i < length; i++ {
|
||||||
switch (*pointer).(type) {
|
switch (*pointer).(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
if i == length-1 {
|
if i == length - 1 {
|
||||||
if removed && value == nil {
|
if removed && value == nil {
|
||||||
// 删除map元素
|
// 删除map元素
|
||||||
delete((*pointer).(map[string]interface{}), array[i])
|
delete((*pointer).(map[string]interface{}), array[i])
|
||||||
} else {
|
} else {
|
||||||
(*pointer).(map[string]interface{})[array[i]] = value
|
(*pointer).(map[string]interface{})[array[i]] = value
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 当键名不存在的情况这里会进行处理
|
// 当键名不存在的情况这里会进行处理
|
||||||
if v, ok := (*pointer).(map[string]interface{})[array[i]]; !ok {
|
if v, ok := (*pointer).(map[string]interface{})[array[i]]; !ok {
|
||||||
if removed && value == nil {
|
if removed && value == nil {
|
||||||
goto done
|
goto done
|
||||||
}
|
}
|
||||||
// 创建新节点
|
// 创建新节点
|
||||||
if gstr.IsNumeric(array[i+1]) {
|
if gstr.IsNumeric(array[i + 1]) {
|
||||||
// 创建array节点
|
// 创建array节点
|
||||||
n, _ := strconv.Atoi(array[i+1])
|
n, _ := strconv.Atoi(array[i + 1])
|
||||||
var v interface{} = make([]interface{}, n+1)
|
var v interface{} = make([]interface{}, n + 1)
|
||||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||||
pointer = &v
|
pointer = &v
|
||||||
} else {
|
} else {
|
||||||
// 创建map节点
|
// 创建map节点
|
||||||
var v interface{} = make(map[string]interface{})
|
var v interface{} = make(map[string]interface{})
|
||||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||||
pointer = &v
|
pointer = &v
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pparent = pointer
|
pparent = pointer
|
||||||
pointer = &v
|
pointer = &v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
// 键名与当前指针类型不符合,需要执行**覆盖操作**
|
// 键名与当前指针类型不符合,需要执行**覆盖操作**
|
||||||
if !gstr.IsNumeric(array[i]) {
|
if !gstr.IsNumeric(array[i]) {
|
||||||
if i == length-1 {
|
if i == length - 1 {
|
||||||
*pointer = map[string]interface{}{array[i]: value}
|
*pointer = map[string]interface{}{ array[i] : value }
|
||||||
} else {
|
} else {
|
||||||
var v interface{} = make(map[string]interface{})
|
var v interface{} = make(map[string]interface{})
|
||||||
*pointer = v
|
*pointer = v
|
||||||
pparent = pointer
|
pparent = pointer
|
||||||
pointer = &v
|
pointer = &v
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
valn, err := strconv.Atoi(array[i])
|
valn, err := strconv.Atoi(array[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// 叶子节点
|
// 叶子节点
|
||||||
if i == length-1 {
|
if i == length - 1 {
|
||||||
if len((*pointer).([]interface{})) > valn {
|
if len((*pointer).([]interface{})) > valn {
|
||||||
if removed && value == nil {
|
if removed && value == nil {
|
||||||
// 删除数据元素
|
// 删除数据元素
|
||||||
j.setPointerWithValue(pparent, array[i-1], append((*pointer).([]interface{})[:valn], (*pointer).([]interface{})[valn+1:]...))
|
j.setPointerWithValue(pparent, array[i - 1], append((*pointer).([]interface{})[ : valn], (*pointer).([]interface{})[valn + 1 : ]...))
|
||||||
} else {
|
} else {
|
||||||
(*pointer).([]interface{})[valn] = value
|
(*pointer).([]interface{})[valn] = value
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if removed && value == nil {
|
if removed && value == nil {
|
||||||
goto done
|
goto done
|
||||||
}
|
}
|
||||||
if pparent == nil {
|
if pparent == nil {
|
||||||
// 表示根节点
|
// 表示根节点
|
||||||
j.setPointerWithValue(pointer, array[i], value)
|
j.setPointerWithValue(pointer, array[i], value)
|
||||||
} else {
|
} else {
|
||||||
// 非根节点
|
// 非根节点
|
||||||
s := make([]interface{}, valn+1)
|
s := make([]interface{}, valn + 1)
|
||||||
copy(s, (*pointer).([]interface{}))
|
copy(s, (*pointer).([]interface{}))
|
||||||
s[valn] = value
|
s[valn] = value
|
||||||
j.setPointerWithValue(pparent, array[i-1], s)
|
j.setPointerWithValue(pparent, array[i - 1], s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if gstr.IsNumeric(array[i+1]) {
|
if gstr.IsNumeric(array[i + 1]) {
|
||||||
n, _ := strconv.Atoi(array[i+1])
|
n, _ := strconv.Atoi(array[i + 1])
|
||||||
if len((*pointer).([]interface{})) > valn {
|
if len((*pointer).([]interface{})) > valn {
|
||||||
(*pointer).([]interface{})[valn] = make([]interface{}, n+1)
|
(*pointer).([]interface{})[valn] = make([]interface{}, n + 1)
|
||||||
pparent = pointer
|
pparent = pointer
|
||||||
pointer = &(*pointer).([]interface{})[valn]
|
pointer = &(*pointer).([]interface{})[valn]
|
||||||
} else {
|
} else {
|
||||||
if removed && value == nil {
|
if removed && value == nil {
|
||||||
goto done
|
goto done
|
||||||
}
|
}
|
||||||
var v interface{} = make([]interface{}, n+1)
|
var v interface{} = make([]interface{}, n + 1)
|
||||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||||
pointer = &v
|
pointer = &v
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var v interface{} = make(map[string]interface{})
|
var v interface{} = make(map[string]interface{})
|
||||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||||
pointer = &v
|
pointer = &v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果当前指针指向的变量不是引用类型的,
|
// 如果当前指针指向的变量不是引用类型的,
|
||||||
// 那么修改变量必须通过父级进行修改,即 pparent
|
// 那么修改变量必须通过父级进行修改,即 pparent
|
||||||
default:
|
default:
|
||||||
if removed && value == nil {
|
if removed && value == nil {
|
||||||
goto done
|
goto done
|
||||||
}
|
}
|
||||||
if gstr.IsNumeric(array[i]) {
|
if gstr.IsNumeric(array[i]) {
|
||||||
n, _ := strconv.Atoi(array[i])
|
n, _ := strconv.Atoi(array[i])
|
||||||
s := make([]interface{}, n+1)
|
s := make([]interface{}, n + 1)
|
||||||
if i == length-1 {
|
if i == length - 1 {
|
||||||
s[n] = value
|
s[n] = value
|
||||||
}
|
}
|
||||||
if pparent != nil {
|
if pparent != nil {
|
||||||
pparent = j.setPointerWithValue(pparent, array[i-1], s)
|
pparent = j.setPointerWithValue(pparent, array[i - 1], s)
|
||||||
} else {
|
} else {
|
||||||
*pointer = s
|
*pointer = s
|
||||||
pparent = pointer
|
pparent = pointer
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var v interface{} = make(map[string]interface{})
|
var v interface{} = make(map[string]interface{})
|
||||||
if i == length-1 {
|
if i == length - 1 {
|
||||||
v = map[string]interface{}{
|
v = map[string]interface{}{
|
||||||
array[i]: value,
|
array[i] : value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pparent != nil {
|
if pparent != nil {
|
||||||
pparent = j.setPointerWithValue(pparent, array[i-1], v)
|
pparent = j.setPointerWithValue(pparent, array[i - 1], v)
|
||||||
} else {
|
} else {
|
||||||
*pointer = v
|
*pointer = v
|
||||||
pparent = pointer
|
pparent = pointer
|
||||||
}
|
}
|
||||||
pointer = &v
|
pointer = &v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert <value> to map[string]interface{} or []interface{},
|
// Convert <value> to map[string]interface{} or []interface{},
|
||||||
// which can be supported for hierarchical data access.
|
// which can be supported for hierarchical data access.
|
||||||
func (j *Json) convertValue(value interface{}) interface{} {
|
func (j *Json) convertValue(value interface{}) interface{} {
|
||||||
switch value.(type) {
|
switch value.(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
return value
|
return value
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
return value
|
return value
|
||||||
default:
|
default:
|
||||||
rv := reflect.ValueOf(value)
|
rv := reflect.ValueOf(value)
|
||||||
kind := rv.Kind()
|
kind := rv.Kind()
|
||||||
if kind == reflect.Ptr {
|
if kind == reflect.Ptr {
|
||||||
rv = rv.Elem()
|
rv = rv.Elem()
|
||||||
kind = rv.Kind()
|
kind = rv.Kind()
|
||||||
}
|
}
|
||||||
switch kind {
|
switch kind {
|
||||||
case reflect.Array:
|
case reflect.Array: return gconv.Interfaces(value)
|
||||||
return gconv.Interfaces(value)
|
case reflect.Slice: return gconv.Interfaces(value)
|
||||||
case reflect.Slice:
|
case reflect.Map: return gconv.Map(value)
|
||||||
return gconv.Interfaces(value)
|
case reflect.Struct: return gconv.Map(value)
|
||||||
case reflect.Map:
|
default:
|
||||||
return gconv.Map(value)
|
// Use json decode/encode at last.
|
||||||
case reflect.Struct:
|
b, _ := Encode(value)
|
||||||
return gconv.Map(value)
|
v, _ := Decode(b)
|
||||||
default:
|
return v
|
||||||
// Use json decode/encode at last.
|
}
|
||||||
b, _ := Encode(value)
|
}
|
||||||
v, _ := Decode(b)
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set <key>:<value> to <pointer>, the <key> may be a map key or slice index.
|
// Set <key>:<value> to <pointer>, the <key> may be a map key or slice index.
|
||||||
// It returns the pointer to the new value set.
|
// It returns the pointer to the new value set.
|
||||||
func (j *Json) setPointerWithValue(pointer *interface{}, key string, value interface{}) *interface{} {
|
func (j *Json) setPointerWithValue(pointer *interface{}, key string, value interface{}) *interface{} {
|
||||||
switch (*pointer).(type) {
|
switch (*pointer).(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
(*pointer).(map[string]interface{})[key] = value
|
(*pointer).(map[string]interface{})[key] = value
|
||||||
return &value
|
return &value
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
n, _ := strconv.Atoi(key)
|
n, _ := strconv.Atoi(key)
|
||||||
if len((*pointer).([]interface{})) > n {
|
if len((*pointer).([]interface{})) > n {
|
||||||
(*pointer).([]interface{})[n] = value
|
(*pointer).([]interface{})[n] = value
|
||||||
return &(*pointer).([]interface{})[n]
|
return &(*pointer).([]interface{})[n]
|
||||||
} else {
|
} else {
|
||||||
s := make([]interface{}, n+1)
|
s := make([]interface{}, n + 1)
|
||||||
copy(s, (*pointer).([]interface{}))
|
copy(s, (*pointer).([]interface{}))
|
||||||
s[n] = value
|
s[n] = value
|
||||||
*pointer = s
|
*pointer = s
|
||||||
return &s[n]
|
return &s[n]
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
*pointer = value
|
*pointer = value
|
||||||
}
|
}
|
||||||
return pointer
|
return pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a pointer to the value by specified <pattern>.
|
// Get a pointer to the value by specified <pattern>.
|
||||||
func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
||||||
if j.vc {
|
if j.vc {
|
||||||
return j.getPointerByPatternWithViolenceCheck(pattern)
|
return j.getPointerByPatternWithViolenceCheck(pattern)
|
||||||
} else {
|
} else {
|
||||||
return j.getPointerByPatternWithoutViolenceCheck(pattern)
|
return j.getPointerByPatternWithoutViolenceCheck(pattern)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a pointer to the value of specified <pattern> with violence check.
|
// Get a pointer to the value of specified <pattern> with violence check.
|
||||||
func (j *Json) getPointerByPatternWithViolenceCheck(pattern string) *interface{} {
|
func (j *Json) getPointerByPatternWithViolenceCheck(pattern string) *interface{} {
|
||||||
//todo 此判断冗余
|
if !j.vc {
|
||||||
if !j.vc {
|
return j.getPointerByPatternWithoutViolenceCheck(pattern)
|
||||||
return j.getPointerByPatternWithoutViolenceCheck(pattern)
|
}
|
||||||
}
|
index := len(pattern)
|
||||||
index := len(pattern)
|
start := 0
|
||||||
start := 0
|
length := 0
|
||||||
length := 0
|
pointer := j.p
|
||||||
pointer := j.p
|
if index == 0 {
|
||||||
if index == 0 {
|
return pointer
|
||||||
return pointer
|
}
|
||||||
}
|
for {
|
||||||
for {
|
if r := j.checkPatternByPointer(pattern[start:index], pointer); r != nil {
|
||||||
if r := j.checkPatternByPointer(pattern[start:index], pointer); r != nil {
|
length += index - start
|
||||||
length += index - start
|
if start > 0 {
|
||||||
if start > 0 {
|
length += 1
|
||||||
length += 1
|
}
|
||||||
}
|
start = index + 1
|
||||||
start = index + 1
|
index = len(pattern)
|
||||||
index = len(pattern)
|
if length == len(pattern) {
|
||||||
if length == len(pattern) {
|
return r
|
||||||
return r
|
} else {
|
||||||
} else {
|
pointer = r
|
||||||
pointer = r
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
// Get the position for next separator char.
|
||||||
// Get the position for next separator char.
|
index = strings.LastIndexByte(pattern[start:index], j.c)
|
||||||
index = strings.LastIndexByte(pattern[start:index], j.c)
|
if index != -1 && length > 0 {
|
||||||
if index != -1 && length > 0 {
|
index += length + 1
|
||||||
index += length + 1
|
}
|
||||||
}
|
}
|
||||||
}
|
if start >= index {
|
||||||
if start >= index {
|
break
|
||||||
break
|
}
|
||||||
}
|
}
|
||||||
}
|
return nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a pointer to the value of specified <pattern>, with no violence check.
|
// Get a pointer to the value of specified <pattern>, with no violence check.
|
||||||
func (j *Json) getPointerByPatternWithoutViolenceCheck(pattern string) *interface{} {
|
func (j *Json) getPointerByPatternWithoutViolenceCheck(pattern string) *interface{} {
|
||||||
//todo 此判断冗余
|
if j.vc {
|
||||||
if j.vc {
|
return j.getPointerByPatternWithViolenceCheck(pattern)
|
||||||
return j.getPointerByPatternWithViolenceCheck(pattern)
|
}
|
||||||
}
|
pointer := j.p
|
||||||
pointer := j.p
|
if len(pattern) == 0 {
|
||||||
if len(pattern) == 0 {
|
return pointer
|
||||||
return pointer
|
}
|
||||||
}
|
array := strings.Split(pattern, string(j.c))
|
||||||
array := strings.Split(pattern, string(j.c))
|
for k, v := range array {
|
||||||
for k, v := range array {
|
if r := j.checkPatternByPointer(v, pointer); r != nil {
|
||||||
if r := j.checkPatternByPointer(v, pointer); r != nil {
|
if k == len(array) - 1 {
|
||||||
if k == len(array)-1 {
|
return r
|
||||||
return r
|
} else {
|
||||||
} else {
|
pointer = r
|
||||||
pointer = r
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
break
|
||||||
break
|
}
|
||||||
}
|
}
|
||||||
}
|
return nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether there's value by <key> in specified <pointer>.
|
// Check whether there's value by <key> in specified <pointer>.
|
||||||
// It returns a pointer to the value.
|
// It returns a pointer to the value.
|
||||||
func (j *Json) checkPatternByPointer(key string, pointer *interface{}) *interface{} {
|
func (j *Json) checkPatternByPointer(key string, pointer *interface{}) *interface{} {
|
||||||
switch (*pointer).(type) {
|
switch (*pointer).(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
if v, ok := (*pointer).(map[string]interface{})[key]; ok {
|
if v, ok := (*pointer).(map[string]interface{})[key]; ok {
|
||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
if gstr.IsNumeric(key) {
|
if gstr.IsNumeric(key) {
|
||||||
n, err := strconv.Atoi(key)
|
n, err := strconv.Atoi(key)
|
||||||
if err == nil && len((*pointer).([]interface{})) > n {
|
if err == nil && len((*pointer).([]interface{})) > n {
|
||||||
return &(*pointer).([]interface{})[n]
|
return &(*pointer).([]interface{})[n]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -27,165 +27,163 @@ import (
|
|||||||
// or it will make no sense.
|
// or it will make no sense.
|
||||||
// The <unsafe> param specifies whether using this Json object
|
// The <unsafe> param specifies whether using this Json object
|
||||||
// in un-concurrent-safe context, which is false in default.
|
// in un-concurrent-safe context, which is false in default.
|
||||||
func New(data interface{}, unsafe ...bool) *Json {
|
func New(data interface{}, unsafe...bool) *Json {
|
||||||
j := (*Json)(nil)
|
j := (*Json)(nil)
|
||||||
switch data.(type) {
|
switch data.(type) {
|
||||||
case string, []byte:
|
case string, []byte:
|
||||||
if r, err := LoadContent(gconv.Bytes(data)); err == nil {
|
if r, err := LoadContent(gconv.Bytes(data)); err == nil {
|
||||||
j = r
|
j = r
|
||||||
} else {
|
} else {
|
||||||
j = &Json{
|
j = &Json {
|
||||||
p: &data,
|
p : &data,
|
||||||
c: byte(gDEFAULT_SPLIT_CHAR),
|
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||||
vc: false,
|
vc : false ,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
rv := reflect.ValueOf(data)
|
rv := reflect.ValueOf(data)
|
||||||
kind := rv.Kind()
|
kind := rv.Kind()
|
||||||
if kind == reflect.Ptr {
|
if kind == reflect.Ptr {
|
||||||
rv = rv.Elem()
|
rv = rv.Elem()
|
||||||
kind = rv.Kind()
|
kind = rv.Kind()
|
||||||
}
|
}
|
||||||
switch kind {
|
switch kind {
|
||||||
case reflect.Slice:
|
case reflect.Slice: fallthrough
|
||||||
fallthrough
|
case reflect.Array:
|
||||||
case reflect.Array:
|
i := interface{}(nil)
|
||||||
i := interface{}(nil)
|
i = gconv.Interfaces(data)
|
||||||
i = gconv.Interfaces(data)
|
j = &Json {
|
||||||
j = &Json{
|
p : &i,
|
||||||
p: &i,
|
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||||
c: byte(gDEFAULT_SPLIT_CHAR),
|
vc : false ,
|
||||||
vc: false,
|
}
|
||||||
}
|
case reflect.Map: fallthrough
|
||||||
case reflect.Map:
|
case reflect.Struct:
|
||||||
fallthrough
|
i := interface{}(nil)
|
||||||
case reflect.Struct:
|
i = gconv.Map(data, "json")
|
||||||
i := interface{}(nil)
|
j = &Json {
|
||||||
i = gconv.Map(data, "json")
|
p : &i,
|
||||||
j = &Json{
|
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||||
p: &i,
|
vc : false ,
|
||||||
c: byte(gDEFAULT_SPLIT_CHAR),
|
}
|
||||||
vc: false,
|
default:
|
||||||
}
|
j = &Json {
|
||||||
default:
|
p : &data,
|
||||||
j = &Json{
|
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||||
p: &data,
|
vc : false ,
|
||||||
c: byte(gDEFAULT_SPLIT_CHAR),
|
}
|
||||||
vc: false,
|
}
|
||||||
}
|
}
|
||||||
}
|
j.mu = rwmutex.New(unsafe...)
|
||||||
}
|
return j
|
||||||
j.mu = rwmutex.New(unsafe...)
|
|
||||||
return j
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUnsafe creates a un-concurrent-safe Json object.
|
// NewUnsafe creates a un-concurrent-safe Json object.
|
||||||
func NewUnsafe(data ...interface{}) *Json {
|
func NewUnsafe(data...interface{}) *Json {
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
return New(data[0], true)
|
return New(data[0], true)
|
||||||
}
|
}
|
||||||
return New(nil, true)
|
return New(nil, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid checks whether <data> is a valid JSON data type.
|
// Valid checks whether <data> is a valid JSON data type.
|
||||||
func Valid(data interface{}) bool {
|
func Valid(data interface{}) bool {
|
||||||
return json.Valid(gconv.Bytes(data))
|
return json.Valid(gconv.Bytes(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode encodes <value> to JSON data type of bytes.
|
// Encode encodes <value> to JSON data type of bytes.
|
||||||
func Encode(value interface{}) ([]byte, error) {
|
func Encode(value interface{}) ([]byte, error) {
|
||||||
return json.Marshal(value)
|
return json.Marshal(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode decodes <data>(string/[]byte) to golang variable.
|
// Decode decodes <data>(string/[]byte) to golang variable.
|
||||||
func Decode(data interface{}) (interface{}, error) {
|
func Decode(data interface{}) (interface{}, error) {
|
||||||
var value interface{}
|
var value interface{}
|
||||||
if err := DecodeTo(gconv.Bytes(data), &value); err != nil {
|
if err := DecodeTo(gconv.Bytes(data), &value); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode decodes <data>(string/[]byte) to specified golang variable <v>.
|
// Decode decodes <data>(string/[]byte) to specified golang variable <v>.
|
||||||
// The <v> should be a pointer type.
|
// The <v> should be a pointer type.
|
||||||
func DecodeTo(data interface{}, v interface{}) error {
|
func DecodeTo(data interface{}, v interface{}) error {
|
||||||
decoder := json.NewDecoder(bytes.NewReader(gconv.Bytes(data)))
|
decoder := json.NewDecoder(bytes.NewReader(gconv.Bytes(data)))
|
||||||
decoder.UseNumber()
|
decoder.UseNumber()
|
||||||
return decoder.Decode(v)
|
return decoder.Decode(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeToJson codes <data>(string/[]byte) to a Json object.
|
// DecodeToJson codes <data>(string/[]byte) to a Json object.
|
||||||
func DecodeToJson(data interface{}, unsafe ...bool) (*Json, error) {
|
func DecodeToJson(data interface{}, unsafe...bool) (*Json, error) {
|
||||||
if v, err := Decode(gconv.Bytes(data)); err != nil {
|
if v, err := Decode(gconv.Bytes(data)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
return New(v, unsafe...), nil
|
return New(v, unsafe...), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load loads content from specified file <path>,
|
// Load loads content from specified file <path>,
|
||||||
// and creates a Json object from its content.
|
// and creates a Json object from its content.
|
||||||
func Load(path string, unsafe ...bool) (*Json, error) {
|
func Load(path string, unsafe...bool) (*Json, error) {
|
||||||
return LoadContent(gfcache.GetBinContents(path), unsafe...)
|
return LoadContent(gfcache.GetBinContents(path), unsafe...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadContent creates a Json object from given content,
|
// LoadContent creates a Json object from given content,
|
||||||
// it checks the data type of <content> automatically,
|
// it checks the data type of <content> automatically,
|
||||||
// supporting JSON, XML, YAML and TOML types of data.
|
// supporting JSON, XML, YAML and TOML types of data.
|
||||||
func LoadContent(data interface{}, unsafe ...bool) (*Json, error) {
|
func LoadContent(data interface{}, unsafe...bool) (*Json, error) {
|
||||||
var err error
|
var err error
|
||||||
var result interface{}
|
var result interface{}
|
||||||
b := gconv.Bytes(data)
|
b := gconv.Bytes(data)
|
||||||
t := ""
|
t := ""
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return New(nil, unsafe...), nil
|
return New(nil, unsafe...), nil
|
||||||
}
|
}
|
||||||
// auto check data type
|
// auto check data type
|
||||||
if json.Valid(b) {
|
if json.Valid(b) {
|
||||||
t = "json"
|
t = "json"
|
||||||
} else if gregex.IsMatch(`^<.+>[\S\s]+<.+>$`, b) {
|
} else if gregex.IsMatch(`^<.+>[\S\s]+<.+>$`, b) {
|
||||||
t = "xml"
|
t = "xml"
|
||||||
} else if gregex.IsMatch(`^[\s\t]*\w+\s*:\s*.+`, b) || gregex.IsMatch(`\n[\s\t]*\w+\s*:\s*.+`, b) {
|
} else if gregex.IsMatch(`^[\s\t]*\w+\s*:\s*.+`, b) || gregex.IsMatch(`\n[\s\t]*\w+\s*:\s*.+`, b) {
|
||||||
t = "yml"
|
t = "yml"
|
||||||
} else if gregex.IsMatch(`^[\s\t]*\w+\s*=\s*.+`, b) || gregex.IsMatch(`\n[\s\t]*\w+\s*=\s*.+`, b) {
|
} else if gregex.IsMatch(`^[\s\t]*\w+\s*=\s*.+`, b) || gregex.IsMatch(`\n[\s\t]*\w+\s*=\s*.+`, b) {
|
||||||
t = "toml"
|
t = "toml"
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.New("unsupported data type")
|
return nil, errors.New("unsupported data type")
|
||||||
}
|
}
|
||||||
// convert to json type data
|
// convert to json type data
|
||||||
switch t {
|
switch t {
|
||||||
case "json", ".json":
|
case "json", ".json":
|
||||||
// ok
|
// ok
|
||||||
case "xml", ".xml":
|
case "xml", ".xml":
|
||||||
// TODO UseNumber
|
// TODO UseNumber
|
||||||
b, err = gxml.ToJson(b)
|
b, err = gxml.ToJson(b)
|
||||||
|
|
||||||
case "yml", "yaml", ".yml", ".yaml":
|
case "yml", "yaml", ".yml", ".yaml":
|
||||||
// TODO UseNumber
|
// TODO UseNumber
|
||||||
b, err = gyaml.ToJson(b)
|
b, err = gyaml.ToJson(b)
|
||||||
|
|
||||||
case "toml", ".toml":
|
case "toml", ".toml":
|
||||||
// TODO UseNumber
|
// TODO UseNumber
|
||||||
b, err = gtoml.ToJson(b)
|
b, err = gtoml.ToJson(b)
|
||||||
//todo 不可达
|
|
||||||
default:
|
default:
|
||||||
err = errors.New("nonsupport type " + t)
|
err = errors.New("nonsupport type " + t)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if result == nil {
|
if result == nil {
|
||||||
decoder := json.NewDecoder(bytes.NewReader(b))
|
decoder := json.NewDecoder(bytes.NewReader(b))
|
||||||
decoder.UseNumber()
|
decoder.UseNumber()
|
||||||
if err := decoder.Decode(&result); err != nil {
|
if err := decoder.Decode(&result); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
switch result.(type) {
|
switch result.(type) {
|
||||||
case string, []byte:
|
case string, []byte:
|
||||||
return nil, fmt.Errorf(`json decoding failed for content: %s`, string(b))
|
return nil, fmt.Errorf(`json decoding failed for content: %s`, string(b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return New(result, unsafe...), nil
|
return New(result, unsafe...), nil
|
||||||
}
|
}
|
||||||
|
@ -26,32 +26,32 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Default configuration file name.
|
// Default configuration file name.
|
||||||
DEFAULT_CONFIG_FILE = "config.toml"
|
DEFAULT_CONFIG_FILE = "config.toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configuration struct.
|
// Configuration struct.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
name *gtype.String // Default configuration file name.
|
name *gtype.String // Default configuration file name.
|
||||||
paths *garray.StringArray // Searching path array.
|
paths *garray.StringArray // Searching path array.
|
||||||
jsons *gmap.StrAnyMap // The pared JSON objects for configuration files.
|
jsons *gmap.StrAnyMap // The pared JSON objects for configuration files.
|
||||||
vc *gtype.Bool // Whether do violence check in value index searching.
|
vc *gtype.Bool // Whether do violence check in value index searching.
|
||||||
// It affects the performance when set true(false in default).
|
// It affects the performance when set true(false in default).
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new configuration management object.
|
// New returns a new configuration management object.
|
||||||
// The param <file> specifies the default configuration file name for reading.
|
// The param <file> specifies the default configuration file name for reading.
|
||||||
func New(file ...string) *Config {
|
func New(file...string) *Config {
|
||||||
name := DEFAULT_CONFIG_FILE
|
name := DEFAULT_CONFIG_FILE
|
||||||
if len(file) > 0 {
|
if len(file) > 0 {
|
||||||
name = file[0]
|
name = file[0]
|
||||||
}
|
}
|
||||||
c := &Config{
|
c := &Config {
|
||||||
name: gtype.NewString(name),
|
name : gtype.NewString(name),
|
||||||
paths: garray.NewStringArray(),
|
paths : garray.NewStringArray(),
|
||||||
jsons: gmap.NewStrAnyMap(),
|
jsons : gmap.NewStrAnyMap(),
|
||||||
vc: gtype.NewBool(),
|
vc : gtype.NewBool(),
|
||||||
}
|
}
|
||||||
// Customized dir path from env/cmd.
|
// Customized dir path from env/cmd.
|
||||||
if envPath := cmdenv.Get("gf.gcfg.path").String(); envPath != "" {
|
if envPath := cmdenv.Get("gf.gcfg.path").String(); envPath != "" {
|
||||||
if gfile.Exists(envPath) {
|
if gfile.Exists(envPath) {
|
||||||
@ -71,85 +71,85 @@ func New(file ...string) *Config {
|
|||||||
_ = c.AddPath(mainPath)
|
_ = c.AddPath(mainPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// filePath returns the absolute configuration file path for the given filename by <file>.
|
// filePath returns the absolute configuration file path for the given filename by <file>.
|
||||||
func (c *Config) filePath(file ...string) (path string) {
|
func (c *Config) filePath(file...string) (path string) {
|
||||||
name := c.name.Val()
|
name := c.name.Val()
|
||||||
if len(file) > 0 {
|
if len(file) > 0 {
|
||||||
name = file[0]
|
name = file[0]
|
||||||
}
|
}
|
||||||
path = c.FilePath(name)
|
path = c.FilePath(name)
|
||||||
if path == "" {
|
if path == "" {
|
||||||
buffer := bytes.NewBuffer(nil)
|
buffer := bytes.NewBuffer(nil)
|
||||||
if c.paths.Len() > 0 {
|
if c.paths.Len() > 0 {
|
||||||
buffer.WriteString(fmt.Sprintf("[gcfg] cannot find config file \"%s\" in following paths:", name))
|
buffer.WriteString(fmt.Sprintf("[gcfg] cannot find config file \"%s\" in following paths:", name))
|
||||||
c.paths.RLockFunc(func(array []string) {
|
c.paths.RLockFunc(func(array []string) {
|
||||||
index := 1
|
index := 1
|
||||||
for _, v := range array {
|
for _, v := range array {
|
||||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v))
|
buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v))
|
||||||
index++
|
index++
|
||||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v+gfile.Separator+"config"))
|
buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v + gfile.Separator + "config"))
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(fmt.Sprintf("[gcfg] cannot find config file \"%s\" with no path set/add", name))
|
buffer.WriteString(fmt.Sprintf("[gcfg] cannot find config file \"%s\" with no path set/add", name))
|
||||||
}
|
}
|
||||||
glog.Error(buffer.String())
|
glog.Error(buffer.String())
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPath sets the configuration directory path for file search.
|
// SetPath sets the configuration directory path for file search.
|
||||||
// The param <path> can be absolute or relative path,
|
// The param <path> can be absolute or relative path,
|
||||||
// but absolute path is strongly recommended.
|
// but absolute path is strongly recommended.
|
||||||
func (c *Config) SetPath(path string) error {
|
func (c *Config) SetPath(path string) error {
|
||||||
// Absolute path.
|
// Absolute path.
|
||||||
realPath := gfile.RealPath(path)
|
realPath := gfile.RealPath(path)
|
||||||
if realPath == "" {
|
if realPath == "" {
|
||||||
// Relative path.
|
// Relative path.
|
||||||
c.paths.RLockFunc(func(array []string) {
|
c.paths.RLockFunc(func(array []string) {
|
||||||
for _, v := range array {
|
for _, v := range array {
|
||||||
if path, _ := gspath.Search(v, path); path != "" {
|
if path, _ := gspath.Search(v, path); path != "" {
|
||||||
realPath = path
|
realPath = path
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Path not exist.
|
// Path not exist.
|
||||||
if realPath == "" {
|
if realPath == "" {
|
||||||
buffer := bytes.NewBuffer(nil)
|
buffer := bytes.NewBuffer(nil)
|
||||||
if c.paths.Len() > 0 {
|
if c.paths.Len() > 0 {
|
||||||
buffer.WriteString(fmt.Sprintf("[gcfg] SetPath failed: cannot find directory \"%s\" in following paths:", path))
|
buffer.WriteString(fmt.Sprintf("[gcfg] SetPath failed: cannot find directory \"%s\" in following paths:", path))
|
||||||
c.paths.RLockFunc(func(array []string) {
|
c.paths.RLockFunc(func(array []string) {
|
||||||
for k, v := range array {
|
for k, v := range array {
|
||||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", k+1, v))
|
buffer.WriteString(fmt.Sprintf("\n%d. %s",k + 1, v))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(fmt.Sprintf(`[gcfg] SetPath failed: path "%s" does not exist`, path))
|
buffer.WriteString(fmt.Sprintf(`[gcfg] SetPath failed: path "%s" does not exist`, path))
|
||||||
}
|
}
|
||||||
err := errors.New(buffer.String())
|
err := errors.New(buffer.String())
|
||||||
glog.Error(err)
|
glog.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Should be a directory.
|
// Should be a directory.
|
||||||
if !gfile.IsDir(realPath) {
|
if !gfile.IsDir(realPath) {
|
||||||
err := errors.New(fmt.Sprintf(`[gcfg] SetPath failed: path "%s" should be directory type`, path))
|
err := errors.New(fmt.Sprintf(`[gcfg] SetPath failed: path "%s" should be directory type`, path))
|
||||||
glog.Error(err)
|
glog.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Repeated path check.
|
// Repeated path check.
|
||||||
if c.paths.Search(realPath) != -1 {
|
if c.paths.Search(realPath) != -1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
c.jsons.Clear()
|
c.jsons.Clear()
|
||||||
c.paths.Clear()
|
c.paths.Clear()
|
||||||
c.paths.Append(realPath)
|
c.paths.Append(realPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetViolenceCheck sets whether to perform hierarchical conflict check.
|
// SetViolenceCheck sets whether to perform hierarchical conflict check.
|
||||||
@ -159,58 +159,58 @@ func (c *Config) SetPath(path string) error {
|
|||||||
// and it is not recommended to allow separators in the key names.
|
// and it is not recommended to allow separators in the key names.
|
||||||
// It is best to avoid this on the application side.
|
// It is best to avoid this on the application side.
|
||||||
func (c *Config) SetViolenceCheck(check bool) {
|
func (c *Config) SetViolenceCheck(check bool) {
|
||||||
c.vc.Set(check)
|
c.vc.Set(check)
|
||||||
c.Clear()
|
c.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddPath adds a absolute or relative path to the search paths.
|
// AddPath adds a absolute or relative path to the search paths.
|
||||||
func (c *Config) AddPath(path string) error {
|
func (c *Config) AddPath(path string) error {
|
||||||
// Absolute path.
|
// Absolute path.
|
||||||
realPath := gfile.RealPath(path)
|
realPath := gfile.RealPath(path)
|
||||||
if realPath == "" {
|
if realPath == "" {
|
||||||
// Relative path.
|
// Relative path.
|
||||||
c.paths.RLockFunc(func(array []string) {
|
c.paths.RLockFunc(func(array []string) {
|
||||||
for _, v := range array {
|
for _, v := range array {
|
||||||
if path, _ := gspath.Search(v, path); path != "" {
|
if path, _ := gspath.Search(v, path); path != "" {
|
||||||
realPath = path
|
realPath = path
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if realPath == "" {
|
if realPath == "" {
|
||||||
buffer := bytes.NewBuffer(nil)
|
buffer := bytes.NewBuffer(nil)
|
||||||
if c.paths.Len() > 0 {
|
if c.paths.Len() > 0 {
|
||||||
buffer.WriteString(fmt.Sprintf("[gcfg] AddPath failed: cannot find directory \"%s\" in following paths:", path))
|
buffer.WriteString(fmt.Sprintf("[gcfg] AddPath failed: cannot find directory \"%s\" in following paths:", path))
|
||||||
c.paths.RLockFunc(func(array []string) {
|
c.paths.RLockFunc(func(array []string) {
|
||||||
for k, v := range array {
|
for k, v := range array {
|
||||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", k+1, v))
|
buffer.WriteString(fmt.Sprintf("\n%d. %s", k + 1, v))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(fmt.Sprintf(`[gcfg] AddPath failed: path "%s" does not exist`, path))
|
buffer.WriteString(fmt.Sprintf(`[gcfg] AddPath failed: path "%s" does not exist`, path))
|
||||||
}
|
}
|
||||||
err := errors.New(buffer.String())
|
err := errors.New(buffer.String())
|
||||||
glog.Error(err)
|
glog.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !gfile.IsDir(realPath) {
|
if !gfile.IsDir(realPath) {
|
||||||
err := errors.New(fmt.Sprintf(`[gcfg] AddPath failed: path "%s" should be directory type`, path))
|
err := errors.New(fmt.Sprintf(`[gcfg] AddPath failed: path "%s" should be directory type`, path))
|
||||||
glog.Error(err)
|
glog.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Repeated path check.
|
// Repeated path check.
|
||||||
if c.paths.Search(realPath) != -1 {
|
if c.paths.Search(realPath) != -1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
c.paths.Append(realPath)
|
c.paths.Append(realPath)
|
||||||
//glog.Debug("[gcfg] AddPath:", realPath)
|
//glog.Debug("[gcfg] AddPath:", realPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated.
|
// Deprecated.
|
||||||
// Alias of FilePath.
|
// Alias of FilePath.
|
||||||
func (c *Config) GetFilePath(file ...string) (path string) {
|
func (c *Config) GetFilePath(file...string) (path string) {
|
||||||
return c.FilePath(file...)
|
return c.FilePath(file...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,274 +218,275 @@ func (c *Config) GetFilePath(file ...string) (path string) {
|
|||||||
// If <file> is not passed, it returns the configuration file path of the default name.
|
// If <file> is not passed, it returns the configuration file path of the default name.
|
||||||
// If the specified configuration file does not exist,
|
// If the specified configuration file does not exist,
|
||||||
// an empty string is returned.
|
// an empty string is returned.
|
||||||
func (c *Config) FilePath(file ...string) (path string) {
|
func (c *Config) FilePath(file...string) (path string) {
|
||||||
name := c.name.Val()
|
name := c.name.Val()
|
||||||
if len(file) > 0 {
|
if len(file) > 0 {
|
||||||
name = file[0]
|
name = file[0]
|
||||||
}
|
}
|
||||||
c.paths.RLockFunc(func(array []string) {
|
c.paths.RLockFunc(func(array []string) {
|
||||||
for _, v := range array {
|
for _, v := range array {
|
||||||
if path, _ = gspath.Search(v, name); path != "" {
|
if path, _ = gspath.Search(v, name); path != "" {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if path, _ = gspath.Search(v+gfile.Separator+"config", name); path != "" {
|
if path, _ = gspath.Search(v + gfile.Separator + "config", name); path != "" {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFileName sets the default configuration file name.
|
// SetFileName sets the default configuration file name.
|
||||||
func (c *Config) SetFileName(name string) {
|
func (c *Config) SetFileName(name string) {
|
||||||
c.name.Set(name)
|
c.name.Set(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFileName returns the default configuration file name.
|
// GetFileName returns the default configuration file name.
|
||||||
func (c *Config) GetFileName() string {
|
func (c *Config) GetFileName() string {
|
||||||
return c.name.Val()
|
return c.name.Val()
|
||||||
}
|
}
|
||||||
|
|
||||||
// getJson returns a gjson.Json object for the specified <file> content.
|
// getJson returns a gjson.Json object for the specified <file> content.
|
||||||
// It would print error if file reading fails.
|
// It would print error if file reading fails.
|
||||||
// If any error occurs, it return nil.
|
// If any error occurs, it return nil.
|
||||||
func (c *Config) getJson(file ...string) *gjson.Json {
|
func (c *Config) getJson(file...string) *gjson.Json {
|
||||||
name := c.name.Val()
|
name := c.name.Val()
|
||||||
//todo 此函数file参数无效,没有地方调用,且有SetFileName函数提供链式操作,因此建议去掉
|
if len(file) > 0 {
|
||||||
if len(file) > 0 {
|
name = file[0]
|
||||||
name = file[0]
|
}
|
||||||
}
|
r := c.jsons.GetOrSetFuncLock(name, func() interface{} {
|
||||||
r := c.jsons.GetOrSetFuncLock(name, func() interface{} {
|
content := ""
|
||||||
content := ""
|
filePath := ""
|
||||||
filePath := ""
|
if content = GetContent(name); content == "" {
|
||||||
if content = GetContent(name); content == "" {
|
filePath = c.filePath(name)
|
||||||
filePath = c.filePath(name)
|
if filePath == "" {
|
||||||
if filePath == "" {
|
return nil
|
||||||
return nil
|
}
|
||||||
}
|
content = gfile.GetContents(filePath)
|
||||||
content = gfile.GetContents(filePath)
|
}
|
||||||
}
|
if j, err := gjson.LoadContent(content); err == nil {
|
||||||
if j, err := gjson.LoadContent(content); err == nil {
|
j.SetViolenceCheck(c.vc.Val())
|
||||||
j.SetViolenceCheck(c.vc.Val())
|
// Add monitor for this configuration file,
|
||||||
// Add monitor for this configuration file,
|
// any changes of this file will refresh its cache in Config object.
|
||||||
// any changes of this file will refresh its cache in Config object.
|
if filePath != "" {
|
||||||
if filePath != "" {
|
gfsnotify.Add(filePath, func(event *gfsnotify.Event) {
|
||||||
gfsnotify.Add(filePath, func(event *gfsnotify.Event) {
|
c.jsons.Remove(name)
|
||||||
c.jsons.Remove(name)
|
})
|
||||||
})
|
}
|
||||||
}
|
return j
|
||||||
return j
|
} else {
|
||||||
} else {
|
if filePath != "" {
|
||||||
if filePath != "" {
|
glog.Criticalf(`[gcfg] Load config file "%s" failed: %s`, filePath, err.Error())
|
||||||
glog.Criticalf(`[gcfg] Load config file "%s" failed: %s`, filePath, err.Error())
|
} else {
|
||||||
} else {
|
glog.Criticalf(`[gcfg] Load configuration failed: %s`, err.Error())
|
||||||
glog.Criticalf(`[gcfg] Load configuration failed: %s`, err.Error())
|
}
|
||||||
}
|
}
|
||||||
}
|
return nil
|
||||||
return nil
|
})
|
||||||
})
|
if r != nil {
|
||||||
if r != nil {
|
return r.(*gjson.Json)
|
||||||
return r.(*gjson.Json)
|
}
|
||||||
}
|
return nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Get(pattern string, def ...interface{}) interface{} {
|
func (c *Config) Get(pattern string, def...interface{}) interface{} {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.Get(pattern, def...)
|
return j.Get(pattern, def...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetVar(pattern string, def ...interface{}) *gvar.Var {
|
func (c *Config) GetVar(pattern string, def...interface{}) *gvar.Var {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return gvar.New(j.Get(pattern, def...), true)
|
return gvar.New(j.Get(pattern, def...), true)
|
||||||
}
|
}
|
||||||
return gvar.New(nil, true)
|
return gvar.New(nil, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Contains(pattern string) bool {
|
func (c *Config) Contains(pattern string) bool {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.Contains(pattern)
|
return j.Contains(pattern)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetMap(pattern string, def ...interface{}) map[string]interface{} {
|
func (c *Config) GetMap(pattern string, def...interface{}) map[string]interface{} {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetMap(pattern, def...)
|
return j.GetMap(pattern, def...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetArray(pattern string, def ...interface{}) []interface{} {
|
func (c *Config) GetArray(pattern string, def...interface{}) []interface{} {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetArray(pattern, def...)
|
return j.GetArray(pattern, def...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetString(pattern string, def ...interface{}) string {
|
func (c *Config) GetString(pattern string, def...interface{}) string {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetString(pattern, def...)
|
return j.GetString(pattern, def...)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetStrings(pattern string, def ...interface{}) []string {
|
func (c *Config) GetStrings(pattern string, def...interface{}) []string {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetStrings(pattern, def...)
|
return j.GetStrings(pattern, def...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetInterfaces(pattern string, def ...interface{}) []interface{} {
|
func (c *Config) GetInterfaces(pattern string, def...interface{}) []interface{} {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetInterfaces(pattern, def...)
|
return j.GetInterfaces(pattern, def...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetBool(pattern string, def ...interface{}) bool {
|
func (c *Config) GetBool(pattern string, def...interface{}) bool {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetBool(pattern, def...)
|
return j.GetBool(pattern, def...)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetFloat32(pattern string, def ...interface{}) float32 {
|
func (c *Config) GetFloat32(pattern string, def...interface{}) float32 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetFloat32(pattern, def...)
|
return j.GetFloat32(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetFloat64(pattern string, def ...interface{}) float64 {
|
func (c *Config) GetFloat64(pattern string, def...interface{}) float64 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetFloat64(pattern, def...)
|
return j.GetFloat64(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetFloats(pattern string, def ...interface{}) []float64 {
|
func (c *Config) GetFloats(pattern string, def...interface{}) []float64 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetFloats(pattern, def...)
|
return j.GetFloats(pattern, def...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetInt(pattern string, def ...interface{}) int {
|
func (c *Config) GetInt(pattern string, def...interface{}) int {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetInt(pattern, def...)
|
return j.GetInt(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetInt8(pattern string, def ...interface{}) int8 {
|
|
||||||
if j := c.getJson(); j != nil {
|
func (c *Config) GetInt8(pattern string, def...interface{}) int8 {
|
||||||
return j.GetInt8(pattern, def...)
|
if j := c.getJson(); j != nil {
|
||||||
}
|
return j.GetInt8(pattern, def...)
|
||||||
return 0
|
}
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetInt16(pattern string, def ...interface{}) int16 {
|
func (c *Config) GetInt16(pattern string, def...interface{}) int16 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetInt16(pattern, def...)
|
return j.GetInt16(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetInt32(pattern string, def ...interface{}) int32 {
|
func (c *Config) GetInt32(pattern string, def...interface{}) int32 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetInt32(pattern, def...)
|
return j.GetInt32(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetInt64(pattern string, def ...interface{}) int64 {
|
func (c *Config) GetInt64(pattern string, def...interface{}) int64 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetInt64(pattern, def...)
|
return j.GetInt64(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetInts(pattern string, def ...interface{}) []int {
|
func (c *Config) GetInts(pattern string, def...interface{}) []int {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetInts(pattern, def...)
|
return j.GetInts(pattern, def...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetUint(pattern string, def ...interface{}) uint {
|
func (c *Config) GetUint(pattern string, def...interface{}) uint {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetUint(pattern, def...)
|
return j.GetUint(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetUint8(pattern string, def ...interface{}) uint8 {
|
func (c *Config) GetUint8(pattern string, def...interface{}) uint8 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetUint8(pattern, def...)
|
return j.GetUint8(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetUint16(pattern string, def ...interface{}) uint16 {
|
func (c *Config) GetUint16(pattern string, def...interface{}) uint16 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetUint16(pattern, def...)
|
return j.GetUint16(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetUint32(pattern string, def ...interface{}) uint32 {
|
func (c *Config) GetUint32(pattern string, def...interface{}) uint32 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetUint32(pattern, def...)
|
return j.GetUint32(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetUint64(pattern string, def ...interface{}) uint64 {
|
func (c *Config) GetUint64(pattern string, def...interface{}) uint64 {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetUint64(pattern, def...)
|
return j.GetUint64(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetTime(pattern string, format ...string) time.Time {
|
func (c *Config) GetTime(pattern string, format...string) time.Time {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetTime(pattern, format...)
|
return j.GetTime(pattern, format...)
|
||||||
}
|
}
|
||||||
return time.Time{}
|
return time.Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetDuration(pattern string, def ...interface{}) time.Duration {
|
func (c *Config) GetDuration(pattern string, def...interface{}) time.Duration {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetDuration(pattern, def...)
|
return j.GetDuration(pattern, def...)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetGTime(pattern string, format ...string) *gtime.Time {
|
func (c *Config) GetGTime(pattern string, format...string) *gtime.Time {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetGTime(pattern, format...)
|
return j.GetGTime(pattern, format...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetToStruct(pattern string, pointer interface{}, def ...interface{}) error {
|
func (c *Config) GetToStruct(pattern string, pointer interface{}, def...interface{}) error {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return j.GetToStruct(pattern, pointer)
|
return j.GetToStruct(pattern, pointer)
|
||||||
}
|
}
|
||||||
return errors.New("config file not found")
|
return errors.New("config file not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated. See Clear.
|
// Deprecated. See Clear.
|
||||||
func (c *Config) Reload() {
|
func (c *Config) Reload() {
|
||||||
c.jsons.Clear()
|
c.jsons.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear removes all parsed configuration files content cache,
|
// Clear removes all parsed configuration files content cache,
|
||||||
// which will force reload configuration content from file.
|
// which will force reload configuration content from file.
|
||||||
func (c *Config) Clear() {
|
func (c *Config) Clear() {
|
||||||
c.jsons.Clear()
|
c.jsons.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user