mirror of
https://gitee.com/johng/gf
synced 2026-06-07 10:22:11 +08:00
Merge branch 'qiangg_gcfg'
This commit is contained in:
54
g/container/gqueue/int_queue.go
Normal file
54
g/container/gqueue/int_queue.go
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
package gqueue
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
"container/list"
|
||||
)
|
||||
|
||||
type IntQueue struct {
|
||||
mu sync.RWMutex
|
||||
list *list.List
|
||||
events chan struct{}
|
||||
}
|
||||
|
||||
func NewIntQueue() *IntQueue {
|
||||
return &IntQueue{
|
||||
list : list.New(),
|
||||
events : make(chan struct{}, math.MaxInt64),
|
||||
}
|
||||
}
|
||||
|
||||
// 将数据压入队列
|
||||
func (q *IntQueue) Push(v int) {
|
||||
q.mu.Lock()
|
||||
q.list.PushBack(v)
|
||||
q.mu.Unlock()
|
||||
q.events <- struct{}{}
|
||||
}
|
||||
|
||||
// 先进先出地从队列取出一项数据,当没有数据可获取时,阻塞等待
|
||||
func (q *IntQueue) Pop() int {
|
||||
select {
|
||||
case <- q.events:
|
||||
q.mu.Lock()
|
||||
if elem := q.list.Front(); elem != nil {
|
||||
item := q.list.Remove(elem).(int)
|
||||
q.mu.Unlock()
|
||||
return item
|
||||
}
|
||||
q.mu.Unlock()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 获取当前队列大小
|
||||
func (q *IntQueue) Size() int {
|
||||
return len(q.events)
|
||||
}
|
||||
55
g/container/gqueue/interface_queue.go
Normal file
55
g/container/gqueue/interface_queue.go
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// 动态大小的安全队列(dynamic channel).
|
||||
package gqueue
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
"container/list"
|
||||
)
|
||||
|
||||
type InterfaceQueue struct {
|
||||
mu sync.RWMutex
|
||||
list *list.List
|
||||
events chan struct{}
|
||||
}
|
||||
|
||||
func NewInterfaceQueue() *InterfaceQueue {
|
||||
return &InterfaceQueue {
|
||||
list : list.New(),
|
||||
events : make(chan struct{}, math.MaxInt64),
|
||||
}
|
||||
}
|
||||
|
||||
// 将数据压入队列
|
||||
func (q *InterfaceQueue) Push(v interface{}) {
|
||||
q.mu.Lock()
|
||||
q.list.PushBack(v)
|
||||
q.mu.Unlock()
|
||||
q.events <- struct{}{}
|
||||
}
|
||||
|
||||
// 先进先出地从队列取出一项数据,当没有数据可获取时,阻塞等待
|
||||
func (q *InterfaceQueue) Pop() interface{} {
|
||||
select {
|
||||
case <- q.events:
|
||||
q.mu.Lock()
|
||||
if elem := q.list.Front(); elem != nil {
|
||||
item := q.list.Remove(elem)
|
||||
q.mu.Unlock()
|
||||
return item
|
||||
}
|
||||
q.mu.Unlock()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取当前队列大小
|
||||
func (q *InterfaceQueue) Size() int {
|
||||
return len(q.events)
|
||||
}
|
||||
54
g/container/gqueue/string_queue.go
Normal file
54
g/container/gqueue/string_queue.go
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
package gqueue
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
"container/list"
|
||||
)
|
||||
|
||||
type StringQueue struct {
|
||||
mu sync.RWMutex
|
||||
list *list.List
|
||||
events chan struct{}
|
||||
}
|
||||
|
||||
func NewStringQueue() *StringQueue {
|
||||
return &StringQueue{
|
||||
list : list.New(),
|
||||
events : make(chan struct{}, math.MaxInt64),
|
||||
}
|
||||
}
|
||||
|
||||
// 将数据压入队列
|
||||
func (q *StringQueue) Push(v string) {
|
||||
q.mu.Lock()
|
||||
q.list.PushBack(v)
|
||||
q.mu.Unlock()
|
||||
q.events <- struct{}{}
|
||||
}
|
||||
|
||||
// 先进先出地从队列取出一项数据,当没有数据可获取时,阻塞等待
|
||||
func (q *StringQueue) Pop() string {
|
||||
select {
|
||||
case <- q.events:
|
||||
q.mu.Lock()
|
||||
if elem := q.list.Front(); elem != nil {
|
||||
item := q.list.Remove(elem).(string)
|
||||
q.mu.Unlock()
|
||||
return item
|
||||
}
|
||||
q.mu.Unlock()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 获取当前队列大小
|
||||
func (q *StringQueue) Size() int {
|
||||
return len(q.events)
|
||||
}
|
||||
54
g/container/gqueue/uint_queue.go
Normal file
54
g/container/gqueue/uint_queue.go
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
package gqueue
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
"container/list"
|
||||
)
|
||||
|
||||
type UintQueue struct {
|
||||
mu sync.RWMutex
|
||||
list *list.List
|
||||
events chan struct{}
|
||||
}
|
||||
|
||||
func NewUintQueue() *UintQueue {
|
||||
return &UintQueue{
|
||||
list : list.New(),
|
||||
events : make(chan struct{}, math.MaxInt64),
|
||||
}
|
||||
}
|
||||
|
||||
// 将数据压入队列
|
||||
func (q *UintQueue) Push(v uint) {
|
||||
q.mu.Lock()
|
||||
q.list.PushBack(v)
|
||||
q.mu.Unlock()
|
||||
q.events <- struct{}{}
|
||||
}
|
||||
|
||||
// 先进先出地从队列取出一项数据,当没有数据可获取时,阻塞等待
|
||||
func (q *UintQueue) Pop() uint {
|
||||
select {
|
||||
case <- q.events:
|
||||
q.mu.Lock()
|
||||
if elem := q.list.Front(); elem != nil {
|
||||
item := q.list.Remove(elem).(uint)
|
||||
q.mu.Unlock()
|
||||
return item
|
||||
}
|
||||
q.mu.Unlock()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 获取当前队列大小
|
||||
func (q *UintQueue) Size() int {
|
||||
return len(q.events)
|
||||
}
|
||||
@ -12,7 +12,11 @@ import (
|
||||
"strconv"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g/util/gconv"
|
||||
"gitee.com/johng/gf/g/encoding/gxml"
|
||||
"gitee.com/johng/gf/g/encoding/gyaml"
|
||||
"gitee.com/johng/gf/g/encoding/gtoml"
|
||||
)
|
||||
|
||||
// json解析结果存放数组
|
||||
@ -39,7 +43,7 @@ func Decode (b []byte) (interface{}, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 解析json字符串为go变量,注意第二个参数为指针
|
||||
// 解析json字符串为go变量,注意第二个参数为指针(任意结构的变量)
|
||||
func DecodeTo (b []byte, v interface{}) error {
|
||||
return json.Unmarshal(b, v)
|
||||
}
|
||||
@ -53,13 +57,42 @@ func DecodeToJson (b []byte) (*Json, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 加载json文件内容,并转换为json对象
|
||||
// 支持多种配置文件类型转换为json格式内容并解析为gjson.Json对象
|
||||
func Load (path string) (*Json, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return LoadContent(data, gfile.Ext(path))
|
||||
}
|
||||
|
||||
// 支持的配置文件格式:xml, json, yaml/yml, toml
|
||||
func LoadContent (data []byte, t string) (*Json, error) {
|
||||
var err error
|
||||
var result interface{}
|
||||
switch t {
|
||||
case "xml": fallthrough
|
||||
case ".xml":
|
||||
data, err = gxml.ToJson(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "yml": fallthrough
|
||||
case "yaml": fallthrough
|
||||
case ".yml": fallthrough
|
||||
case ".yaml":
|
||||
data, err = gyaml.ToJson(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case "toml": fallthrough
|
||||
case ".toml":
|
||||
data, err = gtoml.ToJson(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -189,10 +222,9 @@ func (p *Json) Get(pattern string) interface{} {
|
||||
|
||||
// 转换为map[string]interface{}类型,如果转换失败,返回nil
|
||||
func (p *Json) ToMap() map[string]interface{} {
|
||||
pointer := p.value
|
||||
switch (*pointer).(type) {
|
||||
switch (*(p.value)).(type) {
|
||||
case map[string]interface{}:
|
||||
return (*pointer).(map[string]interface{})
|
||||
return (*(p.value)).(map[string]interface{})
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@ -200,15 +232,37 @@ func (p *Json) ToMap() map[string]interface{} {
|
||||
|
||||
// 转换为[]interface{}类型,如果转换失败,返回nil
|
||||
func (p *Json) ToArray() []interface{} {
|
||||
pointer := p.value
|
||||
switch (*pointer).(type) {
|
||||
switch (*(p.value)).(type) {
|
||||
case []interface{}:
|
||||
return (*pointer).([]interface{})
|
||||
return (*(p.value)).([]interface{})
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Json) ToXml(rootTag...string) ([]byte, error) {
|
||||
return gxml.Encode(p.ToMap(), rootTag...)
|
||||
}
|
||||
|
||||
func (p *Json) ToXmlIndent(rootTag...string) ([]byte, error) {
|
||||
return gxml.EncodeWithIndent(p.ToMap(), rootTag...)
|
||||
}
|
||||
|
||||
func (p *Json) ToJson() ([]byte, error) {
|
||||
return Encode(*(p.value))
|
||||
}
|
||||
|
||||
func (p *Json) ToJsonIndent() ([]byte, error) {
|
||||
return json.MarshalIndent(*(p.value), "", "\t")
|
||||
}
|
||||
|
||||
func (p *Json) ToYaml() ([]byte, error) {
|
||||
return gyaml.Encode(*(p.value))
|
||||
}
|
||||
|
||||
func (p *Json) ToToml() ([]byte, error) {
|
||||
return gtoml.Encode(*(p.value))
|
||||
}
|
||||
|
||||
// 判断所给字符串是否为数字
|
||||
func isNumeric(s string) bool {
|
||||
|
||||
@ -1,443 +0,0 @@
|
||||
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"strings"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 这是一个自己开发的,使用go进行json语法解析的解析器,效率没有官方的json解析高,仅作学习参考
|
||||
|
||||
const (
|
||||
gJSON_CHAR_BRACE_LEFT = rune('{')
|
||||
gJSON_CHAR_BRACE_RIGHT = rune('}')
|
||||
gJSON_CHAR_BRACKET_LEFT = rune('[')
|
||||
gJSON_CHAR_BRACKET_RIGHT = rune(']')
|
||||
gJSON_CHAR_QUOTATION = rune('\\')
|
||||
gJSON_CHAR_COMMA = rune(',')
|
||||
gJSON_CHAR_COLON = rune(':')
|
||||
gJSON_CHAR_DOUBLE_QUOTE_MARK = rune('"')
|
||||
)
|
||||
|
||||
const (
|
||||
gJSON_TOKEN_BRACE_LEFT = rune('{')
|
||||
gJSON_TOKEN_BRACE_RIGHT = rune('}')
|
||||
gJSON_TOKEN_BRACKET_LEFT = rune('[')
|
||||
gJSON_TOKEN_BRACKET_RIGHT = rune(']')
|
||||
gJSON_TOKEN_COMMA = rune(',')
|
||||
gJSON_TOKEN_COLON = rune(':')
|
||||
gJSON_TOKEN_STRING = rune('"')
|
||||
gJSON_TOKEN_NUMBER = rune('0')
|
||||
)
|
||||
|
||||
// json关联数组(哈希表)
|
||||
type JsonMap map[string]interface{}
|
||||
// json索引数组(普通数组,从0开始索引)
|
||||
type JsonArray []interface{}
|
||||
|
||||
// JSON数据对象
|
||||
type gJsonNode struct {
|
||||
m JsonMap
|
||||
a JsonArray
|
||||
}
|
||||
|
||||
// JSON语义token
|
||||
type gJsonToken struct {
|
||||
token []rune // token字符串
|
||||
tokenType rune // token类型
|
||||
tokenindex int // token在原始字符串中的索引位置
|
||||
}
|
||||
|
||||
// JSON解析结构对象
|
||||
type gJsonParser struct {
|
||||
content []rune // 需要解析json字符串(通过string转换为[]rune)
|
||||
tokens []gJsonToken // 存放解析content后的json token数组
|
||||
root *gJsonNode // json根节点
|
||||
pointer *gJsonNode // 指向当前正在解析的json节点
|
||||
}
|
||||
|
||||
// 解析json字符串
|
||||
func Decode(j *string) (*gJsonParser, error) {
|
||||
p := &gJsonParser{content:[]rune(*j)}
|
||||
err := p.parse()
|
||||
if err == nil {
|
||||
return p, err
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 判断所给字符串是否为数字
|
||||
func isNumeric(s string) bool {
|
||||
for i :=0; i < len(s); i++ {
|
||||
if s[i] < byte('0') || s[i] > byte('9') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 获得一个键值对关联数组/哈希表,方便操作,不需要自己做类型转换
|
||||
// 注意,如果获取的值不存在,或者类型与json类型不匹配,那么将会返回nil
|
||||
func (p *gJsonParser) GetMap(pattern string) JsonMap {
|
||||
result := p.Get(pattern)
|
||||
if result != nil {
|
||||
if r, ok := result.(JsonMap); ok {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获得一个数组[]interface{},方便操作,不需要自己做类型转换
|
||||
// 注意,如果获取的值不存在,或者类型与json类型不匹配,那么将会返回nil
|
||||
func (p *gJsonParser) GetArray(pattern string) JsonArray {
|
||||
result := p.Get(pattern)
|
||||
if result != nil {
|
||||
if r, ok := result.(JsonArray); ok {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// 根据约定字符串方式访问json解析数据,参数形如: "items.name.first", "list.0"
|
||||
// 返回的结果类型的interface{},因此需要自己做类型转换
|
||||
// 如果找不到对应节点的数据,返回nil
|
||||
func (p *gJsonParser) Get(pattern string) interface{} {
|
||||
var result interface{}
|
||||
pointer := p.root
|
||||
array := strings.Split(pattern, ".")
|
||||
length := len(array)
|
||||
for i:= 0; i < length; i++ {
|
||||
// 优先判断数组
|
||||
if isNumeric(array[i]) {
|
||||
n, err := strconv.Atoi(array[i])
|
||||
if err == nil && len(pointer.a) > n {
|
||||
if i == length - 1 {
|
||||
result = pointer.a[n]
|
||||
break;
|
||||
} else {
|
||||
if p, ok := pointer.a[n].(*gJsonNode); ok {
|
||||
pointer = p
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 其次判断哈希表,如果一个键在数组及map中均不存在,直接返回nil
|
||||
if v, ok := pointer.m[array[i]]; ok {
|
||||
if i == length - 1 {
|
||||
result = v
|
||||
} else {
|
||||
if p, ok := v.(*gJsonNode); ok {
|
||||
pointer = p
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// 处理结果,如果是gJsonNode类型,那么需要做转换
|
||||
if r, ok := result.(*gJsonNode); ok {
|
||||
if len(r.m) < 1 {
|
||||
return r.a
|
||||
} else {
|
||||
return r.m
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 遍历json字符串数组,并且判断转义
|
||||
func (p *gJsonParser) getNextChar(c rune, f int) int {
|
||||
for i := f + 1; i < len(p.content); i++ {
|
||||
if p.content[i] == c {
|
||||
if i > 0 && p.content[i - 1] != gJSON_CHAR_QUOTATION {
|
||||
return i
|
||||
}
|
||||
} else {
|
||||
switch p.content[i] {
|
||||
case gJSON_CHAR_DOUBLE_QUOTE_MARK:
|
||||
r := p.getNextChar(gJSON_CHAR_DOUBLE_QUOTE_MARK, i)
|
||||
if r > 0 {
|
||||
i = r
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 判断字符是否为数字
|
||||
func (p *gJsonParser) isCharNumber(c rune) bool {
|
||||
if c >= rune('0') && c <= rune('9') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 按照json语法对保存的字符串进行解析
|
||||
func (p *gJsonParser) parse() error {
|
||||
// 首先将字符串解析成token进行保存
|
||||
for i := 0; i < len(p.content); i++ {
|
||||
if p.isCharNumber(p.content[i]) {
|
||||
j := i + 1
|
||||
for ; j < len(p.content); j++ {
|
||||
if !p.isCharNumber(p.content[j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
p.tokens = append(p.tokens, gJsonToken {
|
||||
token: p.content[i:j],
|
||||
tokenType: gJSON_TOKEN_NUMBER,
|
||||
tokenindex: i,
|
||||
})
|
||||
i = j - 1
|
||||
} else {
|
||||
switch p.content[i] {
|
||||
case gJSON_CHAR_DOUBLE_QUOTE_MARK:
|
||||
r := p.getNextChar(gJSON_CHAR_DOUBLE_QUOTE_MARK, i)
|
||||
if r > 0 {
|
||||
// 注意这里需要去掉字符串两边的双引号
|
||||
p.tokens = append(p.tokens, gJsonToken {
|
||||
token: p.content[i+1:r],
|
||||
tokenType: gJSON_TOKEN_STRING,
|
||||
tokenindex: i,
|
||||
})
|
||||
i = r
|
||||
}
|
||||
case gJSON_CHAR_COLON:
|
||||
p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_COLON, tokenindex: i})
|
||||
case gJSON_CHAR_COMMA:
|
||||
p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_COMMA, tokenindex: i})
|
||||
case gJSON_CHAR_BRACE_LEFT:
|
||||
p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_BRACE_LEFT, tokenindex: i})
|
||||
case gJSON_CHAR_BRACE_RIGHT:
|
||||
p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_BRACE_RIGHT, tokenindex: i})
|
||||
case gJSON_CHAR_BRACKET_LEFT:
|
||||
p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_BRACKET_LEFT, tokenindex: i})
|
||||
case gJSON_CHAR_BRACKET_RIGHT:
|
||||
p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_BRACKET_RIGHT, tokenindex: i})
|
||||
|
||||
default:
|
||||
c := string(p.content[i])
|
||||
if c != " " && c != "\r" && c != "\n" && c != "\t" {
|
||||
return errors.New(fmt.Sprintf("json parse error: invalid char '%s' at index %d", c, i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 最后对解析后的token转换为go变量
|
||||
return p.parseTokenNodeToVar(0, len(p.tokens) - 1)
|
||||
}
|
||||
|
||||
// 获取json范围字符包含范围最右侧的索引位置
|
||||
func (p *gJsonParser)getTokenBorderRightIndex(token rune, from int) int {
|
||||
switch token {
|
||||
case gJSON_TOKEN_BRACE_LEFT:
|
||||
leftCount := 0
|
||||
for i := from + 1; i < len(p.tokens); i++ {
|
||||
if p.tokens[i].tokenType == gJSON_TOKEN_BRACE_LEFT {
|
||||
leftCount ++
|
||||
} else if p.tokens[i].tokenType == gJSON_TOKEN_BRACE_RIGHT {
|
||||
if leftCount < 1 {
|
||||
return i
|
||||
} else {
|
||||
leftCount--
|
||||
}
|
||||
}
|
||||
}
|
||||
case gJSON_CHAR_BRACKET_LEFT:
|
||||
leftCount := 0
|
||||
for i := from + 1; i < len(p.tokens); i++ {
|
||||
if p.tokens[i].tokenType == gJSON_CHAR_BRACKET_LEFT {
|
||||
leftCount ++
|
||||
} else if p.tokens[i].tokenType == gJSON_CHAR_BRACKET_RIGHT {
|
||||
if leftCount < 1 {
|
||||
return i
|
||||
} else {
|
||||
leftCount--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 将解析过后的json token转换为go变量
|
||||
func (p *gJsonParser) parseTokenNodeToVar(left int, right int) error {
|
||||
//fmt.Println("================================")
|
||||
//for i := left; i <= right; i++ {
|
||||
// fmt.Println(string(p.tokens[i].token))
|
||||
//}
|
||||
for i := left; i <= right; i++ {
|
||||
//fmt.Println(string(p.tokens[i].token))
|
||||
switch p.tokens[i].tokenType {
|
||||
case gJSON_TOKEN_BRACE_LEFT:
|
||||
fallthrough
|
||||
case gJSON_TOKEN_BRACKET_LEFT:
|
||||
node := newJsonNode()
|
||||
// 判断根节点
|
||||
if p.root == nil {
|
||||
p.root = node
|
||||
p.pointer = node
|
||||
}
|
||||
// 判断层级关系
|
||||
borderRight := p.getTokenBorderRightIndex(p.tokens[i].tokenType, i)
|
||||
if borderRight < 1 {
|
||||
return errors.New(fmt.Sprintf("json parse error: unclosed tag '%s' at index %d", string(p.tokens[i].token), p.tokens[i].tokenindex))
|
||||
}
|
||||
if i > 1 && (
|
||||
p.tokens[i-1].tokenType == gJSON_TOKEN_COLON &&
|
||||
p.tokens[i-2].tokenType == gJSON_TOKEN_STRING) {
|
||||
// json赋值操作
|
||||
oldptr := p.pointer
|
||||
k := string(p.tokens[i-2].token)
|
||||
p.pointer.m[k] = node
|
||||
p.pointer = node
|
||||
err := p.parseTokenNodeToVar(i + 1, borderRight - 1)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
i = borderRight
|
||||
p.pointer = oldptr
|
||||
}
|
||||
|
||||
} else if i > 0 && (
|
||||
p.tokens[i-1].tokenType == gJSON_TOKEN_COMMA ||
|
||||
p.tokens[i-1].tokenType == gJSON_TOKEN_BRACE_LEFT ||
|
||||
p.tokens[i-1].tokenType == gJSON_TOKEN_BRACKET_LEFT) {
|
||||
// json数组操作
|
||||
oldptr := p.pointer
|
||||
p.pointer.a = append(p.pointer.a, node)
|
||||
p.pointer = node
|
||||
err := p.parseTokenNodeToVar(i + 1, borderRight - 1)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
i = borderRight
|
||||
p.pointer = oldptr
|
||||
}
|
||||
} else {
|
||||
// json层级关系
|
||||
p.pointer = node
|
||||
err := p.parseTokenNodeToVar(i + 1, borderRight - 1)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
i = borderRight
|
||||
}
|
||||
}
|
||||
|
||||
case gJSON_TOKEN_STRING:
|
||||
fallthrough
|
||||
case gJSON_TOKEN_NUMBER:
|
||||
if i > 0 && p.tokens[i-1].tokenType == gJSON_TOKEN_COLON {
|
||||
k := string(p.tokens[i-2].token)
|
||||
v := string(p.tokens[i].token)
|
||||
p.pointer.m[k] = v
|
||||
} else if p.tokens[i+1].tokenType != gJSON_TOKEN_COLON {
|
||||
p.pointer.a = append(p.pointer.a, string(p.tokens[i].token))
|
||||
}
|
||||
|
||||
case gJSON_TOKEN_COLON:
|
||||
if i < 1 || (p.tokens[i-1].tokenType != gJSON_TOKEN_STRING) {
|
||||
return errors.New(fmt.Sprintf("json parse error: invalid charactar '%s' at index %d", string(p.tokens[i].token), p.tokens[i].tokenindex))
|
||||
}
|
||||
|
||||
case gJSON_TOKEN_COMMA:
|
||||
if (p.tokens[i+1].tokenType != gJSON_TOKEN_STRING &&
|
||||
p.tokens[i+1].tokenType != gJSON_TOKEN_NUMBER &&
|
||||
p.tokens[i+1].tokenType != gJSON_TOKEN_BRACE_LEFT &&
|
||||
p.tokens[i+1].tokenType != gJSON_TOKEN_BRACKET_LEFT) ||
|
||||
(i < 1 || (
|
||||
p.tokens[i-1].tokenType != gJSON_TOKEN_STRING &&
|
||||
p.tokens[i-1].tokenType != gJSON_TOKEN_NUMBER &&
|
||||
p.tokens[i-1].tokenType != gJSON_TOKEN_BRACE_RIGHT &&
|
||||
p.tokens[i-1].tokenType != gJSON_TOKEN_BRACKET_RIGHT)) {
|
||||
return errors.New(fmt.Sprintf("json parse error: invalid charactar '%s' at index %d", string(p.tokens[i].token), p.tokens[i].tokenindex))
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 打印出所有的token(测试用)
|
||||
func (p *gJsonParser)printTokens() {
|
||||
for _, v := range p.tokens {
|
||||
fmt.Println(string(v.token))
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化打印根节点
|
||||
func (p *gJsonParser)Print() {
|
||||
if len(p.root.m) > 0 {
|
||||
fmt.Println("{")
|
||||
} else {
|
||||
fmt.Println("[")
|
||||
}
|
||||
p.printNode(p.pointer, "\t")
|
||||
if len(p.root.m) > 0 {
|
||||
fmt.Println("}")
|
||||
} else {
|
||||
fmt.Println("]")
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化打印根节点
|
||||
func (p *gJsonParser)printNode(n *gJsonNode, indent string) {
|
||||
if len(n.m) > 0 {
|
||||
for k, v := range n.m {
|
||||
if t, ok := v.(*gJsonNode); ok {
|
||||
if len(t.m) > 0 {
|
||||
fmt.Printf("%v%v\t: {\n", indent, k)
|
||||
p.printNode(t, indent + "\t")
|
||||
fmt.Printf("%v}\n", indent)
|
||||
} else {
|
||||
fmt.Printf("%v%v\t: [\n", indent, k)
|
||||
p.printNode(t, indent + "\t")
|
||||
fmt.Printf("%v}\n", indent)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%v%v\t: %v\n", indent, k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(n.a) > 0 {
|
||||
for k, v := range n.a {
|
||||
if t, ok := v.(*gJsonNode); ok {
|
||||
if len(t.m) > 0 {
|
||||
fmt.Printf("%v%v\t: {\n", indent, k)
|
||||
p.printNode(t, indent + "\t")
|
||||
fmt.Printf("%v}\n", indent)
|
||||
} else {
|
||||
fmt.Printf("%v%v\t: [\n", indent, k)
|
||||
p.printNode(t, indent + "\t")
|
||||
fmt.Printf("%v}\n", indent)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%v%v : %v\n", indent, k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建一个json数据对象
|
||||
func newJsonNode() *gJsonNode {
|
||||
return &gJsonNode {
|
||||
m: make(map[string]interface{}),
|
||||
a: make([]interface{}, 0),
|
||||
}
|
||||
}
|
||||
|
||||
42
g/encoding/gtoml/gtoml.go
Normal file
42
g/encoding/gtoml/gtoml.go
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// TOML
|
||||
package gtoml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
func Encode(v interface{}) ([]byte, error) {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if err := toml.NewEncoder(buffer).Encode(v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
func Decode(v []byte) (interface{}, error) {
|
||||
var result interface{}
|
||||
if err := toml.Unmarshal(v, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func DecodeTo(v []byte, result interface{}) error {
|
||||
return toml.Unmarshal(v, result)
|
||||
}
|
||||
|
||||
func ToJson(v []byte) ([]byte, error) {
|
||||
if r, err := Decode(v); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return json.Marshal(r)
|
||||
}
|
||||
}
|
||||
35
g/encoding/gxml/gxml.go
Normal file
35
g/encoding/gxml/gxml.go
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// XML
|
||||
package gxml
|
||||
|
||||
import (
|
||||
"github.com/clbanning/mxj"
|
||||
)
|
||||
|
||||
// 将XML内容解析为map变量
|
||||
func Decode(xmlbyte []byte) (map[string]interface{}, error) {
|
||||
return mxj.NewMapXml(xmlbyte)
|
||||
}
|
||||
|
||||
// 将map变量解析为XML格式内容
|
||||
func Encode(v map[string]interface{}, rootTag...string) ([]byte, error) {
|
||||
return mxj.Map(v).Xml(rootTag...)
|
||||
}
|
||||
|
||||
func EncodeWithIndent(v map[string]interface{}, rootTag...string) ([]byte, error) {
|
||||
return mxj.Map(v).XmlIndent("", "\t", rootTag...)
|
||||
}
|
||||
|
||||
// XML格式内容直接转换为JSON格式内容
|
||||
func ToJson(xmlbyte []byte) ([]byte, error) {
|
||||
if mv, err := mxj.NewMapXml(xmlbyte); err == nil {
|
||||
return mv.Json()
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
30
g/encoding/gyaml/gyaml.go
Normal file
30
g/encoding/gyaml/gyaml.go
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// YAML
|
||||
package gyaml
|
||||
|
||||
import "github.com/ghodss/yaml"
|
||||
|
||||
func Encode(v interface{}) ([]byte, error) {
|
||||
return yaml.Marshal(v)
|
||||
}
|
||||
|
||||
func Decode(v []byte) (interface{}, error) {
|
||||
var result interface{}
|
||||
if err := yaml.Unmarshal(v, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func DecodeTo(v []byte, result interface{}) error {
|
||||
return yaml.Unmarshal(v, &result)
|
||||
}
|
||||
|
||||
func ToJson(v []byte) ([]byte, error) {
|
||||
return yaml.YAMLToJSON(v)
|
||||
}
|
||||
@ -4,18 +4,18 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// 单例对象管理.
|
||||
// 框架内置了一些核心对象,并且可以通过Set和Get方法实现IoC以及对内置核心对象的自定义替换
|
||||
// 单例对象管理(耦合了一些框架核心对象获取方法).
|
||||
// 框架内置了一些核心对象获取方法,并且可以通过Set和Get方法实现IoC以及对内置核心对象的自定义替换
|
||||
package gins
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"gitee.com/johng/gf/g/os/gcfg"
|
||||
"gitee.com/johng/gf/g/os/gcmd"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"gitee.com/johng/gf/g/os/genv"
|
||||
"gitee.com/johng/gf/g/os/gview"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g/frame/gcfg"
|
||||
"gitee.com/johng/gf/g/database/gdb"
|
||||
"gitee.com/johng/gf/g/container/gmap"
|
||||
)
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// 配置管理
|
||||
// 配置管理.
|
||||
// 配置文件格式支持:json, xml, toml, yaml/yml
|
||||
package gcfg
|
||||
|
||||
import (
|
||||
@ -16,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
gDEFAULT_CONFIG_FILE = "config" // 默认的配置管理文件名称
|
||||
gDEFAULT_CONFIG_FILE = "config.json" // 默认的配置管理文件名称
|
||||
)
|
||||
|
||||
// 配置管理对象
|
||||
@ -43,7 +44,7 @@ func (c *Config) filePath(files []string) string {
|
||||
c.mu.RLock()
|
||||
fpath := c.path + gfile.Separator + file
|
||||
c.mu.RUnlock()
|
||||
return fpath + ".json"
|
||||
return fpath
|
||||
}
|
||||
|
||||
// 设置配置管理器的配置文件存放目录绝对路径
|
||||
@ -111,6 +112,14 @@ func (c *Config) GetBool(pattern string, files...string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 返回指定json中的float32
|
||||
func (c *Config) GetFloat32(pattern string, files...string) float32 {
|
||||
if j := c.getJson(files); j != nil {
|
||||
return j.GetFloat32(pattern)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 返回指定json中的float64
|
||||
func (c *Config) GetFloat64(pattern string, files...string) float64 {
|
||||
if j := c.getJson(files); j != nil {
|
||||
@ -121,10 +130,16 @@ func (c *Config) GetFloat64(pattern string, files...string) float64 {
|
||||
|
||||
// 返回指定json中的float64->int
|
||||
func (c *Config) GetInt(pattern string, files...string) int {
|
||||
return int(c.GetFloat64(pattern))
|
||||
if j := c.getJson(files); j != nil {
|
||||
return j.GetInt(pattern)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 返回指定json中的float64->int64
|
||||
func (c *Config) GetInt64(pattern string, files...string) int64 {
|
||||
return int64(c.GetFloat64(pattern))
|
||||
}
|
||||
// 返回指定json中的float64->uint
|
||||
func (c *Config) GetUint(pattern string, files...string) uint {
|
||||
if j := c.getJson(files); j != nil {
|
||||
return j.GetUint(pattern)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@ -56,7 +56,7 @@ func New(expire int, sizes...int) *Pool {
|
||||
funcs : glist.NewSafeList(),
|
||||
freeEvents : make(chan struct{}, math.MaxUint32),
|
||||
funcEvents : make(chan struct{}, math.MaxUint32),
|
||||
stopEvents : make(chan struct{}, 1),
|
||||
stopEvents : make(chan struct{}, 2),
|
||||
}
|
||||
p.startWorkLoop()
|
||||
p.startClearLoop()
|
||||
|
||||
32
geg/container/gqueue.go
Normal file
32
geg/container/gqueue.go
Normal file
@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/os/gtime"
|
||||
"gitee.com/johng/gf/g/container/gqueue"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
t := gtime.Microsecond()
|
||||
q := gqueue.NewInterfaceQueue()
|
||||
fmt.Println("queue creation costs(μs):", gtime.Microsecond() - t)
|
||||
|
||||
// 每隔2秒异步打印出当前队列的大小
|
||||
gtime.SetInterval(2*time.Second, func() bool {
|
||||
fmt.Println("queue size:", q.Size())
|
||||
return true
|
||||
})
|
||||
|
||||
// push10条数据
|
||||
for i := 0; i < 10; i++ {
|
||||
q.Push(i)
|
||||
fmt.Println("push:", i)
|
||||
}
|
||||
|
||||
// 每隔1秒pop1条数据
|
||||
for {
|
||||
time.Sleep(time.Second)
|
||||
fmt.Println(" pop:", q.Pop())
|
||||
}
|
||||
}
|
||||
@ -17,7 +17,7 @@ func init () {
|
||||
Port : "3306",
|
||||
User : "root",
|
||||
Pass : "123456",
|
||||
Name : "test2",
|
||||
Name : "test",
|
||||
Type : "mysql",
|
||||
Role : "master",
|
||||
Charset : "utf8",
|
||||
@ -416,7 +416,7 @@ func main() {
|
||||
//create()
|
||||
//create()
|
||||
//insert()
|
||||
//query()
|
||||
query()
|
||||
//replace()
|
||||
//save()
|
||||
//batchInsert()
|
||||
|
||||
28
geg/frame/config.xml
Normal file
28
geg/frame/config.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<config>
|
||||
<viewpath>/home/www/templates/</viewpath>
|
||||
<database>
|
||||
<default>
|
||||
<host>127.0.0.1</host>
|
||||
<port>3306</port>
|
||||
<user>root</user>
|
||||
<pass>123456</pass>
|
||||
<name>test</name>
|
||||
<role>master</role>
|
||||
<type>mysql</type>
|
||||
<charset>utf8</charset>
|
||||
<priority>1</priority>
|
||||
</default>
|
||||
<default>
|
||||
<host>127.0.0.1</host>
|
||||
<port>3306</port>
|
||||
<user>root</user>
|
||||
<pass>123456</pass>
|
||||
<name>test</name>
|
||||
<role>master</role>
|
||||
<type>mysql</type>
|
||||
<charset>utf8</charset>
|
||||
<priority>1</priority>
|
||||
</default>
|
||||
</database>
|
||||
</config>
|
||||
20
geg/frame/config.yml
Normal file
20
geg/frame/config.yml
Normal file
@ -0,0 +1,20 @@
|
||||
viewpath: /home/www/templates/
|
||||
database:
|
||||
default:
|
||||
- host: 127.0.0.1
|
||||
port: 3306
|
||||
user: root
|
||||
pass: 123456
|
||||
name: test
|
||||
type: mysql
|
||||
role: master
|
||||
priority: 1
|
||||
- host: 127.0.0.1
|
||||
port: 3306
|
||||
user: root
|
||||
pass: 123456
|
||||
name: test
|
||||
type: mysql
|
||||
role: master
|
||||
priority: 1
|
||||
|
||||
@ -5,5 +5,13 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("%b\n", 123)
|
||||
c1 := make(chan int, 2)
|
||||
c2 := make(chan int, 5)
|
||||
c1 <- 1
|
||||
c1 <- 2
|
||||
c2 = c1
|
||||
c2 <- 3
|
||||
fmt.Println(<-c2)
|
||||
fmt.Println(<-c2)
|
||||
fmt.Println(<-c2)
|
||||
}
|
||||
Reference in New Issue
Block a user