diff --git a/src/reader/cif/binary/field.ts b/src/reader/cif/binary/field.ts index d5d5ff891e0b6a90b9e06be82e6eeb90764eba3a..2c8821e685a49c205f23fbe7cd4f7be86b3040e1 100644 --- a/src/reader/cif/binary/field.ts +++ b/src/reader/cif/binary/field.ts @@ -8,13 +8,12 @@ import * as Column from '../../common/column' import * as Data from '../data-model' import { EncodedColumn } from './encoding' import decode from './decoder' -import { isTypedArray, typedArrayWindow } from '../../common/binary/column' import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../common/text/number-parser' export default function Field(column: EncodedColumn): Data.Field { const mask = column.mask ? decode(column.mask) as number[] : void 0; const data = decode(column.data); - const isNumeric = isTypedArray(data); + const isNumeric = Column.isTypedArray(data); const str: Data.Field['str'] = isNumeric ? mask @@ -49,10 +48,10 @@ export default function Field(column: EncodedColumn): Data.Field { stringEquals: (row, v) => str(row) === v, toStringArray: params => Column.createAndFillArray(rowCount, str, params), toIntArray: isNumeric - ? params => typedArrayWindow(data, params) + ? params => Column.typedArrayWindow(data, params) : params => Column.createAndFillArray(rowCount, int, params), toFloatArray: isNumeric - ? params => typedArrayWindow(data, params) + ? params => Column.typedArrayWindow(data, params) : params => Column.createAndFillArray(rowCount, float, params) }; } \ No newline at end of file diff --git a/src/reader/common/binary/column.ts b/src/reader/common/binary/column.ts index 39d80d76b4c5217f2e71ece71592af65b03532b8..28ce9a00172e698d50f8e908a3908248acf2ccb9 100644 --- a/src/reader/common/binary/column.ts +++ b/src/reader/common/binary/column.ts @@ -2,17 +2,4 @@ * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> - */ - -import { getArrayBounds, ToArrayParams } from '../column' - -export function isTypedArray(data: any) { - return data.buffer && typeof data.byteLength === 'number' && data.BYTES_PER_ELEMENT; -} - -export function typedArrayWindow(data: any, params?: ToArrayParams): ReadonlyArray<number> { - const { constructor, buffer, length, byteOffset, BYTES_PER_ELEMENT } = data; - const { start, end } = getArrayBounds(length, params); - if (start === 0 && end === length) return data; - return new constructor(buffer, byteOffset + BYTES_PER_ELEMENT * start, Math.min(length, end - start)); -} \ No newline at end of file + */ \ No newline at end of file diff --git a/src/reader/common/column.ts b/src/reader/common/column.ts index fc8ca58d1f8f46068cd1e244969c4021e5492028..13dc3f2bafb0ea0ce3576ab829cec9bb2cf257a2 100644 --- a/src/reader/common/column.ts +++ b/src/reader/common/column.ts @@ -37,14 +37,42 @@ export function UndefinedColumn<T extends ColumnType>(rowCount: number, type: T) isDefined: false, rowCount, value, - isValueDefined(row) { return false; }, - toArray(params) { + isValueDefined: row => false, + toArray: params => { const { array } = createArray(rowCount, params); for (let i = 0, _i = array.length; i < _i; i++) array[i] = value(0) return array; }, - stringEquals(row, value) { return !value; }, - areValuesEqual(rowA, rowB) { return true; } + stringEquals: (row, value) => !value, + areValuesEqual: (rowA, rowB) => true + } +} + +export function ArrayColumn<T>(array: ArrayLike<T>): Column<T> { + const rowCount = array.length; + const value: Column<T>['value'] = row => array[row]; + const isTyped = isTypedArray(array); + return { + isDefined: false, + rowCount, + value, + isValueDefined: row => true, + toArray: isTyped + ? params => typedArrayWindow(array, params) as any as ReadonlyArray<T> + : params => { + const { start, end } = getArrayBounds(rowCount, params); + const ret = new Array(end - start); + for (let i = 0, _i = end - start; i < _i; i++) ret[i] = array[start + i]; + return ret; + }, + stringEquals: isTyped + ? (row, value) => (array as any)[row] === +value + : (row, value) => { + const v = array[row]; + if (typeof v !== 'string') return '' + v === value; + return v === value; + }, + areValuesEqual: (rowA, rowB) => array[rowA] === array[rowB] } } @@ -74,4 +102,13 @@ export function createAndFillArray(rowCount: number, value: (row: number) => any return fillArrayValues(value, array, start); } +export function isTypedArray(data: any) { + return data.buffer && typeof data.byteLength === 'number' && data.BYTES_PER_ELEMENT; +} +export function typedArrayWindow(data: any, params?: ToArrayParams): ReadonlyArray<number> { + const { constructor, buffer, length, byteOffset, BYTES_PER_ELEMENT } = data; + const { start, end } = getArrayBounds(length, params); + if (start === 0 && end === length) return data; + return new constructor(buffer, byteOffset + BYTES_PER_ELEMENT * start, Math.min(length, end - start)); +} \ No newline at end of file diff --git a/src/reader/spec/column.spec.ts b/src/reader/spec/column.spec.ts index 6e885afd2ee3d6c405725dafc7f822b3eba35350..1bd08dfdb5f7e537ef173b34c5d982310b2e3265 100644 --- a/src/reader/spec/column.spec.ts +++ b/src/reader/spec/column.spec.ts @@ -5,10 +5,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as BinaryColumn from '../common/binary/column' import FixedColumn from '../common/text/column/fixed' import TokenColumn from '../common/text/column/token' -import { ColumnType } from '../common/column' +import { ColumnType, typedArrayWindow } from '../common/column' const lines = [ '1.123 abc', @@ -65,8 +64,8 @@ describe('token text column', () => { describe('binary column', () => { it('window works', () => { const xs = new Float64Array([1, 2, 3, 4]); - const w1 = BinaryColumn.typedArrayWindow(xs, { start: 1 }); - const w2 = BinaryColumn.typedArrayWindow(xs, { start: 2, end: 4 }); + const w1 = typedArrayWindow(xs, { start: 1 }); + const w2 = typedArrayWindow(xs, { start: 2, end: 4 }); expect(w1.length).toBe(3); for (let i = 0; i < w1.length; i++) expect(w1[i]).toBe(xs[i + 1]);