@@ -7,12 +7,26 @@ import {
77 storeUnsafe
88} from "./internal/arraybuffer" ;
99
10+ import {
11+ allocateUnsafe as allocateUnsafeString ,
12+ freeUnsafe as freeUnsafeString ,
13+ copyUnsafe as copyUnsafeString
14+ } from "./internal/string" ;
15+
1016import {
1117 defaultComparator ,
1218 insertionSort ,
1319 weakHeapSort
1420} from "./internal/array" ;
1521
22+ import {
23+ itoa ,
24+ dtoa ,
25+ itoa_stream ,
26+ dtoa_stream ,
27+ MAX_DOUBLE_LENGTH
28+ } from "./internal/number" ;
29+
1630export class Array < T > {
1731
1832 /* @internal */ buffer_ : ArrayBuffer ;
@@ -118,16 +132,9 @@ export class Array<T> {
118132 return this ;
119133 }
120134
135+ @inline
121136 includes ( searchElement : T , fromIndex : i32 = 0 ) : bool {
122- var length = this . length_ ;
123- if ( length == 0 || fromIndex >= length ) return false ;
124- if ( fromIndex < 0 ) fromIndex = max ( length + fromIndex , 0 ) ;
125- var buffer = this . buffer_ ;
126- while ( fromIndex < length ) {
127- if ( loadUnsafe < T , T > ( buffer , fromIndex ) == searchElement ) return true ;
128- ++ fromIndex ;
129- }
130- return false ;
137+ return this . indexOf ( searchElement , fromIndex ) >= 0 ;
131138 }
132139
133140 indexOf ( searchElement : T , fromIndex : i32 = 0 ) : i32 {
@@ -356,6 +363,169 @@ export class Array<T> {
356363 }
357364 }
358365
366+ join ( separator : string = "," ) : string {
367+ var lastIndex = this . length_ - 1 ;
368+ if ( lastIndex < 0 ) return "" ;
369+ var result = "" ;
370+ var value : T ;
371+ var buffer = this . buffer_ ;
372+ var sepLen = separator . length ;
373+ var hasSeparator = sepLen != 0 ;
374+ if ( value instanceof bool ) {
375+ if ( ! lastIndex ) {
376+ return select < string > ( "true" , "false" , loadUnsafe < T , bool > ( buffer , 0 ) ) ;
377+ }
378+ let valueLen = 5 ; // max possible length of element len("false")
379+ let estLen = ( valueLen + sepLen ) * lastIndex + valueLen ;
380+ let result = allocateUnsafeString ( estLen ) ;
381+ let offset = 0 ;
382+ for ( let i = 0 ; i < lastIndex ; ++ i ) {
383+ value = loadUnsafe < T , bool > ( buffer , i ) ;
384+ valueLen = 4 + < i32 > ( ! value ) ;
385+ copyUnsafeString ( result , offset , select < string > ( "true" , "false" , value ) , 0 , valueLen ) ;
386+ offset += valueLen ;
387+ if ( hasSeparator ) {
388+ copyUnsafeString ( result , offset , changetype < String > ( separator ) , 0 , sepLen ) ;
389+ offset += sepLen ;
390+ }
391+ }
392+ value = loadUnsafe < T , bool > ( buffer , lastIndex ) ;
393+ valueLen = 4 + < i32 > ( ! value ) ;
394+ copyUnsafeString ( result , offset , select < string > ( "true" , "false" , value ) , 0 , valueLen ) ;
395+ offset += valueLen ;
396+
397+ let out = result ;
398+ if ( estLen > offset ) {
399+ out = result . substring ( 0 , offset ) ;
400+ freeUnsafeString ( result ) ;
401+ }
402+ return out ;
403+ } else if ( isInteger < T > ( ) ) {
404+ if ( ! lastIndex ) {
405+ return changetype < string > ( itoa < T > ( loadUnsafe < T , T > ( buffer , 0 ) ) ) ;
406+ }
407+ const valueLen = ( sizeof < T > ( ) <= 4 ? 10 : 20 ) + < i32 > isSigned < T > ( ) ;
408+ let estLen = ( valueLen + sepLen ) * lastIndex + valueLen ;
409+ let result = allocateUnsafeString ( estLen ) ;
410+ let offset = 0 ;
411+ for ( let i = 0 ; i < lastIndex ; ++ i ) {
412+ value = loadUnsafe < T , T > ( buffer , i ) ;
413+ offset += itoa_stream < T > ( changetype < usize > ( result ) , offset , value ) ;
414+ if ( hasSeparator ) {
415+ copyUnsafeString ( result , offset , separator , 0 , sepLen ) ;
416+ offset += sepLen ;
417+ }
418+ }
419+ value = loadUnsafe < T , T > ( buffer , lastIndex ) ;
420+ offset += itoa_stream < T > ( changetype < usize > ( result ) , offset , value ) ;
421+ let out = result ;
422+ if ( estLen > offset ) {
423+ out = result . substring ( 0 , offset ) ;
424+ freeUnsafeString ( result ) ;
425+ }
426+ return out ;
427+ } else if ( isFloat < T > ( ) ) {
428+ if ( ! lastIndex ) {
429+ return changetype < string > ( dtoa ( loadUnsafe < T , f64 > ( buffer , 0 ) ) ) ;
430+ }
431+ const valueLen = MAX_DOUBLE_LENGTH ;
432+ let estLen = ( valueLen + sepLen ) * lastIndex + valueLen ;
433+ let result = allocateUnsafeString ( estLen ) ;
434+ let offset = 0 ;
435+ for ( let i = 0 ; i < lastIndex ; ++ i ) {
436+ value = loadUnsafe < T , f64 > ( buffer , i ) ;
437+ offset += dtoa_stream ( changetype < usize > ( result ) , offset , value ) ;
438+ if ( hasSeparator ) {
439+ copyUnsafeString ( result , offset , separator , 0 , sepLen ) ;
440+ offset += sepLen ;
441+ }
442+ }
443+ value = loadUnsafe < T , f64 > ( buffer , lastIndex ) ;
444+ offset += dtoa_stream ( changetype < usize > ( result ) , offset , value ) ;
445+ let out = result ;
446+ if ( estLen > offset ) {
447+ out = result . substring ( 0 , offset ) ;
448+ freeUnsafeString ( result ) ;
449+ }
450+ return out ;
451+ } else if ( isString < T > ( ) ) {
452+ if ( ! lastIndex ) {
453+ return loadUnsafe < T , string > ( buffer , 0 ) ;
454+ }
455+ let estLen = 0 ;
456+ for ( let i = 0 , len = lastIndex + 1 ; i < len ; ++ i ) {
457+ estLen += loadUnsafe < T , string > ( buffer , i ) . length ;
458+ }
459+ let offset = 0 ;
460+ let result = allocateUnsafeString ( estLen + sepLen * lastIndex ) ;
461+ for ( let i = 0 ; i < lastIndex ; ++ i ) {
462+ value = loadUnsafe < T , String > ( buffer , i ) ;
463+ if ( value ) {
464+ let valueLen = value . length ; // tslint:disable-line:no-unsafe-any
465+ copyUnsafeString ( result , offset , value , 0 , valueLen ) ; // tslint:disable-line:no-unsafe-any
466+ offset += valueLen ; // tslint:disable-line:no-unsafe-any
467+ }
468+ if ( hasSeparator ) {
469+ copyUnsafeString ( result , offset , separator , 0 , sepLen ) ;
470+ offset += sepLen ;
471+ }
472+ }
473+ value = loadUnsafe < T , String > ( buffer , lastIndex ) ;
474+ if ( value ) {
475+ let valueLen = value . length ; // tslint:disable-line:no-unsafe-any
476+ copyUnsafeString ( result , offset , value , 0 , valueLen ) ; // tslint:disable-line:no-unsafe-any
477+ }
478+ return result ;
479+ } else if ( isArray < T > ( ) ) {
480+ if ( ! lastIndex ) {
481+ value = loadUnsafe < T , T > ( buffer , 0 ) ;
482+ return value ? value . join ( separator ) : "" ; // tslint:disable-line:no-unsafe-any
483+ }
484+ for ( let i = 0 ; i < lastIndex ; ++ i ) {
485+ value = loadUnsafe < T , T > ( buffer , i ) ;
486+ if ( value ) result += value . join ( separator ) ; // tslint:disable-line:no-unsafe-any
487+ if ( hasSeparator ) result += separator ;
488+ }
489+ value = loadUnsafe < T , T > ( buffer , lastIndex ) ;
490+ if ( value ) result += value . join ( separator ) ; // tslint:disable-line:no-unsafe-any
491+ return result ;
492+ } else if ( isReference < T > ( ) ) { // References
493+ if ( ! lastIndex ) return "[object Object]" ;
494+ const valueLen = 15 ; // max possible length of element len("[object Object]")
495+ let estLen = ( valueLen + sepLen ) * lastIndex + valueLen ;
496+ let result = allocateUnsafeString ( estLen ) ;
497+ let offset = 0 ;
498+ for ( let i = 0 ; i < lastIndex ; ++ i ) {
499+ value = loadUnsafe < T , T > ( buffer , i ) ;
500+ if ( value ) {
501+ copyUnsafeString ( result , offset , changetype < String > ( "[object Object]" ) , 0 , valueLen ) ;
502+ offset += valueLen ;
503+ }
504+ if ( hasSeparator ) {
505+ copyUnsafeString ( result , offset , changetype < String > ( separator ) , 0 , sepLen ) ;
506+ offset += sepLen ;
507+ }
508+ }
509+ if ( loadUnsafe < T , T > ( buffer , lastIndex ) ) {
510+ copyUnsafeString ( result , offset , changetype < String > ( "[object Object]" ) , 0 , valueLen ) ;
511+ offset += valueLen ;
512+ }
513+ let out = result ;
514+ if ( estLen > offset ) {
515+ out = result . substring ( 0 , offset ) ;
516+ freeUnsafeString ( result ) ;
517+ }
518+ return out ;
519+ } else {
520+ assert ( false ) ; // Unsupported generic typename
521+ }
522+ }
523+
524+ @inline
525+ toString ( ) : string {
526+ return this . join ( ) ;
527+ }
528+
359529 private __gc ( ) : void {
360530 var buffer = this . buffer_ ;
361531 __gc_mark ( changetype < usize > ( buffer ) ) ; // tslint:disable-line
0 commit comments