You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

extjson_writer.go 17KB

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