UNPKG

modern-netcdf

Version:
127 lines (121 loc) 4.13 kB
const { readType, num2str } = require('./types'); const { notNetcdf, padding, readName } = require('./utils'); // Constants const ZERO = 0; const NC_DIMENSION = 10; const NC_VARIABLE = 11; const NC_ATTRIBUTE = 12; const NC_UNLIMITED = 0; function dimensionsList(buffer) { const result = {}; let recordId, recordName; const dimList = buffer.readUint32(); let dimensions; if (dimList === ZERO) { notNetcdf(buffer.readUint32() !== ZERO, 'wrong empty tag for list of dimensions'); return []; } else { notNetcdf(dimList !== NC_DIMENSION, 'wrong tag for list of dimensions'); const dimensionSize = buffer.readUint32(); dimensions = new Array(dimensionSize); for (let dim = 0; dim < dimensionSize; dim++) { const name = readName(buffer); const size = buffer.readUint32(); if (size === NC_UNLIMITED) { recordId = dim; recordName = name; } dimensions[dim] = { name, size }; } } if (recordId !== undefined) result.recordId = recordId; if (recordName !== undefined) result.recordName = recordName; result.dimensions = dimensions; return result; } function attributesList(buffer) { const gAttList = buffer.readUint32(); let attributes; if (gAttList === ZERO) { notNetcdf(buffer.readUint32() !== ZERO, 'wrong empty tag for list of attributes'); return []; } else { notNetcdf(gAttList !== NC_ATTRIBUTE, 'wrong tag for list of attributes'); const attributeSize = buffer.readUint32(); attributes = new Array(attributeSize); for (let gAtt = 0; gAtt < attributeSize; gAtt++) { const name = readName(buffer); const type = buffer.readUint32(); notNetcdf(type < 1 || type > 6, `non valid type ${type}`); const size = buffer.readUint32(); const value = readType(buffer, type, size); padding(buffer); attributes[gAtt] = { name, type: num2str(type), value }; } } return attributes; } function variablesList(buffer, recordId, version) { const varList = buffer.readUint32(); let recordStep = 0; let variables; if (varList === ZERO) { notNetcdf(buffer.readUint32() !== ZERO, 'wrong empty tag for list of variables'); return []; } else { notNetcdf(varList !== NC_VARIABLE, 'wrong tag for list of variables'); const variableSize = buffer.readUint32(); variables = new Array(variableSize); for (let v = 0; v < variableSize; v++) { const name = readName(buffer); const dimensionality = buffer.readUint32(); const dimensionsIds = new Array(dimensionality); for (let d = 0; d < dimensionality; d++) { dimensionsIds[d] = buffer.readUint32(); } const attributes = attributesList(buffer); const type = buffer.readUint32(); notNetcdf(type < 1 || type > 6, `non valid type ${type}`); const varSize = buffer.readUint32(); let offset = buffer.readUint32(); if (version === 2) { notNetcdf(offset > 0, 'offsets larger than 4GB not supported'); offset = buffer.readUint32(); } let record = false; if (typeof recordId !== 'undefined' && dimensionsIds[0] === recordId) { recordStep += varSize; record = true; } variables[v] = { name, dimensions: dimensionsIds, attributes, type: num2str(type), size: varSize, offset, record, }; } } return { variables, recordStep }; } function header(buffer, version) { const header = { version }; const recordDimension = { length: buffer.readUint32() }; const dimList = dimensionsList(buffer); if (!Array.isArray(dimList)) { recordDimension.id = dimList.recordId; recordDimension.name = dimList.recordName; header.dimensions = dimList.dimensions; } header.globalAttributes = attributesList(buffer); const varsInfo = variablesList(buffer, recordDimension?.id, version); if (!Array.isArray(varsInfo)) { header.variables = varsInfo.variables; recordDimension.recordStep = varsInfo.recordStep; } header.recordDimension = recordDimension; return header; } module.exports = { header };