iter_object.go raw

   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