github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go (about)

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package bsonrw
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/base64"
    12  	"fmt"
    13  	"io"
    14  	"math"
    15  	"sort"
    16  	"strconv"
    17  	"strings"
    18  	"sync"
    19  	"time"
    20  	"unicode/utf8"
    21  
    22  	"go.mongodb.org/mongo-driver/bson/primitive"
    23  )
    24  
    25  // ExtJSONValueWriterPool is a pool for ExtJSON ValueWriters.
    26  //
    27  // Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0.
    28  type ExtJSONValueWriterPool struct {
    29  	pool sync.Pool
    30  }
    31  
    32  // NewExtJSONValueWriterPool creates a new pool for ValueWriter instances that write to ExtJSON.
    33  //
    34  // Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0.
    35  func NewExtJSONValueWriterPool() *ExtJSONValueWriterPool {
    36  	return &ExtJSONValueWriterPool{
    37  		pool: sync.Pool{
    38  			New: func() interface{} {
    39  				return new(extJSONValueWriter)
    40  			},
    41  		},
    42  	}
    43  }
    44  
    45  // Get retrieves a ExtJSON ValueWriter from the pool and resets it to use w as the destination.
    46  //
    47  // Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0.
    48  func (bvwp *ExtJSONValueWriterPool) Get(w io.Writer, canonical, escapeHTML bool) ValueWriter {
    49  	vw := bvwp.pool.Get().(*extJSONValueWriter)
    50  	if writer, ok := w.(*SliceWriter); ok {
    51  		vw.reset(*writer, canonical, escapeHTML)
    52  		vw.w = writer
    53  		return vw
    54  	}
    55  	vw.buf = vw.buf[:0]
    56  	vw.w = w
    57  	return vw
    58  }
    59  
    60  // Put inserts a ValueWriter into the pool. If the ValueWriter is not a ExtJSON ValueWriter, nothing
    61  // happens and ok will be false.
    62  //
    63  // Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0.
    64  func (bvwp *ExtJSONValueWriterPool) Put(vw ValueWriter) (ok bool) {
    65  	bvw, ok := vw.(*extJSONValueWriter)
    66  	if !ok {
    67  		return false
    68  	}
    69  
    70  	if _, ok := bvw.w.(*SliceWriter); ok {
    71  		bvw.buf = nil
    72  	}
    73  	bvw.w = nil
    74  
    75  	bvwp.pool.Put(bvw)
    76  	return true
    77  }
    78  
    79  type ejvwState struct {
    80  	mode mode
    81  }
    82  
    83  type extJSONValueWriter struct {
    84  	w   io.Writer
    85  	buf []byte
    86  
    87  	stack      []ejvwState
    88  	frame      int64
    89  	canonical  bool
    90  	escapeHTML bool
    91  	newlines   bool
    92  }
    93  
    94  // NewExtJSONValueWriter creates a ValueWriter that writes Extended JSON to w.
    95  func NewExtJSONValueWriter(w io.Writer, canonical, escapeHTML bool) (ValueWriter, error) {
    96  	if w == nil {
    97  		return nil, errNilWriter
    98  	}
    99  
   100  	// Enable newlines for all Extended JSON value writers created by NewExtJSONValueWriter. We
   101  	// expect these value writers to be used with an Encoder, which should add newlines after
   102  	// encoded Extended JSON documents.
   103  	return newExtJSONWriter(w, canonical, escapeHTML, true), nil
   104  }
   105  
   106  func newExtJSONWriter(w io.Writer, canonical, escapeHTML, newlines bool) *extJSONValueWriter {
   107  	stack := make([]ejvwState, 1, 5)
   108  	stack[0] = ejvwState{mode: mTopLevel}
   109  
   110  	return &extJSONValueWriter{
   111  		w:          w,
   112  		buf:        []byte{},
   113  		stack:      stack,
   114  		canonical:  canonical,
   115  		escapeHTML: escapeHTML,
   116  		newlines:   newlines,
   117  	}
   118  }
   119  
   120  func newExtJSONWriterFromSlice(buf []byte, canonical, escapeHTML bool) *extJSONValueWriter {
   121  	stack := make([]ejvwState, 1, 5)
   122  	stack[0] = ejvwState{mode: mTopLevel}
   123  
   124  	return &extJSONValueWriter{
   125  		buf:        buf,
   126  		stack:      stack,
   127  		canonical:  canonical,
   128  		escapeHTML: escapeHTML,
   129  	}
   130  }
   131  
   132  func (ejvw *extJSONValueWriter) reset(buf []byte, canonical, escapeHTML bool) {
   133  	if ejvw.stack == nil {
   134  		ejvw.stack = make([]ejvwState, 1, 5)
   135  	}
   136  
   137  	ejvw.stack = ejvw.stack[:1]
   138  	ejvw.stack[0] = ejvwState{mode: mTopLevel}
   139  	ejvw.canonical = canonical
   140  	ejvw.escapeHTML = escapeHTML
   141  	ejvw.frame = 0
   142  	ejvw.buf = buf
   143  	ejvw.w = nil
   144  }
   145  
   146  func (ejvw *extJSONValueWriter) advanceFrame() {
   147  	if ejvw.frame+1 >= int64(len(ejvw.stack)) { // We need to grow the stack
   148  		length := len(ejvw.stack)
   149  		if length+1 >= cap(ejvw.stack) {
   150  			// double it
   151  			buf := make([]ejvwState, 2*cap(ejvw.stack)+1)
   152  			copy(buf, ejvw.stack)
   153  			ejvw.stack = buf
   154  		}
   155  		ejvw.stack = ejvw.stack[:length+1]
   156  	}
   157  	ejvw.frame++
   158  }
   159  
   160  func (ejvw *extJSONValueWriter) push(m mode) {
   161  	ejvw.advanceFrame()
   162  
   163  	ejvw.stack[ejvw.frame].mode = m
   164  }
   165  
   166  func (ejvw *extJSONValueWriter) pop() {
   167  	switch ejvw.stack[ejvw.frame].mode {
   168  	case mElement, mValue:
   169  		ejvw.frame--
   170  	case mDocument, mArray, mCodeWithScope:
   171  		ejvw.frame -= 2 // we pop twice to jump over the mElement: mDocument -> mElement -> mDocument/mTopLevel/etc...
   172  	}
   173  }
   174  
   175  func (ejvw *extJSONValueWriter) invalidTransitionErr(destination mode, name string, modes []mode) error {
   176  	te := TransitionError{
   177  		name:        name,
   178  		current:     ejvw.stack[ejvw.frame].mode,
   179  		destination: destination,
   180  		modes:       modes,
   181  		action:      "write",
   182  	}
   183  	if ejvw.frame != 0 {
   184  		te.parent = ejvw.stack[ejvw.frame-1].mode
   185  	}
   186  	return te
   187  }
   188  
   189  func (ejvw *extJSONValueWriter) ensureElementValue(destination mode, callerName string, addmodes ...mode) error {
   190  	switch ejvw.stack[ejvw.frame].mode {
   191  	case mElement, mValue:
   192  	default:
   193  		modes := []mode{mElement, mValue}
   194  		if addmodes != nil {
   195  			modes = append(modes, addmodes...)
   196  		}
   197  		return ejvw.invalidTransitionErr(destination, callerName, modes)
   198  	}
   199  
   200  	return nil
   201  }
   202  
   203  func (ejvw *extJSONValueWriter) writeExtendedSingleValue(key string, value string, quotes bool) {
   204  	var s string
   205  	if quotes {
   206  		s = fmt.Sprintf(`{"$%s":"%s"}`, key, value)
   207  	} else {
   208  		s = fmt.Sprintf(`{"$%s":%s}`, key, value)
   209  	}
   210  
   211  	ejvw.buf = append(ejvw.buf, []byte(s)...)
   212  }
   213  
   214  func (ejvw *extJSONValueWriter) WriteArray() (ArrayWriter, error) {
   215  	if err := ejvw.ensureElementValue(mArray, "WriteArray"); err != nil {
   216  		return nil, err
   217  	}
   218  
   219  	ejvw.buf = append(ejvw.buf, '[')
   220  
   221  	ejvw.push(mArray)
   222  	return ejvw, nil
   223  }
   224  
   225  func (ejvw *extJSONValueWriter) WriteBinary(b []byte) error {
   226  	return ejvw.WriteBinaryWithSubtype(b, 0x00)
   227  }
   228  
   229  func (ejvw *extJSONValueWriter) WriteBinaryWithSubtype(b []byte, btype byte) error {
   230  	if err := ejvw.ensureElementValue(mode(0), "WriteBinaryWithSubtype"); err != nil {
   231  		return err
   232  	}
   233  
   234  	var buf bytes.Buffer
   235  	buf.WriteString(`{"$binary":{"base64":"`)
   236  	buf.WriteString(base64.StdEncoding.EncodeToString(b))
   237  	buf.WriteString(fmt.Sprintf(`","subType":"%02x"}},`, btype))
   238  
   239  	ejvw.buf = append(ejvw.buf, buf.Bytes()...)
   240  
   241  	ejvw.pop()
   242  	return nil
   243  }
   244  
   245  func (ejvw *extJSONValueWriter) WriteBoolean(b bool) error {
   246  	if err := ejvw.ensureElementValue(mode(0), "WriteBoolean"); err != nil {
   247  		return err
   248  	}
   249  
   250  	ejvw.buf = append(ejvw.buf, []byte(strconv.FormatBool(b))...)
   251  	ejvw.buf = append(ejvw.buf, ',')
   252  
   253  	ejvw.pop()
   254  	return nil
   255  }
   256  
   257  func (ejvw *extJSONValueWriter) WriteCodeWithScope(code string) (DocumentWriter, error) {
   258  	if err := ejvw.ensureElementValue(mCodeWithScope, "WriteCodeWithScope"); err != nil {
   259  		return nil, err
   260  	}
   261  
   262  	var buf bytes.Buffer
   263  	buf.WriteString(`{"$code":`)
   264  	writeStringWithEscapes(code, &buf, ejvw.escapeHTML)
   265  	buf.WriteString(`,"$scope":{`)
   266  
   267  	ejvw.buf = append(ejvw.buf, buf.Bytes()...)
   268  
   269  	ejvw.push(mCodeWithScope)
   270  	return ejvw, nil
   271  }
   272  
   273  func (ejvw *extJSONValueWriter) WriteDBPointer(ns string, oid primitive.ObjectID) error {
   274  	if err := ejvw.ensureElementValue(mode(0), "WriteDBPointer"); err != nil {
   275  		return err
   276  	}
   277  
   278  	var buf bytes.Buffer
   279  	buf.WriteString(`{"$dbPointer":{"$ref":"`)
   280  	buf.WriteString(ns)
   281  	buf.WriteString(`","$id":{"$oid":"`)
   282  	buf.WriteString(oid.Hex())
   283  	buf.WriteString(`"}}},`)
   284  
   285  	ejvw.buf = append(ejvw.buf, buf.Bytes()...)
   286  
   287  	ejvw.pop()
   288  	return nil
   289  }
   290  
   291  func (ejvw *extJSONValueWriter) WriteDateTime(dt int64) error {
   292  	if err := ejvw.ensureElementValue(mode(0), "WriteDateTime"); err != nil {
   293  		return err
   294  	}
   295  
   296  	t := time.Unix(dt/1e3, dt%1e3*1e6).UTC()
   297  
   298  	if ejvw.canonical || t.Year() < 1970 || t.Year() > 9999 {
   299  		s := fmt.Sprintf(`{"$numberLong":"%d"}`, dt)
   300  		ejvw.writeExtendedSingleValue("date", s, false)
   301  	} else {
   302  		ejvw.writeExtendedSingleValue("date", t.Format(rfc3339Milli), true)
   303  	}
   304  
   305  	ejvw.buf = append(ejvw.buf, ',')
   306  
   307  	ejvw.pop()
   308  	return nil
   309  }
   310  
   311  func (ejvw *extJSONValueWriter) WriteDecimal128(d primitive.Decimal128) error {
   312  	if err := ejvw.ensureElementValue(mode(0), "WriteDecimal128"); err != nil {
   313  		return err
   314  	}
   315  
   316  	ejvw.writeExtendedSingleValue("numberDecimal", d.String(), true)
   317  	ejvw.buf = append(ejvw.buf, ',')
   318  
   319  	ejvw.pop()
   320  	return nil
   321  }
   322  
   323  func (ejvw *extJSONValueWriter) WriteDocument() (DocumentWriter, error) {
   324  	if ejvw.stack[ejvw.frame].mode == mTopLevel {
   325  		ejvw.buf = append(ejvw.buf, '{')
   326  		return ejvw, nil
   327  	}
   328  
   329  	if err := ejvw.ensureElementValue(mDocument, "WriteDocument", mTopLevel); err != nil {
   330  		return nil, err
   331  	}
   332  
   333  	ejvw.buf = append(ejvw.buf, '{')
   334  	ejvw.push(mDocument)
   335  	return ejvw, nil
   336  }
   337  
   338  func (ejvw *extJSONValueWriter) WriteDouble(f float64) error {
   339  	if err := ejvw.ensureElementValue(mode(0), "WriteDouble"); err != nil {
   340  		return err
   341  	}
   342  
   343  	s := formatDouble(f)
   344  
   345  	if ejvw.canonical {
   346  		ejvw.writeExtendedSingleValue("numberDouble", s, true)
   347  	} else {
   348  		switch s {
   349  		case "Infinity":
   350  			fallthrough
   351  		case "-Infinity":
   352  			fallthrough
   353  		case "NaN":
   354  			s = fmt.Sprintf(`{"$numberDouble":"%s"}`, s)
   355  		}
   356  		ejvw.buf = append(ejvw.buf, []byte(s)...)
   357  	}
   358  
   359  	ejvw.buf = append(ejvw.buf, ',')
   360  
   361  	ejvw.pop()
   362  	return nil
   363  }
   364  
   365  func (ejvw *extJSONValueWriter) WriteInt32(i int32) error {
   366  	if err := ejvw.ensureElementValue(mode(0), "WriteInt32"); err != nil {
   367  		return err
   368  	}
   369  
   370  	s := strconv.FormatInt(int64(i), 10)
   371  
   372  	if ejvw.canonical {
   373  		ejvw.writeExtendedSingleValue("numberInt", s, true)
   374  	} else {
   375  		ejvw.buf = append(ejvw.buf, []byte(s)...)
   376  	}
   377  
   378  	ejvw.buf = append(ejvw.buf, ',')
   379  
   380  	ejvw.pop()
   381  	return nil
   382  }
   383  
   384  func (ejvw *extJSONValueWriter) WriteInt64(i int64) error {
   385  	if err := ejvw.ensureElementValue(mode(0), "WriteInt64"); err != nil {
   386  		return err
   387  	}
   388  
   389  	s := strconv.FormatInt(i, 10)
   390  
   391  	if ejvw.canonical {
   392  		ejvw.writeExtendedSingleValue("numberLong", s, true)
   393  	} else {
   394  		ejvw.buf = append(ejvw.buf, []byte(s)...)
   395  	}
   396  
   397  	ejvw.buf = append(ejvw.buf, ',')
   398  
   399  	ejvw.pop()
   400  	return nil
   401  }
   402  
   403  func (ejvw *extJSONValueWriter) WriteJavascript(code string) error {
   404  	if err := ejvw.ensureElementValue(mode(0), "WriteJavascript"); err != nil {
   405  		return err
   406  	}
   407  
   408  	var buf bytes.Buffer
   409  	writeStringWithEscapes(code, &buf, ejvw.escapeHTML)
   410  
   411  	ejvw.writeExtendedSingleValue("code", buf.String(), false)
   412  	ejvw.buf = append(ejvw.buf, ',')
   413  
   414  	ejvw.pop()
   415  	return nil
   416  }
   417  
   418  func (ejvw *extJSONValueWriter) WriteMaxKey() error {
   419  	if err := ejvw.ensureElementValue(mode(0), "WriteMaxKey"); err != nil {
   420  		return err
   421  	}
   422  
   423  	ejvw.writeExtendedSingleValue("maxKey", "1", false)
   424  	ejvw.buf = append(ejvw.buf, ',')
   425  
   426  	ejvw.pop()
   427  	return nil
   428  }
   429  
   430  func (ejvw *extJSONValueWriter) WriteMinKey() error {
   431  	if err := ejvw.ensureElementValue(mode(0), "WriteMinKey"); err != nil {
   432  		return err
   433  	}
   434  
   435  	ejvw.writeExtendedSingleValue("minKey", "1", false)
   436  	ejvw.buf = append(ejvw.buf, ',')
   437  
   438  	ejvw.pop()
   439  	return nil
   440  }
   441  
   442  func (ejvw *extJSONValueWriter) WriteNull() error {
   443  	if err := ejvw.ensureElementValue(mode(0), "WriteNull"); err != nil {
   444  		return err
   445  	}
   446  
   447  	ejvw.buf = append(ejvw.buf, []byte("null")...)
   448  	ejvw.buf = append(ejvw.buf, ',')
   449  
   450  	ejvw.pop()
   451  	return nil
   452  }
   453  
   454  func (ejvw *extJSONValueWriter) WriteObjectID(oid primitive.ObjectID) error {
   455  	if err := ejvw.ensureElementValue(mode(0), "WriteObjectID"); err != nil {
   456  		return err
   457  	}
   458  
   459  	ejvw.writeExtendedSingleValue("oid", oid.Hex(), true)
   460  	ejvw.buf = append(ejvw.buf, ',')
   461  
   462  	ejvw.pop()
   463  	return nil
   464  }
   465  
   466  func (ejvw *extJSONValueWriter) WriteRegex(pattern string, options string) error {
   467  	if err := ejvw.ensureElementValue(mode(0), "WriteRegex"); err != nil {
   468  		return err
   469  	}
   470  
   471  	var buf bytes.Buffer
   472  	buf.WriteString(`{"$regularExpression":{"pattern":`)
   473  	writeStringWithEscapes(pattern, &buf, ejvw.escapeHTML)
   474  	buf.WriteString(`,"options":"`)
   475  	buf.WriteString(sortStringAlphebeticAscending(options))
   476  	buf.WriteString(`"}},`)
   477  
   478  	ejvw.buf = append(ejvw.buf, buf.Bytes()...)
   479  
   480  	ejvw.pop()
   481  	return nil
   482  }
   483  
   484  func (ejvw *extJSONValueWriter) WriteString(s string) error {
   485  	if err := ejvw.ensureElementValue(mode(0), "WriteString"); err != nil {
   486  		return err
   487  	}
   488  
   489  	var buf bytes.Buffer
   490  	writeStringWithEscapes(s, &buf, ejvw.escapeHTML)
   491  
   492  	ejvw.buf = append(ejvw.buf, buf.Bytes()...)
   493  	ejvw.buf = append(ejvw.buf, ',')
   494  
   495  	ejvw.pop()
   496  	return nil
   497  }
   498  
   499  func (ejvw *extJSONValueWriter) WriteSymbol(symbol string) error {
   500  	if err := ejvw.ensureElementValue(mode(0), "WriteSymbol"); err != nil {
   501  		return err
   502  	}
   503  
   504  	var buf bytes.Buffer
   505  	writeStringWithEscapes(symbol, &buf, ejvw.escapeHTML)
   506  
   507  	ejvw.writeExtendedSingleValue("symbol", buf.String(), false)
   508  	ejvw.buf = append(ejvw.buf, ',')
   509  
   510  	ejvw.pop()
   511  	return nil
   512  }
   513  
   514  func (ejvw *extJSONValueWriter) WriteTimestamp(t uint32, i uint32) error {
   515  	if err := ejvw.ensureElementValue(mode(0), "WriteTimestamp"); err != nil {
   516  		return err
   517  	}
   518  
   519  	var buf bytes.Buffer
   520  	buf.WriteString(`{"$timestamp":{"t":`)
   521  	buf.WriteString(strconv.FormatUint(uint64(t), 10))
   522  	buf.WriteString(`,"i":`)
   523  	buf.WriteString(strconv.FormatUint(uint64(i), 10))
   524  	buf.WriteString(`}},`)
   525  
   526  	ejvw.buf = append(ejvw.buf, buf.Bytes()...)
   527  
   528  	ejvw.pop()
   529  	return nil
   530  }
   531  
   532  func (ejvw *extJSONValueWriter) WriteUndefined() error {
   533  	if err := ejvw.ensureElementValue(mode(0), "WriteUndefined"); err != nil {
   534  		return err
   535  	}
   536  
   537  	ejvw.writeExtendedSingleValue("undefined", "true", false)
   538  	ejvw.buf = append(ejvw.buf, ',')
   539  
   540  	ejvw.pop()
   541  	return nil
   542  }
   543  
   544  func (ejvw *extJSONValueWriter) WriteDocumentElement(key string) (ValueWriter, error) {
   545  	switch ejvw.stack[ejvw.frame].mode {
   546  	case mDocument, mTopLevel, mCodeWithScope:
   547  		var buf bytes.Buffer
   548  		writeStringWithEscapes(key, &buf, ejvw.escapeHTML)
   549  
   550  		ejvw.buf = append(ejvw.buf, []byte(fmt.Sprintf(`%s:`, buf.String()))...)
   551  		ejvw.push(mElement)
   552  	default:
   553  		return nil, ejvw.invalidTransitionErr(mElement, "WriteDocumentElement", []mode{mDocument, mTopLevel, mCodeWithScope})
   554  	}
   555  
   556  	return ejvw, nil
   557  }
   558  
   559  func (ejvw *extJSONValueWriter) WriteDocumentEnd() error {
   560  	switch ejvw.stack[ejvw.frame].mode {
   561  	case mDocument, mTopLevel, mCodeWithScope:
   562  	default:
   563  		return fmt.Errorf("incorrect mode to end document: %s", ejvw.stack[ejvw.frame].mode)
   564  	}
   565  
   566  	// close the document
   567  	if ejvw.buf[len(ejvw.buf)-1] == ',' {
   568  		ejvw.buf[len(ejvw.buf)-1] = '}'
   569  	} else {
   570  		ejvw.buf = append(ejvw.buf, '}')
   571  	}
   572  
   573  	switch ejvw.stack[ejvw.frame].mode {
   574  	case mCodeWithScope:
   575  		ejvw.buf = append(ejvw.buf, '}')
   576  		fallthrough
   577  	case mDocument:
   578  		ejvw.buf = append(ejvw.buf, ',')
   579  	case mTopLevel:
   580  		// If the value writer has newlines enabled, end top-level documents with a newline so that
   581  		// multiple documents encoded to the same writer are separated by newlines. That matches the
   582  		// Go json.Encoder behavior and also works with bsonrw.NewExtJSONValueReader.
   583  		if ejvw.newlines {
   584  			ejvw.buf = append(ejvw.buf, '\n')
   585  		}
   586  		if ejvw.w != nil {
   587  			if _, err := ejvw.w.Write(ejvw.buf); err != nil {
   588  				return err
   589  			}
   590  			ejvw.buf = ejvw.buf[:0]
   591  		}
   592  	}
   593  
   594  	ejvw.pop()
   595  	return nil
   596  }
   597  
   598  func (ejvw *extJSONValueWriter) WriteArrayElement() (ValueWriter, error) {
   599  	switch ejvw.stack[ejvw.frame].mode {
   600  	case mArray:
   601  		ejvw.push(mValue)
   602  	default:
   603  		return nil, ejvw.invalidTransitionErr(mValue, "WriteArrayElement", []mode{mArray})
   604  	}
   605  
   606  	return ejvw, nil
   607  }
   608  
   609  func (ejvw *extJSONValueWriter) WriteArrayEnd() error {
   610  	switch ejvw.stack[ejvw.frame].mode {
   611  	case mArray:
   612  		// close the array
   613  		if ejvw.buf[len(ejvw.buf)-1] == ',' {
   614  			ejvw.buf[len(ejvw.buf)-1] = ']'
   615  		} else {
   616  			ejvw.buf = append(ejvw.buf, ']')
   617  		}
   618  
   619  		ejvw.buf = append(ejvw.buf, ',')
   620  
   621  		ejvw.pop()
   622  	default:
   623  		return fmt.Errorf("incorrect mode to end array: %s", ejvw.stack[ejvw.frame].mode)
   624  	}
   625  
   626  	return nil
   627  }
   628  
   629  func formatDouble(f float64) string {
   630  	var s string
   631  	if math.IsInf(f, 1) {
   632  		s = "Infinity"
   633  	} else if math.IsInf(f, -1) {
   634  		s = "-Infinity"
   635  	} else if math.IsNaN(f) {
   636  		s = "NaN"
   637  	} else {
   638  		// Print exactly one decimalType place for integers; otherwise, print as many are necessary to
   639  		// perfectly represent it.
   640  		s = strconv.FormatFloat(f, 'G', -1, 64)
   641  		if !strings.ContainsRune(s, 'E') && !strings.ContainsRune(s, '.') {
   642  			s += ".0"
   643  		}
   644  	}
   645  
   646  	return s
   647  }
   648  
   649  var hexChars = "0123456789abcdef"
   650  
   651  func writeStringWithEscapes(s string, buf *bytes.Buffer, escapeHTML bool) {
   652  	buf.WriteByte('"')
   653  	start := 0
   654  	for i := 0; i < len(s); {
   655  		if b := s[i]; b < utf8.RuneSelf {
   656  			if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
   657  				i++
   658  				continue
   659  			}
   660  			if start < i {
   661  				buf.WriteString(s[start:i])
   662  			}
   663  			switch b {
   664  			case '\\', '"':
   665  				buf.WriteByte('\\')
   666  				buf.WriteByte(b)
   667  			case '\n':
   668  				buf.WriteByte('\\')
   669  				buf.WriteByte('n')
   670  			case '\r':
   671  				buf.WriteByte('\\')
   672  				buf.WriteByte('r')
   673  			case '\t':
   674  				buf.WriteByte('\\')
   675  				buf.WriteByte('t')
   676  			case '\b':
   677  				buf.WriteByte('\\')
   678  				buf.WriteByte('b')
   679  			case '\f':
   680  				buf.WriteByte('\\')
   681  				buf.WriteByte('f')
   682  			default:
   683  				// This encodes bytes < 0x20 except for \t, \n and \r.
   684  				// If escapeHTML is set, it also escapes <, >, and &
   685  				// because they can lead to security holes when
   686  				// user-controlled strings are rendered into JSON
   687  				// and served to some browsers.
   688  				buf.WriteString(`\u00`)
   689  				buf.WriteByte(hexChars[b>>4])
   690  				buf.WriteByte(hexChars[b&0xF])
   691  			}
   692  			i++
   693  			start = i
   694  			continue
   695  		}
   696  		c, size := utf8.DecodeRuneInString(s[i:])
   697  		if c == utf8.RuneError && size == 1 {
   698  			if start < i {
   699  				buf.WriteString(s[start:i])
   700  			}
   701  			buf.WriteString(`\ufffd`)
   702  			i += size
   703  			start = i
   704  			continue
   705  		}
   706  		// U+2028 is LINE SEPARATOR.
   707  		// U+2029 is PARAGRAPH SEPARATOR.
   708  		// They are both technically valid characters in JSON strings,
   709  		// but don't work in JSONP, which has to be evaluated as JavaScript,
   710  		// and can lead to security holes there. It is valid JSON to
   711  		// escape them, so we do so unconditionally.
   712  		// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
   713  		if c == '\u2028' || c == '\u2029' {
   714  			if start < i {
   715  				buf.WriteString(s[start:i])
   716  			}
   717  			buf.WriteString(`\u202`)
   718  			buf.WriteByte(hexChars[c&0xF])
   719  			i += size
   720  			start = i
   721  			continue
   722  		}
   723  		i += size
   724  	}
   725  	if start < len(s) {
   726  		buf.WriteString(s[start:])
   727  	}
   728  	buf.WriteByte('"')
   729  }
   730  
   731  type sortableString []rune
   732  
   733  func (ss sortableString) Len() int {
   734  	return len(ss)
   735  }
   736  
   737  func (ss sortableString) Less(i, j int) bool {
   738  	return ss[i] < ss[j]
   739  }
   740  
   741  func (ss sortableString) Swap(i, j int) {
   742  	oldI := ss[i]
   743  	ss[i] = ss[j]
   744  	ss[j] = oldI
   745  }
   746  
   747  func sortStringAlphebeticAscending(s string) string {
   748  	ss := sortableString([]rune(s))
   749  	sort.Sort(ss)
   750  	return string([]rune(ss))
   751  }