@@ -24,15 +24,22 @@ internal struct JSONWriter: ~Copyable, ~Escapable {
2424
2525 private var indent = 0
2626 private let pretty : Bool
27- private let withoutEscapingSlashes : Bool
27+ private let escapeTable : StaticString
28+ private let escapeLengths : [ UInt8 ]
2829
2930 var data : GrowableEncodingBytes
3031
3132 @_lifetime ( immortal)
3233 internal init ( pretty: Bool , withoutEscapingSlashes: Bool ) {
3334 self . data = . init( )
3435 self . pretty = pretty
35- self . withoutEscapingSlashes = withoutEscapingSlashes
36+ if withoutEscapingSlashes {
37+ self . escapeTable = Self . escapeTable
38+ self . escapeLengths = Self . escapeLens
39+ } else {
40+ self . escapeTable = Self . escapeTableWithEscapedForwardSlash
41+ self . escapeLengths = Self . escapeLensWithEscapedForwardSlash
42+ }
3643 }
3744
3845 @inline ( __always)
@@ -235,14 +242,14 @@ internal struct JSONWriter: ~Copyable, ~Escapable {
235242 @inline ( __always)
236243 func escapeLength( for byte: UInt8 ) -> Int {
237244 let byteInt = Int ( byte)
238- let escapeLen = Self . escapeLensWithEscapedForwardSlash [ byteInt]
245+ let escapeLen = self . escapeLengths [ byteInt]
239246 return Int ( escapeLen)
240247 }
241248
242249 @inline ( __always)
243250 @_lifetime ( self : copy self )
244251 mutating func writeEscape( byte: UInt8 , length: Int ) {
245- var ptr = Self . escapeTableWithEscapedForwardSlash . utf8Start
252+ var ptr = self . escapeTable . utf8Start
246253 ptr += 8 * Int( byte)
247254 self . write ( pointer: ptr, count: length)
248255 }
@@ -253,13 +260,6 @@ internal struct JSONWriter: ~Copyable, ~Escapable {
253260 return
254261 }
255262
256- @inline ( __always)
257- func appendAccumulatedBytes( from mark: UnsafePointer < UInt8 > , to cursor: UnsafePointer < UInt8 > ) {
258- if cursor > mark {
259- write ( pointer: mark, count: cursor- mark)
260- }
261- }
262-
263263 @inline ( __always)
264264 func appendAccumulatedBytes( in span: Span < UInt8 > , from mark: Int , to cursor: Int ) {
265265 if cursor > mark {
@@ -275,7 +275,7 @@ internal struct JSONWriter: ~Copyable, ~Escapable {
275275 var shift = 0
276276 while shift < T . bitWidth {
277277 result |= 0x01 << shift
278- shift += UInt8 . bitWidth
278+ shift & += UInt8 . bitWidth
279279 }
280280 return result
281281 }
@@ -320,70 +320,36 @@ internal struct JSONWriter: ~Copyable, ~Escapable {
320320 return result != 0
321321 }
322322
323- @inline ( __always)
324- func writeNonEscapingCharacters_SIMD( cursor: inout UnsafePointer < UInt8 > , end: UnsafePointer < UInt8 > ) {
325- let start = cursor
326- if ( end - cursor) > MemoryLayout < SIMD16 < UInt8 > > . size * 2 { // Only do SIMD if we have at least two vectors worth.
327- let spaces = SIMD16 < UInt8 > ( repeating: . _space)
328- let quotes = SIMD16 < UInt8 > ( repeating: . _quote)
329- let slash = SIMD16 < UInt8 > ( repeating: . _slash)
330- let backslash = SIMD16 < UInt8 > ( repeating: . _backslash)
331-
332- let packedDistance = MemoryLayout< SIMD16< UInt8>>. size
333- while ( end - cursor) > packedDistance {
334- let input = UnsafeRawPointer ( cursor) . loadUnaligned ( as: SIMD16< UInt8> . self )
335- let hasControlChars = input .< spaces
336- let hasQuotes = input .== quotes
337- let hasSlashes = input .== slash
338- let hasBackslashes = input .== backslash
339- let result = hasControlChars .| hasQuotes .| hasSlashes .| hasBackslashes
340- if any ( result) == false {
341- cursor += packedDistance
342- continue
343- } else {
344- let bitcast = unsafeBitCast ( result, to: UInt128 . self)
345- let zeroBytes = bitcast. trailingZeroBitCount / 8
346- cursor += zeroBytes
347- break
348- }
349- }
350- }
351- let len = cursor - start
352- if len > 0 {
353- self . write ( pointer: start, count: len)
354- }
355- }
356-
357323 @inline ( __always)
358324 func writeNonEscapingCharacters_SIMD( in span: Span < UInt8 > , from cursor: inout Int ) {
359325 let start = cursor
360326 let end = span. count
361- if ( end - cursor) > MemoryLayout < SIMD16 < UInt8 > > . size * 2 { // Only do SIMD if we have at least two vectors worth.
327+ if ( end & - cursor) > MemoryLayout < SIMD16 < UInt8 > > . size * 2 { // Only do SIMD if we have at least two vectors worth.
362328 let spaces = SIMD16 < UInt8 > ( repeating: . _space)
363329 let quotes = SIMD16 < UInt8 > ( repeating: . _quote)
364330 let slash = SIMD16 < UInt8 > ( repeating: . _slash)
365331 let backslash = SIMD16 < UInt8 > ( repeating: . _backslash)
366332
367333 let packedDistance = MemoryLayout< SIMD16< UInt8>>. size
368- while ( end - cursor) > packedDistance {
334+ while ( end & - cursor) > packedDistance {
369335 let input = span. bytes. unsafeLoadUnaligned ( fromUncheckedByteOffset: cursor, as: SIMD16< UInt8> . self )
370336 let hasControlChars = input .< spaces
371337 let hasQuotes = input .== quotes
372338 let hasSlashes = input .== slash
373339 let hasBackslashes = input .== backslash
374340 let result = hasControlChars .| hasQuotes .| hasSlashes .| hasBackslashes
375341 if any ( result) == false {
376- cursor += packedDistance
342+ cursor & += packedDistance
377343 continue
378344 } else {
379345 let bitcast = unsafeBitCast ( result, to: UInt128 . self)
380346 let zeroBytes = bitcast. trailingZeroBitCount / 8
381- cursor += zeroBytes
347+ cursor & += zeroBytes
382348 break
383349 }
384350 }
385351 }
386- let len = cursor - start
352+ let len = cursor & - start
387353 if len > 0 {
388354 appendAccumulatedBytes ( in: span, from: start, to: cursor)
389355 }
@@ -393,54 +359,39 @@ internal struct JSONWriter: ~Copyable, ~Escapable {
393359 func skipNonEscapingCharacters_SWAR( in span: Span < UInt8 > , at cursor: inout Int ) -> Bool {
394360 do {
395361 let packedDistance = MemoryLayout< UInt64> . size
396- if ( span. count - cursor) >= packedDistance {
362+ if ( span. count & - cursor) >= packedDistance {
397363 let integer = span. bytes. unsafeLoadUnaligned ( fromUncheckedByteOffset: cursor, as: UInt64 . self)
398364 let bytesBeforeEscape = bytesBeforeEscape ( input: integer)
399- cursor += bytesBeforeEscape
365+ cursor & += bytesBeforeEscape
400366 return bytesBeforeEscape == MemoryLayout< UInt64> . size
401367 }
402368 }
403369
404370 do {
405371 let packedDistance = MemoryLayout< UInt32> . size
406- if ( span. count - cursor) >= packedDistance {
372+ if ( span. count & - cursor) >= packedDistance {
407373 let integer = span. bytes. unsafeLoadUnaligned ( fromUncheckedByteOffset: cursor, as: UInt32 . self)
408374 let bytesBeforeEscape = bytesBeforeEscape ( input: integer)
409- cursor += bytesBeforeEscape
375+ cursor & += bytesBeforeEscape
410376 return bytesBeforeEscape == MemoryLayout< UInt32> . size
411377 }
412378 }
413379
414380 return false
415381 }
416-
417- @inline ( __always)
418- func processByte( at cursor: inout UnsafePointer < UInt8 > , mark: inout UnsafePointer < UInt8 > ) {
419- let byte = cursor. pointee
420- let escapeLen = escapeLength ( for: byte)
421- if escapeLen > 0 {
422- appendAccumulatedBytes ( from: cursor, to: mark)
423- writeEscape ( byte: byte, length: escapeLen)
424- cursor += 1
425- mark = cursor
426- } else {
427- // Accumulate byte
428- cursor += 1
429- }
430- }
431-
382+
432383 @inline ( __always)
433384 func processByte( in span: Span < UInt8 > , at cursor: inout Int , mark: inout Int ) {
434385 let byte = span [ unchecked: cursor]
435386 let escapeLen = escapeLength ( for: byte)
436387 if escapeLen > 0 {
437388 appendAccumulatedBytes ( in: span, from: mark, to: cursor)
438389 writeEscape ( byte: byte, length: escapeLen)
439- cursor += 1
390+ cursor & += 1
440391 mark = cursor
441392 } else {
442393 // Accumulate byte
443- cursor += 1
394+ cursor & += 1
444395 }
445396 }
446397
0 commit comments