...

Source file src/github.com/json-iterator/go/iter_object.go

Documentation: github.com/json-iterator/go

     1  package jsoniter
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  // ReadObject read one field from object.
     9  // If object ended, returns empty string.
    10  // Otherwise, returns the field name.
    11  func (iter *Iterator) ReadObject() (ret string) {
    12  	c := iter.nextToken()
    13  	switch c {
    14  	case 'n':
    15  		iter.skipThreeBytes('u', 'l', 'l')
    16  		return "" // null
    17  	case '{':
    18  		c = iter.nextToken()
    19  		if c == '"' {
    20  			iter.unreadByte()
    21  			field := iter.ReadString()
    22  			c = iter.nextToken()
    23  			if c != ':' {
    24  				iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
    25  			}
    26  			return field
    27  		}
    28  		if c == '}' {
    29  			return "" // end of object
    30  		}
    31  		iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c}))
    32  		return
    33  	case ',':
    34  		field := iter.ReadString()
    35  		c = iter.nextToken()
    36  		if c != ':' {
    37  			iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
    38  		}
    39  		return field
    40  	case '}':
    41  		return "" // end of object
    42  	default:
    43  		iter.ReportError("ReadObject", fmt.Sprintf(`expect { or , or } or n, but found %s`, string([]byte{c})))
    44  		return
    45  	}
    46  }
    47  
    48  // CaseInsensitive
    49  func (iter *Iterator) readFieldHash() int64 {
    50  	hash := int64(0x811c9dc5)
    51  	c := iter.nextToken()
    52  	if c != '"' {
    53  		iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c}))
    54  		return 0
    55  	}
    56  	for {
    57  		for i := iter.head; i < iter.tail; i++ {
    58  			// require ascii string and no escape
    59  			b := iter.buf[i]
    60  			if b == '\\' {
    61  				iter.head = i
    62  				for _, b := range iter.readStringSlowPath() {
    63  					if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
    64  						b += 'a' - 'A'
    65  					}
    66  					hash ^= int64(b)
    67  					hash *= 0x1000193
    68  				}
    69  				c = iter.nextToken()
    70  				if c != ':' {
    71  					iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
    72  					return 0
    73  				}
    74  				return hash
    75  			}
    76  			if b == '"' {
    77  				iter.head = i + 1
    78  				c = iter.nextToken()
    79  				if c != ':' {
    80  					iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
    81  					return 0
    82  				}
    83  				return hash
    84  			}
    85  			if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
    86  				b += 'a' - 'A'
    87  			}
    88  			hash ^= int64(b)
    89  			hash *= 0x1000193
    90  		}
    91  		if !iter.loadMore() {
    92  			iter.ReportError("readFieldHash", `incomplete field name`)
    93  			return 0
    94  		}
    95  	}
    96  }
    97  
    98  func calcHash(str string, caseSensitive bool) int64 {
    99  	if !caseSensitive {
   100  		str = strings.ToLower(str)
   101  	}
   102  	hash := int64(0x811c9dc5)
   103  	for _, b := range []byte(str) {
   104  		hash ^= int64(b)
   105  		hash *= 0x1000193
   106  	}
   107  	return int64(hash)
   108  }
   109  
   110  // ReadObjectCB read object with callback, the key is ascii only and field name not copied
   111  func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
   112  	c := iter.nextToken()
   113  	var field string
   114  	if c == '{' {
   115  		if !iter.incrementDepth() {
   116  			return false
   117  		}
   118  		c = iter.nextToken()
   119  		if c == '"' {
   120  			iter.unreadByte()
   121  			field = iter.ReadString()
   122  			c = iter.nextToken()
   123  			if c != ':' {
   124  				iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
   125  			}
   126  			if !callback(iter, field) {
   127  				iter.decrementDepth()
   128  				return false
   129  			}
   130  			c = iter.nextToken()
   131  			for c == ',' {
   132  				field = iter.ReadString()
   133  				c = iter.nextToken()
   134  				if c != ':' {
   135  					iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
   136  				}
   137  				if !callback(iter, field) {
   138  					iter.decrementDepth()
   139  					return false
   140  				}
   141  				c = iter.nextToken()
   142  			}
   143  			if c != '}' {
   144  				iter.ReportError("ReadObjectCB", `object not ended with }`)
   145  				iter.decrementDepth()
   146  				return false
   147  			}
   148  			return iter.decrementDepth()
   149  		}
   150  		if c == '}' {
   151  			return iter.decrementDepth()
   152  		}
   153  		iter.ReportError("ReadObjectCB", `expect " after {, but found `+string([]byte{c}))
   154  		iter.decrementDepth()
   155  		return false
   156  	}
   157  	if c == 'n' {
   158  		iter.skipThreeBytes('u', 'l', 'l')
   159  		return true // null
   160  	}
   161  	iter.ReportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c}))
   162  	return false
   163  }
   164  
   165  // ReadMapCB read map with callback, the key can be any string
   166  func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
   167  	c := iter.nextToken()
   168  	if c == '{' {
   169  		if !iter.incrementDepth() {
   170  			return false
   171  		}
   172  		c = iter.nextToken()
   173  		if c == '"' {
   174  			iter.unreadByte()
   175  			field := iter.ReadString()
   176  			if iter.nextToken() != ':' {
   177  				iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
   178  				iter.decrementDepth()
   179  				return false
   180  			}
   181  			if !callback(iter, field) {
   182  				iter.decrementDepth()
   183  				return false
   184  			}
   185  			c = iter.nextToken()
   186  			for c == ',' {
   187  				field = iter.ReadString()
   188  				if iter.nextToken() != ':' {
   189  					iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
   190  					iter.decrementDepth()
   191  					return false
   192  				}
   193  				if !callback(iter, field) {
   194  					iter.decrementDepth()
   195  					return false
   196  				}
   197  				c = iter.nextToken()
   198  			}
   199  			if c != '}' {
   200  				iter.ReportError("ReadMapCB", `object not ended with }`)
   201  				iter.decrementDepth()
   202  				return false
   203  			}
   204  			return iter.decrementDepth()
   205  		}
   206  		if c == '}' {
   207  			return iter.decrementDepth()
   208  		}
   209  		iter.ReportError("ReadMapCB", `expect " after {, but found `+string([]byte{c}))
   210  		iter.decrementDepth()
   211  		return false
   212  	}
   213  	if c == 'n' {
   214  		iter.skipThreeBytes('u', 'l', 'l')
   215  		return true // null
   216  	}
   217  	iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
   218  	return false
   219  }
   220  
   221  func (iter *Iterator) readObjectStart() bool {
   222  	c := iter.nextToken()
   223  	if c == '{' {
   224  		c = iter.nextToken()
   225  		if c == '}' {
   226  			return false
   227  		}
   228  		iter.unreadByte()
   229  		return true
   230  	} else if c == 'n' {
   231  		iter.skipThreeBytes('u', 'l', 'l')
   232  		return false
   233  	}
   234  	iter.ReportError("readObjectStart", "expect { or n, but found "+string([]byte{c}))
   235  	return false
   236  }
   237  
   238  func (iter *Iterator) readObjectFieldAsBytes() (ret []byte) {
   239  	str := iter.ReadStringAsSlice()
   240  	if iter.skipWhitespacesWithoutLoadMore() {
   241  		if ret == nil {
   242  			ret = make([]byte, len(str))
   243  			copy(ret, str)
   244  		}
   245  		if !iter.loadMore() {
   246  			return
   247  		}
   248  	}
   249  	if iter.buf[iter.head] != ':' {
   250  		iter.ReportError("readObjectFieldAsBytes", "expect : after object field, but found "+string([]byte{iter.buf[iter.head]}))
   251  		return
   252  	}
   253  	iter.head++
   254  	if iter.skipWhitespacesWithoutLoadMore() {
   255  		if ret == nil {
   256  			ret = make([]byte, len(str))
   257  			copy(ret, str)
   258  		}
   259  		if !iter.loadMore() {
   260  			return
   261  		}
   262  	}
   263  	if ret == nil {
   264  		return str
   265  	}
   266  	return ret
   267  }
   268  

View as plain text