github.com/influx6/npkg@v0.8.8/njson/json.go (about)

     1  package njson
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"strconv"
     7  	"sync"
     8  	"sync/atomic"
     9  	"unsafe"
    10  
    11  	"github.com/influx6/npkg"
    12  )
    13  
    14  var (
    15  	comma            = []byte(",")
    16  	colon            = []byte(":")
    17  	space            = []byte(" ")
    18  	openBlock        = []byte("{")
    19  	closingBlock     = []byte("}")
    20  	openBlockList    = []byte("[")
    21  	closingBlockList = []byte("]")
    22  	doubleQuote      = []byte("\"")
    23  	logEventPool     = sync.Pool{
    24  		New: func() interface{} {
    25  			return &JSON{content: make([]byte, 0, 512), r: 1}
    26  		},
    27  	}
    28  )
    29  
    30  var _ npkg.Error = (*JSON)(nil)
    31  var _ npkg.ObjectEncoder = (*JSON)(nil)
    32  var _ npkg.ListEncoder = (*JSON)(nil)
    33  
    34  // JSONL creates a json list.
    35  func JSONL(inherits ...func(event npkg.Encoder)) *JSON {
    36  	event := logEventPool.Get().(*JSON)
    37  	event.l = 1
    38  	event.reset()
    39  
    40  	for _, op := range inherits {
    41  		op(event)
    42  		if event.err != nil {
    43  			return event
    44  		}
    45  	}
    46  	return event
    47  }
    48  
    49  // JSONB creates a json hash.
    50  func JSONB(inherits ...func(event npkg.Encoder)) *JSON {
    51  	event := logEventPool.Get().(*JSON)
    52  	event.l = 0
    53  	event.reset()
    54  
    55  	for _, op := range inherits {
    56  		op(event)
    57  		if event.err != nil {
    58  			return event
    59  		}
    60  	}
    61  	return event
    62  }
    63  
    64  // MJSON creates a json object with a message field with provided message.
    65  func MJSON(message string, inherits ...func(event npkg.Encoder)) *JSON {
    66  	event := logEventPool.Get().(*JSON)
    67  	event.l = 0
    68  
    69  	event.reset()
    70  	event.addQuotedString("message", message)
    71  	event.endEntry()
    72  
    73  	for _, op := range inherits {
    74  		op(event)
    75  		if event.err != nil {
    76  			return event
    77  		}
    78  	}
    79  	return event
    80  }
    81  
    82  //************************************************************
    83  // JSON
    84  //************************************************************
    85  
    86  var (
    87  	_ npkg.Encoder = (*JSON)(nil)
    88  )
    89  
    90  // JSON implements a efficient zero or near zero-allocation as much as possible,
    91  // using a underline non-strict json format to transform log key-value pairs into
    92  // a LogMessage.
    93  //
    94  // Each JSON iss retrieved from a logPool and will panic if after release/write it is used.
    95  type JSON struct {
    96  	err       error
    97  	l         int8
    98  	r         uint32
    99  	content   []byte
   100  	onRelease func([]byte) []byte
   101  }
   102  
   103  func (l *JSON) AddFormatted(format string, m interface{}) {
   104  	l.AddString(fmt.Sprintf(format, m))
   105  }
   106  
   107  func (l *JSON) Formatted(k string, format string, m interface{}) {
   108  	l.String(k, fmt.Sprintf(format, m))
   109  }
   110  
   111  func (l *JSON) AddStringMap(m map[string]string) {
   112  	l.AddObjectWith(func(event npkg.ObjectEncoder) {
   113  		npkg.EncodableStringMap(m).EncodeObject(event)
   114  	})
   115  }
   116  
   117  func (l *JSON) AddMap(m map[string]interface{}) {
   118  	l.AddObjectWith(func(event npkg.ObjectEncoder) {
   119  		npkg.EncodableMap(m).EncodeObject(event)
   120  	})
   121  }
   122  
   123  func (l *JSON) StringMap(key string, m map[string]string) {
   124  	l.ObjectFor(key, func(event npkg.ObjectEncoder) {
   125  		npkg.EncodableStringMap(m).EncodeObject(event)
   126  	})
   127  }
   128  
   129  func (l *JSON) Map(k string, m map[string]interface{}) {
   130  	l.ObjectFor(k, func(event npkg.ObjectEncoder) {
   131  		npkg.EncodableMap(m).EncodeObject(event)
   132  	})
   133  }
   134  
   135  func (l *JSON) AddList(list npkg.EncodableList) {
   136  	l.AddListWith(list.EncodeList)
   137  }
   138  
   139  func (l *JSON) AddObject(object npkg.EncodableObject) {
   140  	l.AddObjectWith(object.EncodeObject)
   141  }
   142  
   143  func (l *JSON) List(k string, list npkg.EncodableList) {
   144  	l.ListFor(k, list.EncodeList)
   145  }
   146  
   147  func (l *JSON) Object(k string, object npkg.EncodableObject) {
   148  	l.ObjectFor(k, object.EncodeObject)
   149  }
   150  
   151  func (l *JSON) Err() error {
   152  	return l.err
   153  }
   154  
   155  // Message returns the generated JSON of giving *JSON.
   156  func (l *JSON) Message() string {
   157  	if l.released() {
   158  		panic("Re-using released *JSON")
   159  	}
   160  
   161  	// remove last comma and space
   162  	total := len(comma) + len(space)
   163  	l.reduce(total)
   164  	l.end()
   165  
   166  	if l.onRelease != nil {
   167  		l.content = l.onRelease(l.content)
   168  		l.onRelease = nil
   169  	}
   170  
   171  	cn := make([]byte, len(l.content))
   172  	copy(cn, l.content)
   173  
   174  	l.resetContent()
   175  	l.release()
   176  	return bytes2String(cn)
   177  }
   178  
   179  // Release releases the JSON object back into the logPool.
   180  func (l *JSON) Release() {
   181  	l.resetContent()
   182  	l.release()
   183  }
   184  
   185  // WriteTo implements io.WriterTo interface.
   186  func (l *JSON) WriteTo(w io.Writer) (int64, error) {
   187  	if l.released() {
   188  		panic("Re-using released *JSON")
   189  	}
   190  
   191  	// if there is an error then talk about it.
   192  	if l.err != nil {
   193  		return -1, l.err
   194  	}
   195  
   196  	// remove last comma and space
   197  	total := len(comma) + len(space)
   198  	l.reduce(total)
   199  	l.end()
   200  
   201  	if l.onRelease != nil {
   202  		l.content = l.onRelease(l.content)
   203  		l.onRelease = nil
   204  	}
   205  
   206  	var n, err = w.Write(l.content)
   207  	l.err = err
   208  	l.resetContent()
   209  	l.release()
   210  	return int64(n), err
   211  }
   212  
   213  // ObjectFor adds a field name with object value.
   214  func (l *JSON) ObjectFor(name string, handler func(event npkg.ObjectEncoder)) {
   215  	l.panicIfList()
   216  
   217  	newEvent := logEventPool.Get().(*JSON)
   218  	newEvent.l = 0
   219  	newEvent.reset()
   220  
   221  	lastLen := len(newEvent.Buf())
   222  	handler(newEvent)
   223  	afterLen := len(newEvent.Buf())
   224  
   225  	if afterLen > lastLen {
   226  		total := len(comma) + len(space)
   227  		newEvent.reduce(total)
   228  	}
   229  	newEvent.end()
   230  
   231  	l.appendBytes(name, newEvent.Buf())
   232  	l.endEntry()
   233  
   234  	newEvent.resetContent()
   235  	newEvent.release()
   236  	if newEvent.err != nil {
   237  		l.err = newEvent.err
   238  	}
   239  }
   240  
   241  // ListFor adds a field name with list value.
   242  func (l *JSON) ListFor(name string, handler func(event npkg.ListEncoder)) {
   243  	l.panicIfList()
   244  
   245  	// stop if error
   246  	if l.err != nil {
   247  		return
   248  	}
   249  
   250  	newEvent := logEventPool.Get().(*JSON)
   251  	newEvent.l = 1
   252  	newEvent.reset()
   253  
   254  	lastLen := len(newEvent.Buf())
   255  	handler(newEvent)
   256  	afterLen := len(newEvent.Buf())
   257  
   258  	if afterLen > lastLen {
   259  		total := len(comma) + len(space)
   260  		newEvent.reduce(total)
   261  	}
   262  	newEvent.end()
   263  
   264  	l.appendBytes(name, newEvent.Buf())
   265  	l.endEntry()
   266  
   267  	newEvent.resetContent()
   268  	newEvent.release()
   269  	if newEvent.err != nil {
   270  		l.err = newEvent.err
   271  	}
   272  }
   273  
   274  // AddList adds new list object with provided properties from provided function into
   275  // a new json list format. It will panic if you use it for a object format call.
   276  func (l *JSON) AddListWith(handler func(event npkg.ListEncoder)) {
   277  	l.panicIfObject()
   278  	// stop if error
   279  	if l.err != nil {
   280  		return
   281  	}
   282  
   283  	newEvent := logEventPool.Get().(*JSON)
   284  	newEvent.l = 1
   285  	newEvent.reset()
   286  
   287  	lastLen := len(newEvent.Buf())
   288  	handler(newEvent)
   289  	afterLen := len(newEvent.Buf())
   290  
   291  	if afterLen > lastLen {
   292  		total := len(comma) + len(space)
   293  		newEvent.reduce(total)
   294  	}
   295  	newEvent.end()
   296  
   297  	l.appendBytesList(newEvent.Buf())
   298  	l.endEntry()
   299  
   300  	newEvent.resetContent()
   301  	newEvent.release()
   302  
   303  	if newEvent.err != nil {
   304  		l.err = newEvent.err
   305  	}
   306  }
   307  
   308  // AddObject adds new object with provided properties from provided function into
   309  // a new json list format. It will panic if you use it for a object format call.
   310  func (l *JSON) AddObjectWith(handler func(event npkg.ObjectEncoder)) {
   311  	l.panicIfObject()
   312  	// stop if error
   313  	if l.err != nil {
   314  		return
   315  	}
   316  
   317  	newEvent := logEventPool.Get().(*JSON)
   318  	newEvent.l = 0
   319  	newEvent.reset()
   320  
   321  	lastLen := len(newEvent.Buf())
   322  	handler(newEvent)
   323  	afterLen := len(newEvent.Buf())
   324  
   325  	if afterLen > lastLen {
   326  		total := len(comma) + len(space)
   327  		newEvent.reduce(total)
   328  	}
   329  	newEvent.end()
   330  
   331  	l.appendBytesList(newEvent.Buf())
   332  	l.endEntry()
   333  
   334  	newEvent.resetContent()
   335  	newEvent.release()
   336  
   337  	if newEvent.err != nil {
   338  		l.err = newEvent.err
   339  	}
   340  }
   341  
   342  // AddError adds a string list item into encoding.
   343  func (l *JSON) AddError(value error) {
   344  	l.AddString(value.Error())
   345  }
   346  
   347  // AddString adds a string list item into encoding.
   348  func (l *JSON) AddString(value string) {
   349  	// stop if error
   350  	if l.err != nil {
   351  		return
   352  	}
   353  
   354  	l.panicIfObject()
   355  	l.addQuotedBytesListItem(string2Bytes(value))
   356  	l.endEntry()
   357  }
   358  
   359  // AddHex adds a hexed string list item into encoding.
   360  func (l *JSON) AddHex(value string) {
   361  	// stop if error
   362  	if l.err != nil {
   363  		return
   364  	}
   365  
   366  	l.panicIfObject()
   367  	l.addQuotedBytesListItem(string2Bytes(value))
   368  	l.endEntry()
   369  }
   370  
   371  // AddBool adds a bool value.
   372  func (l *JSON) AddBool(value bool) {
   373  	// stop if error
   374  	if l.err != nil {
   375  		return
   376  	}
   377  
   378  	l.panicIfObject()
   379  	l.appendItem(func(content []byte) []byte {
   380  		return strconv.AppendBool(content, value)
   381  	})
   382  	l.endEntry()
   383  }
   384  
   385  // AddInt adds a int value.
   386  func (l *JSON) AddInt(value int) {
   387  	// stop if error
   388  	if l.err != nil {
   389  		return
   390  	}
   391  
   392  	l.panicIfObject()
   393  	l.appendItem(func(content []byte) []byte {
   394  		return convertIntToString(content, int64(value), 10)
   395  	})
   396  	l.endEntry()
   397  }
   398  
   399  // AddInt8 adds a int8 value.
   400  func (l *JSON) AddInt8(value int8) {
   401  	// stop if error
   402  	if l.err != nil {
   403  		return
   404  	}
   405  
   406  	l.panicIfObject()
   407  	l.appendItem(func(content []byte) []byte {
   408  		return convertIntToString(content, int64(value), 10)
   409  	})
   410  	l.endEntry()
   411  }
   412  
   413  // AddInt16 adds a int16 value.
   414  func (l *JSON) AddInt16(value int16) {
   415  	// stop if error
   416  	if l.err != nil {
   417  		return
   418  	}
   419  
   420  	l.panicIfObject()
   421  	l.appendItem(func(content []byte) []byte {
   422  		return convertIntToString(content, int64(value), 10)
   423  	})
   424  	l.endEntry()
   425  }
   426  
   427  // AddInt32 adds a int32 value.
   428  func (l *JSON) AddInt32(value int32) {
   429  	// stop if error
   430  	if l.err != nil {
   431  		return
   432  	}
   433  
   434  	l.panicIfObject()
   435  	l.appendItem(func(content []byte) []byte {
   436  		return convertIntToString(content, int64(value), 10)
   437  	})
   438  	l.endEntry()
   439  }
   440  
   441  // AddInt64 adds a int64 value.
   442  func (l *JSON) AddInt64(value int64) {
   443  	// stop if error
   444  	if l.err != nil {
   445  		return
   446  	}
   447  
   448  	l.panicIfObject()
   449  	l.appendItem(func(content []byte) []byte {
   450  		return convertIntToString(content, value, 10)
   451  	})
   452  	l.endEntry()
   453  }
   454  
   455  // AddUInt adds a int value.
   456  func (l *JSON) AddUInt(value uint) {
   457  	// stop if error
   458  	if l.err != nil {
   459  		return
   460  	}
   461  
   462  	l.panicIfObject()
   463  	l.appendItem(func(content []byte) []byte {
   464  		return convertUIntToString(content, uint64(value), 10)
   465  	})
   466  	l.endEntry()
   467  }
   468  
   469  // AddUInt8 adds a int8 value.
   470  func (l *JSON) AddUInt8(value uint8) {
   471  	// stop if error
   472  	if l.err != nil {
   473  		return
   474  	}
   475  
   476  	l.panicIfObject()
   477  	l.appendItem(func(content []byte) []byte {
   478  		return convertUIntToString(content, uint64(value), 10)
   479  	})
   480  	l.endEntry()
   481  }
   482  
   483  // AddUInt16 adds a int16 value.
   484  func (l *JSON) AddUInt16(value uint16) {
   485  	// stop if error
   486  	if l.err != nil {
   487  		return
   488  	}
   489  
   490  	l.panicIfObject()
   491  	l.appendItem(func(content []byte) []byte {
   492  		return convertUIntToString(content, uint64(value), 10)
   493  	})
   494  	l.endEntry()
   495  }
   496  
   497  // AddUInt32 adds a int32 value.
   498  func (l *JSON) AddUInt32(value uint32) {
   499  	// stop if error
   500  	if l.err != nil {
   501  		return
   502  	}
   503  
   504  	l.panicIfObject()
   505  	l.appendItem(func(content []byte) []byte {
   506  		return convertUIntToString(content, uint64(value), 10)
   507  	})
   508  	l.endEntry()
   509  }
   510  
   511  // AddUInt64 adds a int64 value.
   512  func (l *JSON) AddUInt64(value uint64) {
   513  	// stop if error
   514  	if l.err != nil {
   515  		return
   516  	}
   517  
   518  	l.panicIfObject()
   519  	l.appendItem(func(content []byte) []byte {
   520  		return convertUIntToString(content, value, 10)
   521  	})
   522  	l.endEntry()
   523  }
   524  
   525  // AddBase64 adds a int64 value.
   526  func (l *JSON) AddBase64(value int64, base int) {
   527  	// stop if error
   528  	if l.err != nil {
   529  		return
   530  	}
   531  
   532  	l.panicIfObject()
   533  	l.appendItem(func(content []byte) []byte {
   534  		return convertIntToString(content, value, base)
   535  	})
   536  	l.endEntry()
   537  }
   538  
   539  // AddFloat64 adds a float64 value.
   540  func (l *JSON) AddFloat64(value float64) {
   541  	// stop if error
   542  	if l.err != nil {
   543  		return
   544  	}
   545  
   546  	l.panicIfObject()
   547  	l.appendItem(func(content []byte) []byte {
   548  		return convertFloatToString(content, value, 32)
   549  	})
   550  	l.endEntry()
   551  }
   552  
   553  // AddFloat32 adds a float32 value.
   554  func (l *JSON) AddFloat32(value float32) {
   555  	// stop if error
   556  	if l.err != nil {
   557  		return
   558  	}
   559  
   560  	l.panicIfObject()
   561  	l.appendItem(func(content []byte) []byte {
   562  		return convertFloatToString(content, float64(value), 32)
   563  	})
   564  	l.endEntry()
   565  }
   566  
   567  // AddBytes adds a bytes list value. The byte is expected to be
   568  // valid JSON, no checks are made to ensure this, you can mess up your JSON
   569  // if you do not use this correctly.
   570  func (l *JSON) AddBytes(value []byte) {
   571  	// stop if error
   572  	if l.err != nil {
   573  		return
   574  	}
   575  
   576  	l.panicIfObject()
   577  	l.appendBytesList(value)
   578  	l.endEntry()
   579  }
   580  
   581  func (l *JSON) AppendBytes(value []byte) {
   582  	// stop if error
   583  	if l.err != nil {
   584  		return
   585  	}
   586  
   587  	l.panicIfObject()
   588  	l.appendBytesList(value)
   589  	l.endEntry()
   590  }
   591  
   592  // AddQBytes adds a bytes value. The byte is expected to be
   593  // will be wrapped with quotation.
   594  func (l *JSON) AddQBytes(value []byte) {
   595  	// stop if error
   596  	if l.err != nil {
   597  		return
   598  	}
   599  
   600  	l.panicIfObject()
   601  	l.addQuotedBytesListItem(value)
   602  	l.endEntry()
   603  }
   604  
   605  // Error adds a field name with error value.
   606  func (l *JSON) Error(name string, value error) {
   607  	l.String(name, value.Error())
   608  }
   609  
   610  // String adds a field name with string value.
   611  func (l *JSON) String(name string, value string) {
   612  	// stop if error
   613  	if l.err != nil {
   614  		return
   615  	}
   616  
   617  	l.panicIfList()
   618  	l.addQuotedBytes(name, string2Bytes(value))
   619  	l.endEntry()
   620  }
   621  
   622  // Hex adds a field name with hex converted string value.
   623  func (l *JSON) Hex(name string, value string) {
   624  	// stop if error
   625  	if l.err != nil {
   626  		return
   627  	}
   628  
   629  	l.panicIfList()
   630  	l.addQuotedBytes(name, string2Bytes(value))
   631  	l.endEntry()
   632  
   633  }
   634  
   635  // Bytes adds a field name with bytes value. The byte is expected to be
   636  // valid JSON, no checks are made to ensure this, you can mess up your JSON
   637  // if you do not use this correctly.
   638  func (l *JSON) Bytes(name string, value []byte) {
   639  	// stop if error
   640  	if l.err != nil {
   641  		return
   642  	}
   643  
   644  	l.panicIfList()
   645  	l.appendListBytesKV(name, value)
   646  	l.endEntry()
   647  }
   648  
   649  // QBytes adds a field name with bytes value. The byte is expected to be
   650  // will be wrapped with quotation.
   651  func (l *JSON) QBytes(name string, value []byte) {
   652  	// stop if error
   653  	if l.err != nil {
   654  		return
   655  	}
   656  
   657  	l.panicIfList()
   658  	l.addQuotedBytes(name, value)
   659  	l.endEntry()
   660  
   661  }
   662  
   663  // Bool adds a field name with bool value.
   664  func (l *JSON) Bool(name string, value bool) {
   665  	// stop if error
   666  	if l.err != nil {
   667  		return
   668  	}
   669  
   670  	l.panicIfList()
   671  	l.appendItem(func(content []byte) []byte {
   672  		content = append(content, doubleQuote...)
   673  		content = append(content, name...)
   674  		content = append(content, doubleQuote...)
   675  		content = append(content, colon...)
   676  		content = append(content, space...)
   677  		content = strconv.AppendBool(content, value)
   678  		return content
   679  	})
   680  	l.endEntry()
   681  }
   682  
   683  // Base64 adds a field name with int value formatted to base n.
   684  func (l *JSON) Base64(name string, value int64, base int) {
   685  	// stop if error
   686  	if l.err != nil {
   687  		return
   688  	}
   689  
   690  	l.panicIfList()
   691  	l.appendItem(func(content []byte) []byte {
   692  		content = append(content, doubleQuote...)
   693  		content = append(content, name...)
   694  		content = append(content, doubleQuote...)
   695  		content = append(content, colon...)
   696  		content = append(content, space...)
   697  		content = convertIntToString(content, value, base)
   698  		return content
   699  	})
   700  	l.endEntry()
   701  
   702  }
   703  
   704  // Int adds a field name with int value.
   705  func (l *JSON) Int(name string, value int) {
   706  	// stop if error
   707  	if l.err != nil {
   708  		return
   709  	}
   710  
   711  	l.panicIfList()
   712  	l.appendItem(func(content []byte) []byte {
   713  		content = append(content, doubleQuote...)
   714  		content = append(content, name...)
   715  		content = append(content, doubleQuote...)
   716  		content = append(content, colon...)
   717  		content = append(content, space...)
   718  		content = convertIntToString(content, int64(value), 10)
   719  		return content
   720  	})
   721  	l.endEntry()
   722  
   723  }
   724  
   725  // UInt adds a field name with int value.
   726  func (l *JSON) UInt(name string, value uint) {
   727  	// stop if error
   728  	if l.err != nil {
   729  		return
   730  	}
   731  
   732  	l.panicIfList()
   733  	l.appendItem(func(content []byte) []byte {
   734  		content = append(content, doubleQuote...)
   735  		content = append(content, name...)
   736  		content = append(content, doubleQuote...)
   737  		content = append(content, colon...)
   738  		content = append(content, space...)
   739  		content = convertUIntToString(content, uint64(value), 10)
   740  		return content
   741  	})
   742  	l.endEntry()
   743  
   744  }
   745  
   746  // Int8 adds a field name with int8 value.
   747  func (l *JSON) Int8(name string, value int8) {
   748  	// stop if error
   749  	if l.err != nil {
   750  		return
   751  	}
   752  
   753  	l.panicIfList()
   754  	l.appendItem(func(content []byte) []byte {
   755  		content = append(content, doubleQuote...)
   756  		content = append(content, name...)
   757  		content = append(content, doubleQuote...)
   758  		content = append(content, colon...)
   759  		content = append(content, space...)
   760  		content = convertIntToString(content, int64(value), 10)
   761  		return content
   762  	})
   763  	l.endEntry()
   764  
   765  }
   766  
   767  // Int16 adds a field name with int16 value.
   768  func (l *JSON) Int16(name string, value int16) {
   769  	// stop if error
   770  	if l.err != nil {
   771  		return
   772  	}
   773  
   774  	l.panicIfList()
   775  	l.appendItem(func(content []byte) []byte {
   776  		content = append(content, doubleQuote...)
   777  		content = append(content, name...)
   778  		content = append(content, doubleQuote...)
   779  		content = append(content, colon...)
   780  		content = append(content, space...)
   781  		content = convertIntToString(content, int64(value), 10)
   782  		return content
   783  	})
   784  	l.endEntry()
   785  
   786  }
   787  
   788  // Int32 adds a field name with int32 value.
   789  func (l *JSON) Int32(name string, value int32) {
   790  	// stop if error
   791  	if l.err != nil {
   792  		return
   793  	}
   794  
   795  	l.panicIfList()
   796  	l.appendItem(func(content []byte) []byte {
   797  		content = append(content, doubleQuote...)
   798  		content = append(content, name...)
   799  		content = append(content, doubleQuote...)
   800  		content = append(content, colon...)
   801  		content = append(content, space...)
   802  		content = convertIntToString(content, int64(value), 10)
   803  		return content
   804  	})
   805  	l.endEntry()
   806  
   807  }
   808  
   809  // Int64 adds a field name with int64 value.
   810  func (l *JSON) Int64(name string, value int64) {
   811  	// stop if error
   812  	if l.err != nil {
   813  		return
   814  	}
   815  
   816  	l.panicIfList()
   817  	l.appendItem(func(content []byte) []byte {
   818  		content = append(content, doubleQuote...)
   819  		content = append(content, name...)
   820  		content = append(content, doubleQuote...)
   821  		content = append(content, colon...)
   822  		content = append(content, space...)
   823  		content = convertIntToString(content, int64(value), 10)
   824  		return content
   825  	})
   826  	l.endEntry()
   827  }
   828  
   829  // UInt8 adds a field name with uint8 value.
   830  func (l *JSON) UInt8(name string, value uint8) {
   831  	// stop if error
   832  	if l.err != nil {
   833  		return
   834  	}
   835  
   836  	l.panicIfList()
   837  	l.appendItem(func(content []byte) []byte {
   838  		content = append(content, doubleQuote...)
   839  		content = append(content, name...)
   840  		content = append(content, doubleQuote...)
   841  		content = append(content, colon...)
   842  		content = append(content, space...)
   843  		content = convertUIntToString(content, uint64(value), 10)
   844  		return content
   845  	})
   846  	l.endEntry()
   847  
   848  }
   849  
   850  // UInt16 adds a field name with uint16 value.
   851  func (l *JSON) UInt16(name string, value uint16) {
   852  	// stop if error
   853  	if l.err != nil {
   854  		return
   855  	}
   856  
   857  	l.panicIfList()
   858  	l.appendItem(func(content []byte) []byte {
   859  		content = append(content, doubleQuote...)
   860  		content = append(content, name...)
   861  		content = append(content, doubleQuote...)
   862  		content = append(content, colon...)
   863  		content = append(content, space...)
   864  		content = convertUIntToString(content, uint64(value), 10)
   865  		return content
   866  	})
   867  	l.endEntry()
   868  
   869  }
   870  
   871  func (l *JSON) Byte(name string, value byte) {
   872  	l.panicIfList()
   873  
   874  	l.appendItem(func(content []byte) []byte {
   875  		content = append(content, doubleQuote...)
   876  		content = append(content, name...)
   877  		content = append(content, doubleQuote...)
   878  		content = append(content, colon...)
   879  		content = append(content, space...)
   880  		content = append(content, value)
   881  		return content
   882  	})
   883  	l.endEntry()
   884  }
   885  
   886  func (l *JSON) AddByte(value byte) {
   887  	l.panicIfList()
   888  
   889  	l.appendItem(func(content []byte) []byte {
   890  		content = append(content, value)
   891  		return content
   892  	})
   893  	l.endEntry()
   894  }
   895  
   896  // UInt32 adds a field name with uint32 value.
   897  func (l *JSON) UInt32(name string, value uint32) {
   898  	// stop if error
   899  	if l.err != nil {
   900  		return
   901  	}
   902  
   903  	l.panicIfList()
   904  
   905  	l.appendItem(func(content []byte) []byte {
   906  		content = append(content, doubleQuote...)
   907  		content = append(content, name...)
   908  		content = append(content, doubleQuote...)
   909  		content = append(content, colon...)
   910  		content = append(content, space...)
   911  		content = convertUIntToString(content, uint64(value), 10)
   912  		return content
   913  	})
   914  	l.endEntry()
   915  
   916  }
   917  
   918  // UInt64 adds a field name with uint64 value.
   919  func (l *JSON) UInt64(name string, value uint64) {
   920  	// stop if error
   921  	if l.err != nil {
   922  		return
   923  	}
   924  
   925  	l.panicIfList()
   926  	l.appendItem(func(content []byte) []byte {
   927  		content = append(content, doubleQuote...)
   928  		content = append(content, name...)
   929  		content = append(content, doubleQuote...)
   930  		content = append(content, colon...)
   931  		content = append(content, space...)
   932  		content = convertUIntToString(content, value, 10)
   933  		return content
   934  	})
   935  	l.endEntry()
   936  
   937  }
   938  
   939  // Float64 adds a field name with float64 value.
   940  func (l *JSON) Float64(name string, value float64) {
   941  	// stop if error
   942  	if l.err != nil {
   943  		return
   944  	}
   945  
   946  	l.panicIfList()
   947  	l.appendItem(func(content []byte) []byte {
   948  		content = append(content, doubleQuote...)
   949  		content = append(content, name...)
   950  		content = append(content, doubleQuote...)
   951  		content = append(content, colon...)
   952  		content = append(content, space...)
   953  		content = convertFloatToString(content, value, 64)
   954  		return content
   955  	})
   956  	l.endEntry()
   957  
   958  }
   959  
   960  // Float32 adds a field name with float32 value.
   961  func (l *JSON) Float32(name string, value float32) {
   962  	// stop if error
   963  	if l.err != nil {
   964  		return
   965  	}
   966  
   967  	l.panicIfList()
   968  	l.appendItem(func(content []byte) []byte {
   969  		content = append(content, doubleQuote...)
   970  		content = append(content, name...)
   971  		content = append(content, doubleQuote...)
   972  		content = append(content, colon...)
   973  		content = append(content, space...)
   974  		content = convertFloatToString(content, float64(value), 32)
   975  		return content
   976  	})
   977  	l.endEntry()
   978  
   979  }
   980  
   981  // Buf returns the current content of the *JSON.
   982  func (l *JSON) Buf() []byte {
   983  	return l.content
   984  }
   985  
   986  func (l *JSON) reset() {
   987  	atomic.StoreUint32(&l.r, 1)
   988  	l.begin()
   989  }
   990  
   991  func (l *JSON) reduce(d int) {
   992  	available := len(l.content)
   993  	rem := available - d
   994  	if rem < 0 {
   995  		rem = 0
   996  	}
   997  	l.content = l.content[:rem]
   998  }
   999  
  1000  func (l *JSON) resetContent() {
  1001  	l.content = l.content[:0]
  1002  }
  1003  
  1004  func (l *JSON) released() bool {
  1005  	return atomic.LoadUint32(&l.r) == 0
  1006  }
  1007  
  1008  func (l *JSON) release() {
  1009  	atomic.StoreUint32(&l.r, 0)
  1010  	logEventPool.Put(l)
  1011  }
  1012  
  1013  func (l *JSON) begin() {
  1014  	l.appendItem(func(content []byte) []byte {
  1015  		if l.l == 1 {
  1016  			content = append(content, openBlockList...)
  1017  			return content
  1018  		}
  1019  		content = append(content, openBlock...)
  1020  		return content
  1021  	})
  1022  }
  1023  
  1024  func (l *JSON) panicIfObject() {
  1025  	if l.l == 0 {
  1026  		panic("unable to use for a json object format")
  1027  	}
  1028  }
  1029  
  1030  func (l *JSON) panicIfList() {
  1031  	if l.l == 1 {
  1032  		panic("unable to use for a json list format")
  1033  	}
  1034  }
  1035  
  1036  func (l *JSON) addQuotedString(k string, v string) {
  1037  	if l.released() {
  1038  		panic("Re-using released *JSON")
  1039  	}
  1040  
  1041  	l.appendItem(func(content []byte) []byte {
  1042  		content = append(content, doubleQuote...)
  1043  		content = append(content, k...)
  1044  		content = append(content, doubleQuote...)
  1045  		content = append(content, colon...)
  1046  		content = append(content, space...)
  1047  		content = append(content, doubleQuote...)
  1048  		content = append(content, v...)
  1049  		content = append(content, doubleQuote...)
  1050  		return content
  1051  	})
  1052  }
  1053  
  1054  func (l *JSON) addQuotedStringListItem(k string, v string) {
  1055  	if l.released() {
  1056  		panic("Re-using released *JSON")
  1057  	}
  1058  
  1059  	l.appendItem(func(content []byte) []byte {
  1060  		content = append(content, doubleQuote...)
  1061  		content = append(content, v...)
  1062  		content = append(content, doubleQuote...)
  1063  		return content
  1064  	})
  1065  }
  1066  
  1067  func (l *JSON) addString(k string, v string) {
  1068  	if l.released() {
  1069  		panic("Re-using released *JSON")
  1070  	}
  1071  
  1072  	l.appendItem(func(content []byte) []byte {
  1073  		content = append(content, doubleQuote...)
  1074  		content = append(content, k...)
  1075  		content = append(content, doubleQuote...)
  1076  		content = append(content, colon...)
  1077  		content = append(content, space...)
  1078  		content = append(content, v...)
  1079  		return content
  1080  	})
  1081  }
  1082  
  1083  func (l *JSON) addStringListItem(v string) {
  1084  	if l.released() {
  1085  		panic("Re-using released *JSON")
  1086  	}
  1087  
  1088  	l.appendItem(func(content []byte) []byte {
  1089  		content = append(content, v...)
  1090  		return content
  1091  	})
  1092  }
  1093  
  1094  func (l *JSON) addListBytes(v []byte) {
  1095  	if l.released() {
  1096  		panic("Re-using released *JSON")
  1097  	}
  1098  
  1099  	l.appendItem(func(content []byte) []byte {
  1100  		content = append(content, '[')
  1101  		content = append(content, v...)
  1102  		content = append(content, ']')
  1103  		return content
  1104  	})
  1105  }
  1106  
  1107  func (l *JSON) appendListBytesKV(k string, v []byte) {
  1108  	if l.released() {
  1109  		panic("Re-using released *JSON")
  1110  	}
  1111  
  1112  	l.appendItem(func(content []byte) []byte {
  1113  		content = append(content, doubleQuote...)
  1114  		content = append(content, k...)
  1115  		content = append(content, doubleQuote...)
  1116  		content = append(content, colon...)
  1117  		content = append(content, space...)
  1118  		content = append(content, v...)
  1119  		return content
  1120  	})
  1121  }
  1122  
  1123  func (l *JSON) addListBytesKV(k string, v []byte) {
  1124  	if l.released() {
  1125  		panic("Re-using released *JSON")
  1126  	}
  1127  
  1128  	l.appendItem(func(content []byte) []byte {
  1129  		content = append(content, doubleQuote...)
  1130  		content = append(content, k...)
  1131  		content = append(content, doubleQuote...)
  1132  		content = append(content, colon...)
  1133  		content = append(content, space...)
  1134  		content = append(content, '[')
  1135  		content = append(content, v...)
  1136  		content = append(content, ']')
  1137  		return content
  1138  	})
  1139  }
  1140  
  1141  func (l *JSON) addQuotedBytes(k string, v []byte) {
  1142  	if l.released() {
  1143  		panic("Re-using released *JSON")
  1144  	}
  1145  
  1146  	l.appendItem(func(content []byte) []byte {
  1147  		content = append(content, doubleQuote...)
  1148  		content = append(content, k...)
  1149  		content = append(content, doubleQuote...)
  1150  		content = append(content, colon...)
  1151  		content = append(content, space...)
  1152  		content = append(content, doubleQuote...)
  1153  		content = append(content, v...)
  1154  		content = append(content, doubleQuote...)
  1155  		return content
  1156  	})
  1157  }
  1158  
  1159  func (l *JSON) addQuotedBytesListItem(v []byte) {
  1160  	if l.released() {
  1161  		panic("Re-using released *JSON")
  1162  	}
  1163  
  1164  	l.appendItem(func(content []byte) []byte {
  1165  		content = append(content, doubleQuote...)
  1166  		content = append(content, v...)
  1167  		content = append(content, doubleQuote...)
  1168  		return content
  1169  	})
  1170  }
  1171  
  1172  func (l *JSON) appendBytes(k string, v []byte) {
  1173  	if l.released() {
  1174  		panic("Re-using released *JSON")
  1175  	}
  1176  
  1177  	l.appendItem(func(content []byte) []byte {
  1178  		content = append(content, doubleQuote...)
  1179  		content = append(content, k...)
  1180  		content = append(content, doubleQuote...)
  1181  		content = append(content, colon...)
  1182  		content = append(content, space...)
  1183  		content = append(content, v...)
  1184  		return content
  1185  	})
  1186  }
  1187  
  1188  func (l *JSON) appendBytesList(v []byte) {
  1189  	if l.released() {
  1190  		panic("Re-using released *JSON")
  1191  	}
  1192  
  1193  	l.appendItem(func(content []byte) []byte {
  1194  		content = append(content, v...)
  1195  		return content
  1196  	})
  1197  }
  1198  
  1199  func (l *JSON) endEntry() {
  1200  	l.appendItem(func(content []byte) []byte {
  1201  		content = append(content, comma...)
  1202  		content = append(content, space...)
  1203  		return content
  1204  	})
  1205  }
  1206  
  1207  func (l *JSON) end() {
  1208  	if l.l == 1 {
  1209  		l.appendItem(func(content []byte) []byte {
  1210  			return append(content, closingBlockList...)
  1211  		})
  1212  		return
  1213  	}
  1214  
  1215  	l.appendItem(func(content []byte) []byte {
  1216  		return append(content, closingBlock...)
  1217  	})
  1218  }
  1219  
  1220  func (l *JSON) appendItem(cb func([]byte) []byte) {
  1221  	l.content = cb(l.content)
  1222  }
  1223  
  1224  func convertIntToString(in []byte, v int64, b int) []byte {
  1225  	if v == 0 {
  1226  		return append(in, "0"...)
  1227  	}
  1228  
  1229  	return strconv.AppendInt(in, v, b)
  1230  }
  1231  
  1232  func convertFloatToString(in []byte, v float64, pre int) []byte {
  1233  	if v == 0 {
  1234  		return append(in, "0"...)
  1235  	}
  1236  
  1237  	return strconv.AppendFloat(in, v, 'E', -1, pre)
  1238  }
  1239  
  1240  func convertUIntToString(in []byte, v uint64, b int) []byte {
  1241  	if v == 0 {
  1242  		return append(in, "0"...)
  1243  	}
  1244  
  1245  	return strconv.AppendUint(in, v, b)
  1246  }
  1247  
  1248  //*****************************************************
  1249  // unsafe methods
  1250  //*****************************************************
  1251  
  1252  func bytes2String(bc []byte) string {
  1253  	return *(*string)(unsafe.Pointer(&bc))
  1254  }
  1255  
  1256  func string2Bytes(bc string) []byte {
  1257  	return *(*[]byte)(unsafe.Pointer(&bc))
  1258  }