Skip to content

Commit

Permalink
Simplification for array and group creating
Browse files Browse the repository at this point in the history
  • Loading branch information
RickoNoNo3 committed Mar 31, 2021
1 parent 636cfd8 commit 3413842
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 85 deletions.
50 changes: 25 additions & 25 deletions arr.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (o *Object) arrCheckIndexKey(key, keyStr string) (index int, err error) {
err = InvalidKeyStrErr(keyStr)
return
} else { // gotten an integer as the index
arr := *o.val.(*ArrayData)
arr := *o.val.(*arrayData)
if len(arr) <= index { // the index overflows from the arr
err = IndexOverflowErr{
Index: index,
Expand All @@ -43,8 +43,8 @@ func (o *Object) arrCheckIndexKey(key, keyStr string) (index int, err error) {

func (o *Object) ArrPush(value interface{}) (err error) {
switch o.val.(type) {
case *ArrayData:
*o.val.(*ArrayData) = append(*o.val.(*ArrayData), New(getDeepestValue(value)))
case *arrayData:
*o.val.(*arrayData) = append(*o.val.(*arrayData), New(getDeepestValue(value)))
return nil
default:
return InvalidTypeErr("")
Expand All @@ -53,8 +53,8 @@ func (o *Object) ArrPush(value interface{}) (err error) {

func (o *Object) ArrPop() (err error) {
switch o.val.(type) {
case *ArrayData:
*o.val.(*ArrayData) = (*o.val.(*ArrayData))[:len(*o.val.(*ArrayData))-1]
case *arrayData:
*o.val.(*arrayData) = (*o.val.(*arrayData))[:len(*o.val.(*arrayData))-1]
return nil
default:
return InvalidTypeErr("")
Expand All @@ -63,8 +63,8 @@ func (o *Object) ArrPop() (err error) {

func (o *Object) ArrSet(index int, value interface{}) (err error) {
switch o.val.(type) {
case *ArrayData:
(*o.val.(*ArrayData))[index] = New(getDeepestValue(value))
case *arrayData:
(*o.val.(*arrayData))[index] = New(getDeepestValue(value))
return nil
default:
return InvalidTypeErr("")
Expand All @@ -74,38 +74,38 @@ func (o *Object) ArrSet(index int, value interface{}) (err error) {
// An alias of `*Object.Get("[index]")`
func (o *Object) ArrGet(index int) (obj *Object, err error) {
switch o.val.(type) {
case *ArrayData:
return (*o.val.(*ArrayData))[index], nil
case *arrayData:
return (*o.val.(*arrayData))[index], nil
default:
return nil, InvalidTypeErr("")
}
}

func (o *Object) ArrInsert(index int, value interface{}) (err error) {
switch o.val.(type) {
case *ArrayData:
case *arrayData:
var (
arr, arrBefore, arrAfter, arrRes ArrayData
arr, arrBefore, arrAfter, arrRes arrayData
)
arr = *o.val.(*ArrayData)
arr = *o.val.(*arrayData)
// overflow
if index < 0 || index >= len(arr) {
return IndexOverflowErr{index}
}
// before
arrBefore = ArrayData{}
arrBefore = arrayData{}
if index > 0 {
arrBefore = append(arrBefore, arr[:index]...)
}
// after
arrAfter = ArrayData{}
arrAfter = arrayData{}
if index < len(arr)-1 {
arrAfter = append(arrAfter, arr[index:]...)
}
// generate
arrRes = append(arrBefore, New(getDeepestValue(value)))
arrRes = append(arrRes, arrAfter...)
*o.val.(*ArrayData) = arrRes
*o.val.(*arrayData) = arrRes
return nil
default:
return InvalidTypeErr("")
Expand All @@ -114,28 +114,28 @@ func (o *Object) ArrInsert(index int, value interface{}) (err error) {

func (o *Object) ArrRemove(index int) (err error) {
switch o.val.(type) {
case *ArrayData:
case *arrayData:
var (
arr, arrBefore, arrAfter, arrRes ArrayData
arr, arrBefore, arrAfter, arrRes arrayData
)
arr = *o.val.(*ArrayData)
arr = *o.val.(*arrayData)
// overflow
if index < 0 || index >= len(arr) {
return IndexOverflowErr{index}
}
// before
arrBefore = ArrayData{}
arrBefore = arrayData{}
if index > 0 {
arrBefore = append(arrBefore, arr[:index]...)
}
// after
arrAfter = ArrayData{}
arrAfter = arrayData{}
if index < len(arr)-1 {
arrAfter = append(arrAfter, arr[index+1:]...)
}
// generate
arrRes = append(arrBefore, arrAfter...)
*o.val.(*ArrayData) = arrRes
*o.val.(*arrayData) = arrRes
return nil
default:
return InvalidTypeErr("")
Expand All @@ -144,8 +144,8 @@ func (o *Object) ArrRemove(index int) (err error) {

func (o *Object) ArrForeach(do func(index int, obj *Object)) (err error) {
switch o.val.(type) {
case *ArrayData:
for i, obj := range *o.ValArr() {
case *arrayData:
for i, obj := range *o.valArr() {
do(i, obj)
}
return nil
Expand All @@ -156,8 +156,8 @@ func (o *Object) ArrForeach(do func(index int, obj *Object)) (err error) {

func (o *Object) ArrLen() (int, error) {
switch o.val.(type) {
case *ArrayData:
return len(*o.val.(*ArrayData)), nil
case *arrayData:
return len(*o.val.(*arrayData)), nil
default:
return -1, InvalidTypeErr("")
}
Expand Down
55 changes: 40 additions & 15 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func split(keyStr string) (keys []string) {
//
// The func panic at:
// 1. the key is not found and `createLost` is false
// 2. the key is middle of `keyStr` and has an object type neither *GroupData nor *ArrayData
// 2. the key is middle of `keyStr` and has an object type neither *groupData nor *arrayData
// 3. the key behind an Array Object key doesn't satisfy the rule with ArrayName.[index]
func splitAndDig(current *Object, keyStr string, createLost bool) *Object {
tObj := current
Expand All @@ -35,16 +35,16 @@ func splitAndDig(current *Object, keyStr string, createLost bool) *Object {
// Once the code runs here, the tObj means the parent of the param key.
// After this switch, the tObj will be the object self assigned by the param key.
switch tObj.val.(type) {
case *GroupData:
if next, ok := (*tObj.val.(*GroupData))[key]; ok { // the key exists
case *groupData:
if next, ok := (*tObj.val.(*groupData))[key]; ok { // the key exists
tObj = next
} else if createLost { // not exists but can be created
mapObj := *tObj.val.(*GroupData)
mapObj := *tObj.val.(*groupData)
if i != len(keys)-1 { // is a middle key
if arrCheckIndexFormat(keys[i+1]) { // is Array
panic(InvalidKeyStrErr(keyStr))
} else { // is Group
mapObj[key] = New(GroupData{})
mapObj[key] = New(groupData{})
}
} else { // is the last key
mapObj[key] = New(nil)
Expand All @@ -53,9 +53,9 @@ func splitAndDig(current *Object, keyStr string, createLost bool) *Object {
} else { // not found and panic
panic(InvalidKeyStrErr(keyStr))
}
case *ArrayData:
case *arrayData:
if index, err := tObj.arrCheckIndexKey(key, keyStr); err == nil {
tObj = (*tObj.val.(*ArrayData))[index]
tObj = (*tObj.val.(*arrayData))[index]
} else {
panic(err)
}
Expand All @@ -66,6 +66,11 @@ func splitAndDig(current *Object, keyStr string, createLost bool) *Object {
return tObj
}

// The process to make sure the param v is one of [*groupData, *arrayData, UnknownValue].
// All other recognizable types will be transform as:
// Object and *Object get their value and trans again
// groupData and arrayData trans to the pointer to them.
// Group and Array trans to the object-safe types (groupData and arrayData) to them
func getDeepestValue(v interface{}) interface{} {
tv := v
for {
Expand All @@ -74,18 +79,38 @@ func getDeepestValue(v interface{}) interface{} {
tv = tv.(Object).val
case *Object:
tv = tv.(*Object).val
case GroupData:
group := tv.(GroupData)
case groupData:
group := tv.(groupData)
return &group
case *GroupData:
return tv.(*GroupData)
case ArrayData:
arr := tv.(ArrayData)
case *groupData:
return tv.(*groupData)
case arrayData:
arr := tv.(arrayData)
return &arr
case *ArrayData:
return tv.(*ArrayData)
case *arrayData:
return tv.(*arrayData)
case Group:
tv = transGroupToGroupData(tv.(Group))
case Array:
tv = transArrayToArrayData(tv.(Array))
default:
return tv
}
}
}

func transArrayToArrayData(array Array) *arrayData {
data := New(arrayData{})
for _, v := range array {
_ = data.ArrPush(getDeepestValue(v))
}
return data.val.(*arrayData)
}

func transGroupToGroupData(group Group) *groupData {
data := New(groupData{})
for k, v := range group {
_ = data.Set(k, getDeepestValue(v))
}
return data.val.(*groupData)
}
51 changes: 26 additions & 25 deletions m2obj.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ type Object struct {
val interface{}
}

type GroupData map[string]*Object
type ArrayData []*Object
type Group map[string]interface{}
type Array []interface{}
type groupData map[string]*Object
type arrayData []*Object

type DataFormatter interface {
Marshal(obj *Object) (objStr string, err error)
Expand Down Expand Up @@ -118,8 +120,8 @@ func (o *Object) Remove(keyStr string) bool {
parentObj = o
}
switch parentObj.val.(type) {
case *GroupData:
delete(*parentObj.val.(*GroupData), key)
case *groupData:
delete(*parentObj.val.(*groupData), key)
return true
default:
return false
Expand Down Expand Up @@ -178,29 +180,29 @@ func (o *Object) ValFloat64() float64 {
// Returns a pointer to the Object's core array val to achieve more advanced operations on it.
//
// This func is the only one which has writable access to the val of an Object. So be careful.
func (o *Object) ValArr() *ArrayData {
return o.val.(*ArrayData)
func (o *Object) valArr() *arrayData {
return o.val.(*arrayData)
}

// staticize without the wrapper, for different object type, it returns different type:
// Group: map[string]interface{}
// Array: []interface{}
// Value: interface{}
// group: map[string]interface{}
// array: []interface{}
// value: interface{}
func (o *Object) staticize() interface{} {
switch o.val.(type) {
case *GroupData: // Group
case *groupData: // Group
m := make(map[string]interface{})
for k, v := range *o.val.(*GroupData) {
for k, v := range *o.val.(*groupData) {
if v == nil {
m[k] = nil
} else {
m[k] = v.staticize()
}
}
return m
case *ArrayData: // Array
m := make([]interface{}, len(*o.val.(*ArrayData)))
for i, v := range *o.val.(*ArrayData) {
case *arrayData: // Array
m := make([]interface{}, len(*o.val.(*arrayData)))
for i, v := range *o.val.(*arrayData) {
if v == nil {
m[i] = nil
} else {
Expand All @@ -219,9 +221,9 @@ func (o *Object) staticize() interface{} {

func (o *Object) Staticize() map[string]interface{} {
switch o.val.(type) {
case *GroupData: // Group
case *groupData: // Group
return o.staticize().(map[string]interface{})
case *ArrayData: // Array
case *arrayData: // Array
return map[string]interface{}{
"list": o.staticize().([]interface{}),
}
Expand All @@ -234,15 +236,15 @@ func (o *Object) Staticize() map[string]interface{} {

func (o *Object) Clone() (newObj *Object) {
switch o.val.(type) {
case *GroupData: // Group
newObj = New(GroupData{})
for k, obj := range *o.val.(*GroupData) {
case *groupData: // Group
newObj = New(groupData{})
for k, obj := range *o.val.(*groupData) {
_ = newObj.Set(k, obj.Clone())
}
return
case *ArrayData: // Array
newObj = New(ArrayData{})
for _, obj := range *o.val.(*ArrayData) {
case *arrayData: // Array
newObj = New(arrayData{})
for _, obj := range *o.val.(*arrayData) {
_ = newObj.ArrPush(obj.val)
}
return
Expand All @@ -252,7 +254,6 @@ func (o *Object) Clone() (newObj *Object) {
}
}

// TODO: 在新建Group和Array时减少New出现的频率, 把*Object类型限定放宽为interface{}, 然后由代码自己处理成*Object
func New(value interface{}) *Object {
t := getDeepestValue(value)
return &Object{
Expand All @@ -261,13 +262,13 @@ func New(value interface{}) *Object {
}

func NewFromMap(m map[string]interface{}) *Object {
obj := New(GroupData{})
obj := New(groupData{})
for k, v := range m {
switch v.(type) {
case map[string]interface{}:
_ = obj.Set(k, NewFromMap(v.(map[string]interface{})))
case []interface{}:
arr := New(ArrayData{})
arr := New(arrayData{})
for _, v2 := range v.([]interface{}) {
_ = arr.ArrPush(v2)
}
Expand Down
Loading

0 comments on commit 3413842

Please sign in to comment.