import { createIndexArray , ILookUpArray } from '../internal' ; import { FIRST_IS_MISSING , FIRST_IS_NAN , ECompareValueType , ICompareValue , Column , UIntTypedArray , Ranking , IDataRow , } from '../model' ; const missingUInt8 = FIRST_IS_MISSING > 0 ? 255 : 0 ; const missingBinary = missingUInt8 ; const missingUInt16 = FIRST_IS_MISSING > 0 ? 65535 : 0 ; const missingUInt32 = FIRST_IS_MISSING > 0 ? 4294967295 : 0 ; const missingInt8 = FIRST_IS_MISSING > 0 ? 127 : - 128 ; const missingInt16 = FIRST_IS_MISSING > 0 ? 32767 : - 32768 ; const missingInt32 = FIRST_IS_MISSING > 0 ? 2147483647 : - 2147483648 ; const missingFloat = FIRST_IS_NAN > 0 ? Number . POSITIVE_INFINITY : Number . NEGATIVE_INFINITY ; const missingFloatAsc = FIRST_IS_MISSING > 0 ? Number . POSITIVE_INFINITY : Number . NEGATIVE_INFINITY ; const missingString = FIRST_IS_MISSING > 0 ? '\uffff' : '\u0000' ; function chooseMissingByLength ( length ) { if ( length <= 255 ) { return missingBinary ; } if ( length <= 65535 ) { return missingUInt16 ; } return missingUInt32 ; } function toCompareLookUp ( rawLength , type ) { switch ( type ) { case ECompareValueType . COUNT : return createIndexArray ( rawLength + 1 ) ; case ECompareValueType . BINARY : case ECompareValueType . UINT8 : return new Uint8Array ( rawLength ) ; case ECompareValueType . UINT16 : return new Uint16Array ( rawLength ) ; case ECompareValueType . UINT32 : return new Uint32Array ( rawLength ) ; case ECompareValueType . INT8 : return new Int8Array ( rawLength ) ; case ECompareValueType . INT16 : return new Int16Array ( rawLength ) ; case ECompareValueType . INT32 : return new Int32Array ( rawLength ) ; case ECompareValueType . STRING : return [ ] as string [ ] ; case ECompareValueType . FLOAT_ASC : case ECompareValueType . FLOAT : return new Float32Array ( rawLength ) ; case ECompareValueType . DOUBLE_ASC : case ECompareValueType . DOUBLE : return new Float64Array ( rawLength ) ; } } function createSetter ( type , lookup , missingCount ) { switch ( type ) { case ECompareValueType . BINARY : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingBinary : ( v as number ) + 1 ) ; case ECompareValueType . COUNT : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingCount : ( v as number ) + 1 ) ; case ECompareValueType . UINT8 : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingInt8 : ( v as number ) + 1 ) ; case ECompareValueType . UINT16 : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingInt16 : ( v as number ) + 1 ) ; case ECompareValueType . UINT32 : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingInt32 : ( v as number ) + 1 ) ; case ECompareValueType . INT8 : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingInt8 : ( v as number ) ) ; case ECompareValueType . INT16 : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingInt16 : ( v as number ) ) ; case ECompareValueType . INT32 : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingInt32 : ( v as number ) ) ; case ECompareValueType . STRING : return ( index , v ) => ( lookup [ index ] = v == null || v === '' ? missingString : v ) ; case ECompareValueType . FLOAT : case ECompareValueType . DOUBLE : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingFloat : v ) ; case ECompareValueType . FLOAT_ASC : case ECompareValueType . DOUBLE_ASC : return ( index , v ) => ( lookup [ index ] = v == null || Number . isNaN ( v as number ) ? missingFloatAsc : v ) ; } } export class CompareLookup { private readonly criteria : { col : Column ; valueCache ? ( dataIndex ) : any ; } [ ] = [ ] ; private readonly data : { asc : boolean ; v : ECompareValueType ; lookup : ILookUpArray ; setter : ( dataIndex : number , value : ICompareValue ) => void ; } [ ] = [ ] ; constructor ( rawLength , isSorting , ranking , valueCaches ? ) { const missingCount = chooseMissingByLength ( rawLength + 1 ) ; for ( const c of isSorting ? ranking . getSortCriteria ( ) : ranking . getGroupSortCriteria ( ) ) { const v = isSorting ? c . col . toCompareValueType ( ) : c . col . toCompareGroupValueType ( ) ; const valueCache = valueCaches ? valueCaches ( c . col ) : undefined ; this . criteria . push ( { col : c . col , valueCache } ) ; if ( ! Array . isArray ( v ) ) { const lookup = toCompareLookUp ( rawLength , v ) ; this . data . push ( { asc : c . asc , v , lookup , setter : createSetter ( v , lookup , missingCount ) } ) ; continue ; } for ( const vi of v ) { const lookup = toCompareLookUp ( rawLength , vi ) ; this . data . push ( { asc : c . asc , v : vi , lookup , setter : createSetter ( vi , lookup , missingCount ) } ) ; } } if ( isSorting ) { return ; } { const v = ECompareValueType . STRING ; const lookup = toCompareLookUp ( rawLength , v ) ; this . data . push ( { asc : true , v , lookup , setter : createSetter ( v , lookup , missingCount ) } ) ; } } get sortOrders ( ) { return this . data . map ( ( d ) => ( { asc : d . asc , lookup : d . lookup } ) ) ; } get transferAbles ( ) { return this . data . map ( ( d ) => d . lookup ) . filter ( ( d ) : d is UIntTypedArray | Float32Array => ! Array . isArray ( d ) ) . map ( ( d ) => d . buffer ) ; } push ( row ) { let i = 0 ; for ( const c of this . criteria ) { const r = c . col . toCompareValue ( row , c . valueCache ? c . valueCache ( row . i ) : undefined ) ; if ( ! Array . isArray ( r ) ) { this . data [ i ++ ] . setter ( row . i , r ) ; continue ; } for ( const ri of r ) { this . data [ i ++ ] . setter ( row . i , ri ) ; } } } pushValues ( dataIndex , vs ) { for ( let i = 0 ; i < vs . length ; ++ i ) { this . data [ i ] . setter ( dataIndex , vs [ i ] ) ; } } free ( ) { this . data . splice ( 0 , this . data . length ) ; } }