From b09a0c6959d37cd551a8db0550b78d955ac09051 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Tue, 12 Mar 2019 15:56:20 -0700 Subject: [PATCH] use fast number parsers --- .../reader/ply/parse_data/ply_parser.ts | 71 +++++++------------ 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/src/mol-io/reader/ply/parse_data/ply_parser.ts b/src/mol-io/reader/ply/parse_data/ply_parser.ts index a9844ee5d..1a88b09be 100644 --- a/src/mol-io/reader/ply/parse_data/ply_parser.ts +++ b/src/mol-io/reader/ply/parse_data/ply_parser.ts @@ -1,14 +1,15 @@ /** - * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * + * @author Schäfer, Marco <marco.schaefer@uni-tuebingen.de> * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { Tokens, TokenBuilder, Tokenizer } from '../../common/text/tokenizer' import * as Data from './data-model' - import{ ReaderResult } from '../../result' import {Task, RuntimeContext, chunkedSubtask } from 'mol-task' +import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../common/text/number-parser' const enum PlyTokenType { Value = 0, @@ -18,7 +19,6 @@ const enum PlyTokenType { element = 4 } - interface State { data: string; tokenizer: Tokenizer, @@ -54,7 +54,6 @@ interface State { } function State(data: string, runtimeCtx: RuntimeContext, opts: PlyOptions): State { - const tokenizer = Tokenizer(data) return { data, @@ -134,7 +133,6 @@ function eatLine (state: Tokenizer) { } - function skipLine(state: Tokenizer) { while (state.position < state.length) { const c = state.data.charCodeAt(state.position); @@ -143,14 +141,13 @@ function skipLine(state: Tokenizer) { } } -function getColumns(state: State, NumberofColumns: number){ +function getColumns(state: State, numberOfColumns: number) { eatLine(state.tokenizer); - let tmp = (Tokenizer.getTokenString(state.tokenizer)) - let split = tmp.split(" ", NumberofColumns); + let tmp = Tokenizer.getTokenString(state.tokenizer) + let split = tmp.split(' ', numberOfColumns); return split; } - /** * Move to the next token. * Returns true when the current char is a newline, i.e. indicating a full record. @@ -172,8 +169,8 @@ function moveNextInternal(state: State) { skipLine(tokenizer); break; case state.propertyCharCode: // checks all line beginning with 'p' - state.check = getColumns(state,3); - if(state.check[0] !== 'ply' && state.faceCount === 0){ + state.check = getColumns(state, 3); + if (state.check[0] !== 'ply' && state.faceCount === 0) { state.propertyNames.push(state.check[1]); state.propertyNames.push(state.check[2]); state.propertyCount++; @@ -181,38 +178,38 @@ function moveNextInternal(state: State) { return; case state.elementCharCode: // checks all line beginning with 'e' state.check = getColumns(state, 3); - if(state.check[1] === 'vertex') state.vertexCount= Number(state.check[2]); - if(state.check[1] === 'face') state.faceCount = Number(state.check[2]); - if(state.check[0] === 'end_header') state.endHeader = 1; + if (state.check[1] === 'vertex') state.vertexCount= Number(state.check[2]); + if (state.check[1] === 'face') state.faceCount = Number(state.check[2]); + if (state.check[0] === 'end_header') state.endHeader = 1; return; default: // for all the other lines state.tokenType = PlyTokenType.Value; let return_value = eatValue(tokenizer); - if(state.endHeader === 1) - { - if(state.currentVertex < state.vertexCount){ + if (state.endHeader === 1) { + if (state.currentVertex < state.vertexCount) { + // TODO the numbers are parsed twice state.properties[state.currentVertex * state.propertyCount + state.currentProperty] = Number(Tokenizer.getTokenString(state.tokenizer)); - if(state.currentProperty < 3){ - state.vertices[state.currentVertex * 3 + state.currentProperty] = Number(Tokenizer.getTokenString(state.tokenizer)); + if (state.currentProperty < 3) { + state.vertices[state.currentVertex * 3 + state.currentProperty] = fastParseFloat(state.tokenizer.data, state.tokenizer.tokenStart, state.tokenizer.tokenEnd); } - if(state.currentProperty >= 3 && state.currentProperty <6){ - state.colors[state.currentVertex * 3 + state.currentProperty-3] = Number(Tokenizer.getTokenString(state.tokenizer)); + if (state.currentProperty >= 3 && state.currentProperty < 6) { + state.colors[state.currentVertex * 3 + state.currentProperty - 3] = fastParseInt(state.tokenizer.data, state.tokenizer.tokenStart, state.tokenizer.tokenEnd); } - if(state.currentProperty >= 6 && state.currentProperty <9){ - state.normals[state.currentVertex * 3 + state.currentProperty-6] = Number(Tokenizer.getTokenString(state.tokenizer)); + if (state.currentProperty >= 6 && state.currentProperty < 9) { + state.normals[state.currentVertex * 3 + state.currentProperty - 6] = fastParseFloat(state.tokenizer.data, state.tokenizer.tokenStart, state.tokenizer.tokenEnd); } state.currentProperty++; - if(state.currentProperty === state.propertyCount){ + if (state.currentProperty === state.propertyCount) { state.currentProperty = 0; state.currentVertex++; } return return_value; } - if(state.currentFace < state.faceCount && state.currentVertex === state.vertexCount){ - state.faces[state.currentFace * 4 + state.currentFaceElement] = Number(Tokenizer.getTokenString(state.tokenizer)); + if (state.currentFace < state.faceCount && state.currentVertex === state.vertexCount) { + state.faces[state.currentFace * 4 + state.currentFaceElement] = fastParseInt(state.tokenizer.data, state.tokenizer.tokenStart, state.tokenizer.tokenEnd); state.currentFaceElement++; - if(state.currentProperty === 4){ + if (state.currentProperty === 4) { state.currentFaceElement = 0; state.currentFace++; } @@ -234,8 +231,6 @@ function moveNext(state: State) { return newRecord } - - function readRecordsChunk(chunkSize: number, state: State) { if (state.tokenType === PlyTokenType.End) return 0 @@ -258,13 +253,10 @@ function readRecordsChunks(state: State) { function addHeadEntry (state: State) { const head = Tokenizer.getTokenString(state.tokenizer) - console.log(head) state.initialHead.push(head) state.tokens.push(TokenBuilder.create(head, state.data.length / 80)) } - - function init(state: State) { // only for first two lines to get the format and the coding! (marco) let newRecord = moveNext(state) while (!newRecord) { // newRecord is only true when a newline occurs (marco) @@ -278,12 +270,12 @@ function init(state: State) { // only for first two lines to get the format and newRecord = moveNext(state); } addHeadEntry(state) - if(state.initialHead[0] !== 'ply'){ + if (state.initialHead[0] !== 'ply') { console.log('ERROR: this is not a .ply file!') throw new Error('this is not a .ply file!'); return 0; } - if(state.initialHead[2] !== 'ascii'){ + if (state.initialHead[2] !== 'ascii') { console.log('ERROR: only ASCII-DECODING is supported!'); throw new Error('only ASCII-DECODING is supported!'); return 0; @@ -293,7 +285,7 @@ function init(state: State) { // only for first two lines to get the format and } async function handleRecords(state: State): Promise<Data.ply_form> { - if(!init(state)){ + if (!init(state)) { console.log('ERROR: parsing file (PLY) failed!') throw new Error('arsing file (PLY) failed!'); } @@ -308,15 +300,6 @@ async function parseInternal(data: string, ctx: RuntimeContext, opts: PlyOptions ctx.update({ message: 'Parsing...', current: 0, max: data.length }); const PLYdata = await handleRecords(state) const result = Data.PlyFile(PLYdata) - console.log(result); - - // let Data_for_Shape = plyToShape.collectData_for_Shape(table, datas); - // console.log(plyToShape.getShape(state.runtimeCtx, table)); - // let shape = plyToShape.init_ren(PLYdata); - // console.log("shape"+shape); - // const script = document.createElement('script'); - // script.src = "../../build/src/mol-model/shape/formarts/ply/plyData_to_shape.js"; - // document.body.appendChild(script); return ReaderResult.success(result); } -- GitLab