extjson_writer.go raw

   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  }
 752