From 1e28ab5e0c2c571f12a119d602168880fc8b4d1d Mon Sep 17 00:00:00 2001 From: cheminfo bot Date: Thu, 3 Nov 2016 13:07:20 +0000 Subject: [PATCH] Release v0.3.0 --- dist/netcdfjs.js | 47 +++++++++++++++++++++++++++++++++++----- dist/netcdfjs.min.js | 2 +- dist/netcdfjs.min.js.map | 2 +- package.json | 2 +- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/dist/netcdfjs.js b/dist/netcdfjs.js index 23c00ee..0fd54c8 100644 --- a/dist/netcdfjs.js +++ b/dist/netcdfjs.js @@ -143,14 +143,22 @@ return /******/ (function(modules) { // webpackBootstrap /** * Retrieves the data for a given variable - * @param {string} variableName - Name o the variable to search + * @param {string|object} variableName - Name of the variable to search or variable object * @return {Array} */ getDataVariable(variableName) { - // search the variable - var variable = this.header.variables.find(function (val) { - return val.name === variableName; - }); + var variable; + if (typeof variableName === 'string') { + // search the variable + variable = this.header.variables.find(function (val) { + return val.name === variableName; + }); + } else { + variable = variableName; + } + + // throws if variable not found + utils.notNetcdf((variable === undefined), 'variable not found'); // go to the offset position this.buffer.seek(variable.offset); @@ -494,7 +502,7 @@ return /******/ (function(modules) { // webpackBootstrap const type = types.str2num(variable.type); // size of the data - var size = variable.size / 4; + var size = variable.size / types.num2bytes(type); // iterates over the data var data = new Array(size); @@ -581,6 +589,32 @@ return /******/ (function(modules) { // webpackBootstrap } } + /** + * Parse a number type identifier to his size in bytes + * @ignore + * @param {number} type - integer that represents the type + * @return {number} -size of the type + */ + function num2bytes(type) { + switch (Number(type)) { + case types.BYTE: + return 1; + case types.CHAR: + return 1; + case types.SHORT: + return 2; + case types.INT: + return 4; + case types.FLOAT: + return 4; + case types.DOUBLE: + return 8; + /* istanbul ignore next */ + default: + return -1; + } + } + /** * Reverse search of num2str * @ignore @@ -670,6 +704,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = types; module.exports.num2str = num2str; + module.exports.num2bytes = num2bytes; module.exports.str2num = str2num; module.exports.readType = readType; diff --git a/dist/netcdfjs.min.js b/dist/netcdfjs.min.js index fef1513..902b6b8 100644 --- a/dist/netcdfjs.min.js +++ b/dist/netcdfjs.min.js @@ -1,2 +1,2 @@ -(function(b,c){'object'==typeof exports&&'object'==typeof module?module.exports=c():'function'==typeof define&&define.amd?define([],c):'object'==typeof exports?exports.netcdfjs=c():b.netcdfjs=c()})(this,function(){return function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p='',b(0)}([function(a,b,c){'use strict';const d=c(1),e=c(2),f=c(3),g=c(5);class j{constructor(k){const l=new d(k);l.setBigEndian(),e.notNetcdf('CDF'!==l.readChars(3),'should start with CDF');const m=l.readByte();e.notNetcdf(2===m,'64-bit offset format not supported yet'),e.notNetcdf(1!==m,'unknown version'),this.header=g(l),this.header.version=m,this.buffer=l}get version(){return 1===this.header.version?'classic format':'64-bit offset format'}get recordDimension(){return this.header.recordDimension}get dimensions(){return this.header.dimensions}get globalAttributes(){return this.header.globalAttributes}get variables(){return this.header.variables}getDataVariable(k){var l=this.header.variables.find(function(m){return m.name===k});return this.buffer.seek(l.offset),l.record?f.record(this.buffer,l,this.header.recordDimension):f.nonRecord(this.buffer,l)}}a.exports=j},function(a,b){'use strict';const c=8192,d=[];a.exports=class{constructor(f,g){g=g||{},f===void 0&&(f=c),'number'==typeof f&&(f=new ArrayBuffer(f));let h=f.byteLength;const j=g.offset?g.offset>>>0:0;f.buffer&&(h=f.byteLength-j,f=f.byteLength===f.buffer.byteLength?j?f.buffer.slice(j):f.buffer:f.buffer.slice(f.byteOffset+j,f.byteOffset+f.byteLength)),this.buffer=f,this.length=h,this.byteLength=h,this.byteOffset=0,this.offset=0,this.littleEndian=!0,this._data=new DataView(this.buffer),this._increment=h||c,this._mark=0}available(f){return void 0===f&&(f=1),this.offset+f<=this.length}isLittleEndian(){return this.littleEndian}setLittleEndian(){this.littleEndian=!0}isBigEndian(){return!this.littleEndian}setBigEndian(){this.littleEndian=!1}skip(f){f===void 0&&(f=1),this.offset+=f}seek(f){this.offset=f}mark(){this._mark=this.offset}reset(){this.offset=this._mark}rewind(){this.offset=0}ensureAvailable(f){if(void 0===f&&(f=1),!this.available(f)){const g=this._increment+this._increment;this._increment=g;const h=this.length+g,j=new Uint8Array(h);j.set(new Uint8Array(this.buffer)),this.buffer=j.buffer,this.length=h,this._data=new DataView(this.buffer)}}readBoolean(){return 0!==this.readUint8()}readInt8(){return this._data.getInt8(this.offset++)}readUint8(){return this._data.getUint8(this.offset++)}readByte(){return this.readUint8()}readBytes(f){f===void 0&&(f=1);var g=new Uint8Array(f);for(var h=0;hq||6w&&6>>0:0;f.buffer&&(h=f.byteLength-j,f=f.byteLength===f.buffer.byteLength?j?f.buffer.slice(j):f.buffer:f.buffer.slice(f.byteOffset+j,f.byteOffset+f.byteLength)),this.buffer=f,this.length=h,this.byteLength=h,this.byteOffset=0,this.offset=0,this.littleEndian=!0,this._data=new DataView(this.buffer),this._increment=h||c,this._mark=0}available(f){return void 0===f&&(f=1),this.offset+f<=this.length}isLittleEndian(){return this.littleEndian}setLittleEndian(){this.littleEndian=!0}isBigEndian(){return!this.littleEndian}setBigEndian(){this.littleEndian=!1}skip(f){f===void 0&&(f=1),this.offset+=f}seek(f){this.offset=f}mark(){this._mark=this.offset}reset(){this.offset=this._mark}rewind(){this.offset=0}ensureAvailable(f){if(void 0===f&&(f=1),!this.available(f)){const g=this._increment+this._increment;this._increment=g;const h=this.length+g,j=new Uint8Array(h);j.set(new Uint8Array(this.buffer)),this.buffer=j.buffer,this.length=h,this._data=new DataView(this.buffer)}}readBoolean(){return 0!==this.readUint8()}readInt8(){return this._data.getInt8(this.offset++)}readUint8(){return this._data.getUint8(this.offset++)}readByte(){return this.readUint8()}readBytes(f){f===void 0&&(f=1);var g=new Uint8Array(f);for(var h=0;hq||6w&&6} - List of dimensions with:\n * * `name`: String with the name of the dimension\n * * `size`: Number with the size of the dimension\n */\n get dimensions() {\n return this.header.dimensions;\n }\n\n /**\n * @return {Array} - List of global attributes with:\n * * `name`: String with the name of the attribute\n * * `type`: String with the type of the attribute\n * * `value`: A number or string with the value of the attribute\n */\n get globalAttributes() {\n return this.header.globalAttributes;\n }\n\n /**\n * @return {Array} - List of variables with:\n * * `name`: String with the name of the variable\n * * `dimensions`: Array with the dimension IDs of the variable\n * * `attributes`: Array with the attributes of the variable\n * * `type`: String with the type of the variable\n * * `size`: Number with the size of the variable\n * * `offset`: Number with the offset where of the variable begins\n * * `record`: True if is a record variable, false otherwise\n */\n get variables() {\n return this.header.variables;\n }\n\n /**\n * Retrieves the data for a given variable\n * @param {string} variableName - Name o the variable to search\n * @return {Array}\n */\n getDataVariable(variableName) {\n // search the variable\n var variable = this.header.variables.find(function (val) {\n return val.name === variableName;\n });\n\n // go to the offset position\n this.buffer.seek(variable.offset);\n\n if (variable.record) {\n // record variable case\n return data.record(this.buffer, variable, this.header.recordDimension);\n } else {\n // non-record variable case\n return data.nonRecord(this.buffer, variable);\n }\n }\n}\n\nmodule.exports = NetCDFReader;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/index.js\n// module id = 0\n// module chunks = 0","'use strict';\n\nconst defaultByteLength = 1024 * 8;\nconst charArray = [];\n\nclass IOBuffer {\n constructor(data, options) {\n options = options || {};\n if (data === undefined) {\n data = defaultByteLength;\n }\n if (typeof data === 'number') {\n data = new ArrayBuffer(data);\n }\n let length = data.byteLength;\n const offset = options.offset ? options.offset>>>0 : 0;\n if (data.buffer) {\n length = data.byteLength - offset;\n if (data.byteLength !== data.buffer.byteLength) { // Node.js buffer from pool\n data = data.buffer.slice(data.byteOffset + offset, data.byteOffset + data.byteLength);\n } else if (offset) {\n data = data.buffer.slice(offset);\n } else {\n data = data.buffer;\n }\n }\n this.buffer = data;\n this.length = length;\n this.byteLength = length;\n this.byteOffset = 0;\n this.offset = 0;\n this.littleEndian = true;\n this._data = new DataView(this.buffer);\n this._increment = length || defaultByteLength;\n this._mark = 0;\n }\n\n available(byteLength) {\n if (byteLength === undefined) byteLength = 1;\n return (this.offset + byteLength) <= this.length;\n }\n\n isLittleEndian() {\n return this.littleEndian;\n }\n\n setLittleEndian() {\n this.littleEndian = true;\n }\n\n isBigEndian() {\n return !this.littleEndian;\n }\n\n setBigEndian() {\n this.littleEndian = false;\n }\n\n skip(n) {\n if (n === undefined) n = 1;\n this.offset += n;\n }\n\n seek(offset) {\n this.offset = offset;\n }\n\n mark() {\n this._mark = this.offset;\n }\n\n reset() {\n this.offset = this._mark;\n }\n\n rewind() {\n this.offset = 0;\n }\n\n ensureAvailable(byteLength) {\n if (byteLength === undefined) byteLength = 1;\n if (!this.available(byteLength)) {\n const newIncrement = this._increment + this._increment;\n this._increment = newIncrement;\n const newLength = this.length + newIncrement;\n const newArray = new Uint8Array(newLength);\n newArray.set(new Uint8Array(this.buffer));\n this.buffer = newArray.buffer;\n this.length = newLength;\n this._data = new DataView(this.buffer);\n }\n }\n\n readBoolean() {\n return this.readUint8() !== 0;\n }\n\n readInt8() {\n return this._data.getInt8(this.offset++);\n }\n\n readUint8() {\n return this._data.getUint8(this.offset++);\n }\n\n readByte() {\n return this.readUint8();\n }\n\n readBytes(n) {\n if (n === undefined) n = 1;\n var bytes = new Uint8Array(n);\n for (var i = 0; i < n; i++) {\n bytes[i] = this.readByte();\n }\n return bytes;\n }\n\n readInt16() {\n var value = this._data.getInt16(this.offset, this.littleEndian);\n this.offset += 2;\n return value;\n }\n\n readUint16() {\n var value = this._data.getUint16(this.offset, this.littleEndian);\n this.offset += 2;\n return value;\n }\n\n readInt32() {\n var value = this._data.getInt32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n readUint32() {\n var value = this._data.getUint32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n readFloat32() {\n var value = this._data.getFloat32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n readFloat64() {\n var value = this._data.getFloat64(this.offset, this.littleEndian);\n this.offset += 8;\n return value;\n }\n\n readChar() {\n return String.fromCharCode(this.readInt8());\n }\n\n readChars(n) {\n if (n === undefined) n = 1;\n charArray.length = n;\n for (var i = 0; i < n; i++) {\n charArray[i] = this.readChar();\n }\n return charArray.join('');\n }\n\n writeBoolean(bool) {\n this.writeUint8(bool ? 0xff : 0x00);\n }\n\n writeInt8(value) {\n this.ensureAvailable(1);\n this._data.setInt8(this.offset++, value);\n }\n\n writeUint8(value) {\n this.ensureAvailable(1);\n this._data.setUint8(this.offset++, value);\n }\n\n writeByte(value) {\n this.writeUint8(value);\n }\n\n writeBytes(bytes) {\n this.ensureAvailable(bytes.length);\n for (var i = 0; i < bytes.length; i++) {\n this._data.setUint8(this.offset++, bytes[i]);\n }\n }\n\n writeInt16(value) {\n this.ensureAvailable(2);\n this._data.setInt16(this.offset, value, this.littleEndian);\n this.offset += 2;\n }\n\n writeUint16(value) {\n this.ensureAvailable(2);\n this._data.setUint16(this.offset, value, this.littleEndian);\n this.offset += 2;\n }\n\n writeInt32(value) {\n this.ensureAvailable(4);\n this._data.setInt32(this.offset, value, this.littleEndian);\n this.offset += 4;\n }\n\n writeUint32(value) {\n this.ensureAvailable(4);\n this._data.setUint32(this.offset, value, this.littleEndian);\n this.offset += 4;\n }\n\n writeFloat32(value) {\n this.ensureAvailable(4);\n this._data.setFloat32(this.offset, value, this.littleEndian);\n this.offset += 4;\n }\n\n writeFloat64(value) {\n this.ensureAvailable(8);\n this._data.setFloat64(this.offset, value, this.littleEndian);\n this.offset += 8;\n }\n\n writeChar(str) {\n this.writeUint8(str.charCodeAt(0));\n }\n\n writeChars(str) {\n for (var i = 0; i < str.length; i++) {\n this.writeUint8(str.charCodeAt(i));\n }\n }\n\n toArray() {\n return new Uint8Array(this.buffer, 0, this.offset);\n }\n}\n\nmodule.exports = IOBuffer;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/iobuffer/IOBuffer.js\n// module id = 1\n// module chunks = 0","'use strict';\n\n/**\n * Throws a non-valid NetCDF exception if the statement it's true\n * @ignore\n * @param {boolean} statement - Throws if true\n * @param {string} reason - Reason to throw\n */\nfunction notNetcdf(statement, reason) {\n if (statement) {\n throw new TypeError('Not a valid NetCDF v3.x file: ' + reason);\n }\n}\n\n/**\n * Moves 1, 2, or 3 bytes to next 4-byte boundary\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n */\nfunction padding(buffer) {\n if ((buffer.offset % 4) !== 0) {\n buffer.skip(4 - (buffer.offset % 4));\n }\n}\n\n\n/**\n * Reads the name\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {string} - Name\n */\nfunction readName(buffer) {\n // Read name\n var nameLength = buffer.readUint32();\n var name = buffer.readChars(nameLength);\n\n // validate name\n // TODO\n\n // Apply padding\n padding(buffer);\n return name;\n}\n\nmodule.exports.notNetcdf = notNetcdf;\nmodule.exports.padding = padding;\nmodule.exports.readName = readName;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/utils.js\n// module id = 2\n// module chunks = 0","'use strict';\n\nconst types = require('./types');\n\n// const STREAMING = 4294967295;\n\n/**\n * Read data for the given non-record variable\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {object} variable - Variable metadata\n * @return {Array} - Data of the element\n */\nfunction nonRecord(buffer, variable) {\n // variable type\n const type = types.str2num(variable.type);\n\n // size of the data\n var size = variable.size / 4;\n\n // iterates over the data\n var data = new Array(size);\n for (var i = 0; i < size; i++) {\n data[i] = types.readType(buffer, type, 1);\n }\n\n return data;\n}\n\n/**\n * Read data for the given record variable\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {object} variable - Variable metadata\n * @param {object} recordDimension - Record dimension metadata\n * @return {Array} - Data of the element\n */\nfunction record(buffer, variable, recordDimension) {\n // variable type\n const type = types.str2num(variable.type);\n\n // size of the data\n // TODO streaming data\n var size = recordDimension.length;\n\n // iterates over the data\n var data = new Array(size);\n const step = recordDimension.recordStep;\n\n for (var i = 0; i < size; i++) {\n var currentOffset = buffer.offset;\n data[i] = types.readType(buffer, type, 1);\n buffer.seek(currentOffset + step);\n }\n\n return data;\n}\n\nmodule.exports.nonRecord = nonRecord;\nmodule.exports.record = record;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/data.js\n// module id = 3\n// module chunks = 0","'use strict';\n\nconst notNetcdf = require('./utils').notNetcdf;\n\nconst types = {\n BYTE: 1,\n CHAR: 2,\n SHORT: 3,\n INT: 4,\n FLOAT: 5,\n DOUBLE: 6\n};\n\n/**\n * Parse a number into their respective type\n * @ignore\n * @param {number} type - integer that represents the type\n * @return {string} - parsed value of the type\n */\nfunction num2str(type) {\n switch (Number(type)) {\n case types.BYTE:\n return 'byte';\n case types.CHAR:\n return 'char';\n case types.SHORT:\n return 'short';\n case types.INT:\n return 'int';\n case types.FLOAT:\n return 'float';\n case types.DOUBLE:\n return 'double';\n /* istanbul ignore next */\n default:\n return 'undefined';\n }\n}\n\n/**\n * Reverse search of num2str\n * @ignore\n * @param {string} type - string that represents the type\n * @return {number} - parsed value of the type\n */\nfunction str2num(type) {\n switch (String(type)) {\n case 'byte':\n return types.BYTE;\n case 'char':\n return types.CHAR;\n case 'short':\n return types.SHORT;\n case 'int':\n return types.INT;\n case 'float':\n return types.FLOAT;\n case 'double':\n return types.DOUBLE;\n /* istanbul ignore next */\n default:\n return -1;\n }\n}\n\n/**\n * Auxiliary function to read numeric data\n * @ignore\n * @param {number} size - Size of the element to read\n * @param {function} bufferReader - Function to read next value\n * @return {Array|number}\n */\nfunction readNumber(size, bufferReader) {\n if (size !== 1) {\n var numbers = new Array(size);\n for (var i = 0; i < size; i++) {\n numbers[i] = bufferReader();\n }\n return numbers;\n } else {\n return bufferReader();\n }\n}\n\n/**\n * Given a type and a size reads the next element\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {number} type - Type of the data to read\n * @param {number} size - Size of the element to read\n * @return {string|Array|number}\n */\nfunction readType(buffer, type, size) {\n switch (type) {\n case types.BYTE:\n return buffer.readBytes(size);\n case types.CHAR:\n return trimNull(buffer.readChars(size));\n case types.SHORT:\n return readNumber(size, buffer.readInt16.bind(buffer));\n case types.INT:\n return readNumber(size, buffer.readInt32.bind(buffer));\n case types.FLOAT:\n return readNumber(size, buffer.readFloat32.bind(buffer));\n case types.DOUBLE:\n return readNumber(size, buffer.readFloat64.bind(buffer));\n /* istanbul ignore next */\n default:\n notNetcdf(true, 'non valid type ' + type);\n return undefined;\n }\n}\n\n/**\n * Removes null terminate value\n * @ignore\n * @param {string} value - String to trim\n * @return {string} - Trimmed string\n */\nfunction trimNull(value) {\n if (value.charCodeAt(value.length - 1) === 0) {\n return value.substring(0, value.length - 1);\n }\n return value;\n}\n\nmodule.exports = types;\nmodule.exports.num2str = num2str;\nmodule.exports.str2num = str2num;\nmodule.exports.readType = readType;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/types.js\n// module id = 4\n// module chunks = 0","'use strict';\n\nconst utils = require('./utils');\nconst types = require('./types');\n\n// Grammar constants\nconst ZERO = 0;\nconst NC_DIMENSION = 10;\nconst NC_VARIABLE = 11;\nconst NC_ATTRIBUTE = 12;\n\n/**\n * Read the header of the file\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {object} - Object with the fields:\n * * `recordDimension`: Number with the length of record dimension\n * * `dimensions`: List of dimensions\n * * `globalAttributes`: List of global attributes\n * * `variables`: List of variables\n */\nfunction header(buffer) {\n // Length of record dimension\n // sum of the varSize's of all the record variables.\n var header = {recordDimension: {length: buffer.readUint32()}};\n\n // List of dimensions\n var dimList = dimensionsList(buffer);\n header.recordDimension.id = dimList.recordId;\n header.recordDimension.name = dimList.recordName;\n header.dimensions = dimList.dimensions;\n\n // List of global attributes\n header.globalAttributes = attributesList(buffer);\n\n // List of variables\n var variables = variablesList(buffer, dimList.recordId);\n header.variables = variables.variables;\n header.recordDimension.recordStep = variables.recordStep;\n\n return header;\n}\n\n/**\n * List of dimensions\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {object} - List of dimensions and record dimension with:\n * * `name`: String with the name of the dimension\n * * `size`: Number with the size of the dimension\n */\nfunction dimensionsList(buffer) {\n var recordId, recordName;\n const dimList = buffer.readUint32();\n if (dimList === ZERO) {\n utils.notNetcdf((buffer.readUint32() !== ZERO), 'wrong empty tag for list of dimensions');\n return [];\n } else {\n utils.notNetcdf((dimList !== NC_DIMENSION), 'wrong tag for list of dimensions');\n\n // Length of dimensions\n const dimensionSize = buffer.readUint32();\n var dimensions = new Array(dimensionSize);\n for (var dim = 0; dim < dimensionSize; dim++) {\n // Read name\n var name = utils.readName(buffer);\n\n // Read dimension size\n const size = buffer.readUint32();\n if (size === 0) {\n recordId = dim;\n recordName = name;\n }\n\n dimensions[dim] = {\n name: name,\n size: size\n };\n }\n }\n return {\n dimensions: dimensions,\n recordId: recordId,\n recordName: recordName\n };\n}\n\n/**\n * List of attributes\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {Array} - List of attributes with:\n * * `name`: String with the name of the attribute\n * * `type`: String with the type of the attribute\n * * `value`: A number or string with the value of the attribute\n */\nfunction attributesList(buffer) {\n const gAttList = buffer.readUint32();\n if (gAttList === ZERO) {\n utils.notNetcdf((buffer.readUint32() !== ZERO), 'wrong empty tag for list of attributes');\n return [];\n } else {\n utils.notNetcdf((gAttList !== NC_ATTRIBUTE), 'wrong tag for list of attributes');\n\n // Length of attributes\n const attributeSize = buffer.readUint32();\n var attributes = new Array(attributeSize);\n for (var gAtt = 0; gAtt < attributeSize; gAtt++) {\n // Read name\n var name = utils.readName(buffer);\n\n // Read type\n var type = buffer.readUint32();\n utils.notNetcdf(((type < 1) || (type > 6)), 'non valid type ' + type);\n\n // Read attribute\n var size = buffer.readUint32();\n var value = types.readType(buffer, type, size);\n\n // Apply padding\n utils.padding(buffer);\n\n attributes[gAtt] = {\n name: name,\n type: types.num2str(type),\n value: value\n };\n }\n }\n return attributes;\n}\n\n/**\n * List of variables\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {number} recordId - Id if the record dimension\n * @return {object} - Number of recordStep and list of variables with:\n * * `name`: String with the name of the variable\n * * `dimensions`: Array with the dimension IDs of the variable\n * * `attributes`: Array with the attributes of the variable\n * * `type`: String with the type of the variable\n * * `size`: Number with the size of the variable\n * * `offset`: Number with the offset where of the variable begins\n * * `record`: True if is a record variable, false otherwise\n */\nfunction variablesList(buffer, recordId) {\n const varList = buffer.readUint32();\n var recordStep = 0;\n if (varList === ZERO) {\n utils.notNetcdf((buffer.readUint32() !== ZERO), 'wrong empty tag for list of variables');\n return [];\n } else {\n utils.notNetcdf((varList !== NC_VARIABLE), 'wrong tag for list of variables');\n\n // Length of variables\n const variableSize = buffer.readUint32();\n var variables = new Array(variableSize);\n for (var v = 0; v < variableSize; v++) {\n // Read name\n var name = utils.readName(buffer);\n\n // Read dimensionality of the variable\n const dimensionality = buffer.readUint32();\n\n // Index into the list of dimensions\n var dimensionsIds = new Array(dimensionality);\n for (var dim = 0; dim < dimensionality; dim++) {\n dimensionsIds[dim] = buffer.readUint32();\n }\n\n // Read variables size\n var attributes = attributesList(buffer);\n\n // Read type\n var type = buffer.readUint32();\n utils.notNetcdf(((type < 1) && (type > 6)), 'non valid type ' + type);\n\n // Read variable size\n // The 32-bit varSize field is not large enough to contain the size of variables that require\n // more than 2^32 - 4 bytes, so 2^32 - 1 is used in the varSize field for such variables.\n const varSize = buffer.readUint32();\n\n // Read offset\n // TODO change it for supporting 64-bit\n const offset = buffer.readUint32();\n\n // Count amount of record variables\n if (dimensionsIds[0] === recordId) {\n recordStep += varSize;\n }\n\n variables[v] = {\n name: name,\n dimensions: dimensionsIds,\n attributes: attributes,\n type: types.num2str(type),\n size: varSize,\n offset: offset,\n record: (dimensionsIds[0] === recordId)\n };\n }\n }\n\n return {\n variables: variables,\n recordStep: recordStep\n };\n}\n\nmodule.exports = header;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/header.js\n// module id = 5\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///netcdfjs/webpack/universalModuleDefinition","webpack:///netcdfjs/webpack/bootstrap 862471877c797883f038","webpack:///netcdfjs/./src/index.js","webpack:///netcdfjs/./~/iobuffer/IOBuffer.js","webpack:///netcdfjs/./src/utils.js","webpack:///netcdfjs/./src/data.js","webpack:///netcdfjs/./src/types.js","webpack:///netcdfjs/./src/header.js"],"names":[],"mappings":"AAAA,cACA,2BACA,uCACA,sCACA,cACA,GACA,0CAEA,eACA,GAAC,mBACD,kBCTA,cAMA,MACA,eAGA,mBACA,CACA,cACA,EAIA,kDAGA,KAGA,YACA,OAIA,IAzBA,iBA4BA,MAGA,MAGA,yBCtCA,CAEA,uBACA,OACA,OACA,OAQA,UACA,eACA,eACA,KAGA,kDAGA,mCACA,6BACA,4DAGA,iCACA,uBACA,cACA,CAKA,cACA,OACA,yBAEA,iBAEA,sBASA,sBACA,oBACA,eAOA,iBACA,oBACA,UAQA,uBACA,oBACA,gBAYA,gBACA,oBACA,SAOA,mBACA,IACA,YAEA,yDACA,iBACA,CAEA,GAIA,wBAGA,yCAEA,UAEA,0CAGA,yCAEA,EAGA,4BCvHA,CAEA,kBACA,QAEA,oBACA,iBACA,GACA,MACA,eAEA,GACA,uCAEA,YACA,yCACA,IACA,wBACA,4BACA,WAEA,iBAEA,KAGA,oDANa,yBAOb,cACA,kBACA,kBACA,cACA,OACA,6CACA,2BACA,aACA,CAEA,aACA,uBACA,uBACA,MAEA,iBACA,aACA,YAEA,kBACA,MACA,eAEA,cACA,aACA,YAEA,eACA,MACA,eAEA,QACA,gBACA,gBACA,CAEA,QACA,aACA,CAEA,OACA,iBACA,MAEA,QACA,kBACA,KAEA,SACA,aACA,CAEA,mBACA,mBACA,sBACA,8BACA,2BACA,sBACA,mBACA,6BACA,uBACA,mBACA,+BACA,OACA,CAEA,cACA,OACA,qBAEA,WACA,gCACA,SAEA,YACA,iCACA,SAEA,WACA,aACA,WAEA,aACA,gBACA,wBACA,aAAuB,IAAO,EAC9B,cAEA,iBACA,EAEA,YACA,4CACA,kCACA,EACA,CAEA,aACA,6CACA,kCACA,EACA,CAEA,YACA,4CACA,kCACA,EACA,CAEA,aACA,6CACA,kCACA,EACA,CAEA,cACA,8CACA,kCACA,EACA,CAEA,cACA,8CACA,kCACA,EACA,CAEA,WACA,iCACA,WAEA,aACA,gBACA,YACA,YAAuB,IAAO,EAC9B,cAEA,yBACA,GAEA,gBACA,uBACA,EAEA,aACA,sBACA,oCACA,EAEA,cACA,sBACA,qCACA,EAEA,aACA,iBACA,EAEA,cACA,wBACA,kBAAuB,MAAkB,OACzC,wCAEA,GAEA,cACA,sBACA,0CACA,2BACA,CAEA,eACA,sBACA,2CACA,2BACA,CAEA,cACA,sBACA,0CACA,2BACA,CAEA,eACA,sBACA,2CACA,2BACA,CAEA,gBACA,sBACA,4CACA,2BACA,CAEA,gBACA,sBACA,4CACA,2BACA,CAEA,aACA,8BACA,GAEA,cACA,WAAuB,MAAgB,OACvC,iCAEA,GAEA,UACA,0CACA,OAGA,iBCnPA,CAQA,0BAYA,CACA,iCAEA,EASA,WAcA,uBArCA,IACA,uDAEA,EAOA,oBA4BA,gCAbA,SACA,2BAMA,YACA,GACA,CAEA,kBC7CA,CAEA,uBAWA,aA8CA,uBA5CA,qBAGA,+BAGA,WACA,aAAmB,IAAU,EAC7B,wBAGA,SACA,EAUA,kCAEA,qBAIA,cAGA,eACA,aAEA,qBAAmB,IAAU,MAC7B,SACA,2BACA,YACA,EAEA,OACA,EAEA,kBC1DA,CAEA,4BAiGA,UACA,aACA,aAAuB,IAAU,EACjC,SAEA,UACA,EACA,OAEA,IAUA,cA4BA,OACA,qDAEA,GACA,CAEA,cApJA,YACA,MACA,OACA,QACA,MACA,QACA,SASA,aAsIA,YACA,mBAtIA,SACA,UACA,WACA,cACA,WACA,cACA,YACA,eACA,UACA,aACA,YACA,eACA,aAEA,SACA,cAEA,aAQA,YA8GA,qBA7GA,SACA,UACA,WACA,UACA,WACA,UACA,YACA,UACA,UACA,UACA,YACA,UACA,aAEA,GACA,eAEA,GAQA,YAqFA,mBApFA,QACA,UACA,gBACA,SACA,gBACA,SACA,iBACA,UACA,eACA,QACA,iBACA,UACA,kBAEA,OACA,eAEA,GASA,oCAqBA,OACA,OACA,iBACA,SACA,mBACA,UACA,2BACA,UACA,yBACA,UACA,6BACA,UACA,8BAGA,4BAGA,UAQA,kBCjJA,CAEA,0BAkDA,OACA,YACA,oBACA,EAGA,sCAFA,yDAhDA,OAqDA,8CACA,yBACA,aAAyB,IAAqB,MAE9C,kBAGA,aACA,aACA,UACA,IAGA,QACA,MACA,OAEA,EAEA,OACA,YACA,WACA,aAEA,EAWA,cACA,WACA,oBACA,EAGA,sCAFA,yDA/EA,OAoFA,8CACA,yBACA,aAA0B,IAAsB,MAEhD,kBAGA,OACA,oDAGA,WACA,8BAGA,aAEA,QACA,MACA,iBACA,SAEA,EAEA,OACA,EAgBA,gBACA,WACA,mBACA,SACA,EAGA,sCAFA,wDA9IA,OAmJA,6CACA,yBACA,aAAuB,IAAkB,MAEzC,kBAGA,aAGA,yBACA,aAA6B,IAAsB,EACnD,WAIA,qBAGA,OACA,oDAKA,aAIA,iBAGA,oBACA,OAGA,QACA,MACA,aACA,aACA,iBACA,QACA,SACA,gBAEA,EAGA,OACA,WACA,aAEA,EAEA,WA/MA,OAGA,KACA,uBAiBA,QAAkB,iBAAkB,SAGpC,mBACA,0BACA,kCACA,0BAGA,gCAGA,eACA,+BACA,yCAEA,WACA,CAUA","file":"netcdfjs.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"netcdfjs\"] = factory();\n\telse\n\t\troot[\"netcdfjs\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 862471877c797883f038","'use strict';\n\nconst IOBuffer = require('iobuffer');\nconst utils = require('./utils');\nconst data = require('./data');\nconst readHeader = require('./header');\n\n/**\n * Reads a NetCDF v3.x file\n * https://www.unidata.ucar.edu/software/netcdf/docs/file_format_specifications.html\n * @param {ArrayBuffer} data - ArrayBuffer or any Typed Array (including Node.js' Buffer from v4) with the data\n * @constructor\n */\nclass NetCDFReader {\n constructor(data) {\n const buffer = new IOBuffer(data);\n buffer.setBigEndian();\n\n // Validate that it's a NetCDF file\n utils.notNetcdf((buffer.readChars(3) !== 'CDF'), 'should start with CDF');\n\n // Check the NetCDF format\n const version = buffer.readByte();\n utils.notNetcdf((version === 2), '64-bit offset format not supported yet');\n utils.notNetcdf((version !== 1), 'unknown version');\n\n // Read the header\n this.header = readHeader(buffer);\n this.header.version = version;\n this.buffer = buffer;\n }\n\n /**\n * @return {string} - Version for the NetCDF format\n */\n get version() {\n if (this.header.version === 1) {\n return 'classic format';\n } else {\n return '64-bit offset format';\n }\n }\n\n /**\n * @return {object} - Metadata for the record dimension\n * * `length`: Number of elements in the record dimension\n * * `id`: Id number in the list of dimensions for the record dimension\n * * `name`: String with the name of the record dimension\n * * `recordStep`: Number with the record variables step size\n */\n get recordDimension() {\n return this.header.recordDimension;\n }\n\n /**\n * @return {Array} - List of dimensions with:\n * * `name`: String with the name of the dimension\n * * `size`: Number with the size of the dimension\n */\n get dimensions() {\n return this.header.dimensions;\n }\n\n /**\n * @return {Array} - List of global attributes with:\n * * `name`: String with the name of the attribute\n * * `type`: String with the type of the attribute\n * * `value`: A number or string with the value of the attribute\n */\n get globalAttributes() {\n return this.header.globalAttributes;\n }\n\n /**\n * @return {Array} - List of variables with:\n * * `name`: String with the name of the variable\n * * `dimensions`: Array with the dimension IDs of the variable\n * * `attributes`: Array with the attributes of the variable\n * * `type`: String with the type of the variable\n * * `size`: Number with the size of the variable\n * * `offset`: Number with the offset where of the variable begins\n * * `record`: True if is a record variable, false otherwise\n */\n get variables() {\n return this.header.variables;\n }\n\n /**\n * Retrieves the data for a given variable\n * @param {string|object} variableName - Name of the variable to search or variable object\n * @return {Array}\n */\n getDataVariable(variableName) {\n var variable;\n if (typeof variableName === 'string') {\n // search the variable\n variable = this.header.variables.find(function (val) {\n return val.name === variableName;\n });\n } else {\n variable = variableName;\n }\n\n // throws if variable not found\n utils.notNetcdf((variable === undefined), 'variable not found');\n\n // go to the offset position\n this.buffer.seek(variable.offset);\n\n if (variable.record) {\n // record variable case\n return data.record(this.buffer, variable, this.header.recordDimension);\n } else {\n // non-record variable case\n return data.nonRecord(this.buffer, variable);\n }\n }\n}\n\nmodule.exports = NetCDFReader;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/index.js\n// module id = 0\n// module chunks = 0","'use strict';\n\nconst defaultByteLength = 1024 * 8;\nconst charArray = [];\n\nclass IOBuffer {\n constructor(data, options) {\n options = options || {};\n if (data === undefined) {\n data = defaultByteLength;\n }\n if (typeof data === 'number') {\n data = new ArrayBuffer(data);\n }\n let length = data.byteLength;\n const offset = options.offset ? options.offset>>>0 : 0;\n if (data.buffer) {\n length = data.byteLength - offset;\n if (data.byteLength !== data.buffer.byteLength) { // Node.js buffer from pool\n data = data.buffer.slice(data.byteOffset + offset, data.byteOffset + data.byteLength);\n } else if (offset) {\n data = data.buffer.slice(offset);\n } else {\n data = data.buffer;\n }\n }\n this.buffer = data;\n this.length = length;\n this.byteLength = length;\n this.byteOffset = 0;\n this.offset = 0;\n this.littleEndian = true;\n this._data = new DataView(this.buffer);\n this._increment = length || defaultByteLength;\n this._mark = 0;\n }\n\n available(byteLength) {\n if (byteLength === undefined) byteLength = 1;\n return (this.offset + byteLength) <= this.length;\n }\n\n isLittleEndian() {\n return this.littleEndian;\n }\n\n setLittleEndian() {\n this.littleEndian = true;\n }\n\n isBigEndian() {\n return !this.littleEndian;\n }\n\n setBigEndian() {\n this.littleEndian = false;\n }\n\n skip(n) {\n if (n === undefined) n = 1;\n this.offset += n;\n }\n\n seek(offset) {\n this.offset = offset;\n }\n\n mark() {\n this._mark = this.offset;\n }\n\n reset() {\n this.offset = this._mark;\n }\n\n rewind() {\n this.offset = 0;\n }\n\n ensureAvailable(byteLength) {\n if (byteLength === undefined) byteLength = 1;\n if (!this.available(byteLength)) {\n const newIncrement = this._increment + this._increment;\n this._increment = newIncrement;\n const newLength = this.length + newIncrement;\n const newArray = new Uint8Array(newLength);\n newArray.set(new Uint8Array(this.buffer));\n this.buffer = newArray.buffer;\n this.length = newLength;\n this._data = new DataView(this.buffer);\n }\n }\n\n readBoolean() {\n return this.readUint8() !== 0;\n }\n\n readInt8() {\n return this._data.getInt8(this.offset++);\n }\n\n readUint8() {\n return this._data.getUint8(this.offset++);\n }\n\n readByte() {\n return this.readUint8();\n }\n\n readBytes(n) {\n if (n === undefined) n = 1;\n var bytes = new Uint8Array(n);\n for (var i = 0; i < n; i++) {\n bytes[i] = this.readByte();\n }\n return bytes;\n }\n\n readInt16() {\n var value = this._data.getInt16(this.offset, this.littleEndian);\n this.offset += 2;\n return value;\n }\n\n readUint16() {\n var value = this._data.getUint16(this.offset, this.littleEndian);\n this.offset += 2;\n return value;\n }\n\n readInt32() {\n var value = this._data.getInt32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n readUint32() {\n var value = this._data.getUint32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n readFloat32() {\n var value = this._data.getFloat32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n readFloat64() {\n var value = this._data.getFloat64(this.offset, this.littleEndian);\n this.offset += 8;\n return value;\n }\n\n readChar() {\n return String.fromCharCode(this.readInt8());\n }\n\n readChars(n) {\n if (n === undefined) n = 1;\n charArray.length = n;\n for (var i = 0; i < n; i++) {\n charArray[i] = this.readChar();\n }\n return charArray.join('');\n }\n\n writeBoolean(bool) {\n this.writeUint8(bool ? 0xff : 0x00);\n }\n\n writeInt8(value) {\n this.ensureAvailable(1);\n this._data.setInt8(this.offset++, value);\n }\n\n writeUint8(value) {\n this.ensureAvailable(1);\n this._data.setUint8(this.offset++, value);\n }\n\n writeByte(value) {\n this.writeUint8(value);\n }\n\n writeBytes(bytes) {\n this.ensureAvailable(bytes.length);\n for (var i = 0; i < bytes.length; i++) {\n this._data.setUint8(this.offset++, bytes[i]);\n }\n }\n\n writeInt16(value) {\n this.ensureAvailable(2);\n this._data.setInt16(this.offset, value, this.littleEndian);\n this.offset += 2;\n }\n\n writeUint16(value) {\n this.ensureAvailable(2);\n this._data.setUint16(this.offset, value, this.littleEndian);\n this.offset += 2;\n }\n\n writeInt32(value) {\n this.ensureAvailable(4);\n this._data.setInt32(this.offset, value, this.littleEndian);\n this.offset += 4;\n }\n\n writeUint32(value) {\n this.ensureAvailable(4);\n this._data.setUint32(this.offset, value, this.littleEndian);\n this.offset += 4;\n }\n\n writeFloat32(value) {\n this.ensureAvailable(4);\n this._data.setFloat32(this.offset, value, this.littleEndian);\n this.offset += 4;\n }\n\n writeFloat64(value) {\n this.ensureAvailable(8);\n this._data.setFloat64(this.offset, value, this.littleEndian);\n this.offset += 8;\n }\n\n writeChar(str) {\n this.writeUint8(str.charCodeAt(0));\n }\n\n writeChars(str) {\n for (var i = 0; i < str.length; i++) {\n this.writeUint8(str.charCodeAt(i));\n }\n }\n\n toArray() {\n return new Uint8Array(this.buffer, 0, this.offset);\n }\n}\n\nmodule.exports = IOBuffer;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/iobuffer/IOBuffer.js\n// module id = 1\n// module chunks = 0","'use strict';\n\n/**\n * Throws a non-valid NetCDF exception if the statement it's true\n * @ignore\n * @param {boolean} statement - Throws if true\n * @param {string} reason - Reason to throw\n */\nfunction notNetcdf(statement, reason) {\n if (statement) {\n throw new TypeError('Not a valid NetCDF v3.x file: ' + reason);\n }\n}\n\n/**\n * Moves 1, 2, or 3 bytes to next 4-byte boundary\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n */\nfunction padding(buffer) {\n if ((buffer.offset % 4) !== 0) {\n buffer.skip(4 - (buffer.offset % 4));\n }\n}\n\n\n/**\n * Reads the name\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {string} - Name\n */\nfunction readName(buffer) {\n // Read name\n var nameLength = buffer.readUint32();\n var name = buffer.readChars(nameLength);\n\n // validate name\n // TODO\n\n // Apply padding\n padding(buffer);\n return name;\n}\n\nmodule.exports.notNetcdf = notNetcdf;\nmodule.exports.padding = padding;\nmodule.exports.readName = readName;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/utils.js\n// module id = 2\n// module chunks = 0","'use strict';\n\nconst types = require('./types');\n\n// const STREAMING = 4294967295;\n\n/**\n * Read data for the given non-record variable\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {object} variable - Variable metadata\n * @return {Array} - Data of the element\n */\nfunction nonRecord(buffer, variable) {\n // variable type\n const type = types.str2num(variable.type);\n\n // size of the data\n var size = variable.size / types.num2bytes(type);\n\n // iterates over the data\n var data = new Array(size);\n for (var i = 0; i < size; i++) {\n data[i] = types.readType(buffer, type, 1);\n }\n\n return data;\n}\n\n/**\n * Read data for the given record variable\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {object} variable - Variable metadata\n * @param {object} recordDimension - Record dimension metadata\n * @return {Array} - Data of the element\n */\nfunction record(buffer, variable, recordDimension) {\n // variable type\n const type = types.str2num(variable.type);\n\n // size of the data\n // TODO streaming data\n var size = recordDimension.length;\n\n // iterates over the data\n var data = new Array(size);\n const step = recordDimension.recordStep;\n\n for (var i = 0; i < size; i++) {\n var currentOffset = buffer.offset;\n data[i] = types.readType(buffer, type, 1);\n buffer.seek(currentOffset + step);\n }\n\n return data;\n}\n\nmodule.exports.nonRecord = nonRecord;\nmodule.exports.record = record;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/data.js\n// module id = 3\n// module chunks = 0","'use strict';\n\nconst notNetcdf = require('./utils').notNetcdf;\n\nconst types = {\n BYTE: 1,\n CHAR: 2,\n SHORT: 3,\n INT: 4,\n FLOAT: 5,\n DOUBLE: 6\n};\n\n/**\n * Parse a number into their respective type\n * @ignore\n * @param {number} type - integer that represents the type\n * @return {string} - parsed value of the type\n */\nfunction num2str(type) {\n switch (Number(type)) {\n case types.BYTE:\n return 'byte';\n case types.CHAR:\n return 'char';\n case types.SHORT:\n return 'short';\n case types.INT:\n return 'int';\n case types.FLOAT:\n return 'float';\n case types.DOUBLE:\n return 'double';\n /* istanbul ignore next */\n default:\n return 'undefined';\n }\n}\n\n/**\n * Parse a number type identifier to his size in bytes\n * @ignore\n * @param {number} type - integer that represents the type\n * @return {number} -size of the type\n */\nfunction num2bytes(type) {\n switch (Number(type)) {\n case types.BYTE:\n return 1;\n case types.CHAR:\n return 1;\n case types.SHORT:\n return 2;\n case types.INT:\n return 4;\n case types.FLOAT:\n return 4;\n case types.DOUBLE:\n return 8;\n /* istanbul ignore next */\n default:\n return -1;\n }\n}\n\n/**\n * Reverse search of num2str\n * @ignore\n * @param {string} type - string that represents the type\n * @return {number} - parsed value of the type\n */\nfunction str2num(type) {\n switch (String(type)) {\n case 'byte':\n return types.BYTE;\n case 'char':\n return types.CHAR;\n case 'short':\n return types.SHORT;\n case 'int':\n return types.INT;\n case 'float':\n return types.FLOAT;\n case 'double':\n return types.DOUBLE;\n /* istanbul ignore next */\n default:\n return -1;\n }\n}\n\n/**\n * Auxiliary function to read numeric data\n * @ignore\n * @param {number} size - Size of the element to read\n * @param {function} bufferReader - Function to read next value\n * @return {Array|number}\n */\nfunction readNumber(size, bufferReader) {\n if (size !== 1) {\n var numbers = new Array(size);\n for (var i = 0; i < size; i++) {\n numbers[i] = bufferReader();\n }\n return numbers;\n } else {\n return bufferReader();\n }\n}\n\n/**\n * Given a type and a size reads the next element\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {number} type - Type of the data to read\n * @param {number} size - Size of the element to read\n * @return {string|Array|number}\n */\nfunction readType(buffer, type, size) {\n switch (type) {\n case types.BYTE:\n return buffer.readBytes(size);\n case types.CHAR:\n return trimNull(buffer.readChars(size));\n case types.SHORT:\n return readNumber(size, buffer.readInt16.bind(buffer));\n case types.INT:\n return readNumber(size, buffer.readInt32.bind(buffer));\n case types.FLOAT:\n return readNumber(size, buffer.readFloat32.bind(buffer));\n case types.DOUBLE:\n return readNumber(size, buffer.readFloat64.bind(buffer));\n /* istanbul ignore next */\n default:\n notNetcdf(true, 'non valid type ' + type);\n return undefined;\n }\n}\n\n/**\n * Removes null terminate value\n * @ignore\n * @param {string} value - String to trim\n * @return {string} - Trimmed string\n */\nfunction trimNull(value) {\n if (value.charCodeAt(value.length - 1) === 0) {\n return value.substring(0, value.length - 1);\n }\n return value;\n}\n\nmodule.exports = types;\nmodule.exports.num2str = num2str;\nmodule.exports.num2bytes = num2bytes;\nmodule.exports.str2num = str2num;\nmodule.exports.readType = readType;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/types.js\n// module id = 4\n// module chunks = 0","'use strict';\n\nconst utils = require('./utils');\nconst types = require('./types');\n\n// Grammar constants\nconst ZERO = 0;\nconst NC_DIMENSION = 10;\nconst NC_VARIABLE = 11;\nconst NC_ATTRIBUTE = 12;\n\n/**\n * Read the header of the file\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {object} - Object with the fields:\n * * `recordDimension`: Number with the length of record dimension\n * * `dimensions`: List of dimensions\n * * `globalAttributes`: List of global attributes\n * * `variables`: List of variables\n */\nfunction header(buffer) {\n // Length of record dimension\n // sum of the varSize's of all the record variables.\n var header = {recordDimension: {length: buffer.readUint32()}};\n\n // List of dimensions\n var dimList = dimensionsList(buffer);\n header.recordDimension.id = dimList.recordId;\n header.recordDimension.name = dimList.recordName;\n header.dimensions = dimList.dimensions;\n\n // List of global attributes\n header.globalAttributes = attributesList(buffer);\n\n // List of variables\n var variables = variablesList(buffer, dimList.recordId);\n header.variables = variables.variables;\n header.recordDimension.recordStep = variables.recordStep;\n\n return header;\n}\n\n/**\n * List of dimensions\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {object} - List of dimensions and record dimension with:\n * * `name`: String with the name of the dimension\n * * `size`: Number with the size of the dimension\n */\nfunction dimensionsList(buffer) {\n var recordId, recordName;\n const dimList = buffer.readUint32();\n if (dimList === ZERO) {\n utils.notNetcdf((buffer.readUint32() !== ZERO), 'wrong empty tag for list of dimensions');\n return [];\n } else {\n utils.notNetcdf((dimList !== NC_DIMENSION), 'wrong tag for list of dimensions');\n\n // Length of dimensions\n const dimensionSize = buffer.readUint32();\n var dimensions = new Array(dimensionSize);\n for (var dim = 0; dim < dimensionSize; dim++) {\n // Read name\n var name = utils.readName(buffer);\n\n // Read dimension size\n const size = buffer.readUint32();\n if (size === 0) {\n recordId = dim;\n recordName = name;\n }\n\n dimensions[dim] = {\n name: name,\n size: size\n };\n }\n }\n return {\n dimensions: dimensions,\n recordId: recordId,\n recordName: recordName\n };\n}\n\n/**\n * List of attributes\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {Array} - List of attributes with:\n * * `name`: String with the name of the attribute\n * * `type`: String with the type of the attribute\n * * `value`: A number or string with the value of the attribute\n */\nfunction attributesList(buffer) {\n const gAttList = buffer.readUint32();\n if (gAttList === ZERO) {\n utils.notNetcdf((buffer.readUint32() !== ZERO), 'wrong empty tag for list of attributes');\n return [];\n } else {\n utils.notNetcdf((gAttList !== NC_ATTRIBUTE), 'wrong tag for list of attributes');\n\n // Length of attributes\n const attributeSize = buffer.readUint32();\n var attributes = new Array(attributeSize);\n for (var gAtt = 0; gAtt < attributeSize; gAtt++) {\n // Read name\n var name = utils.readName(buffer);\n\n // Read type\n var type = buffer.readUint32();\n utils.notNetcdf(((type < 1) || (type > 6)), 'non valid type ' + type);\n\n // Read attribute\n var size = buffer.readUint32();\n var value = types.readType(buffer, type, size);\n\n // Apply padding\n utils.padding(buffer);\n\n attributes[gAtt] = {\n name: name,\n type: types.num2str(type),\n value: value\n };\n }\n }\n return attributes;\n}\n\n/**\n * List of variables\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {number} recordId - Id if the record dimension\n * @return {object} - Number of recordStep and list of variables with:\n * * `name`: String with the name of the variable\n * * `dimensions`: Array with the dimension IDs of the variable\n * * `attributes`: Array with the attributes of the variable\n * * `type`: String with the type of the variable\n * * `size`: Number with the size of the variable\n * * `offset`: Number with the offset where of the variable begins\n * * `record`: True if is a record variable, false otherwise\n */\nfunction variablesList(buffer, recordId) {\n const varList = buffer.readUint32();\n var recordStep = 0;\n if (varList === ZERO) {\n utils.notNetcdf((buffer.readUint32() !== ZERO), 'wrong empty tag for list of variables');\n return [];\n } else {\n utils.notNetcdf((varList !== NC_VARIABLE), 'wrong tag for list of variables');\n\n // Length of variables\n const variableSize = buffer.readUint32();\n var variables = new Array(variableSize);\n for (var v = 0; v < variableSize; v++) {\n // Read name\n var name = utils.readName(buffer);\n\n // Read dimensionality of the variable\n const dimensionality = buffer.readUint32();\n\n // Index into the list of dimensions\n var dimensionsIds = new Array(dimensionality);\n for (var dim = 0; dim < dimensionality; dim++) {\n dimensionsIds[dim] = buffer.readUint32();\n }\n\n // Read variables size\n var attributes = attributesList(buffer);\n\n // Read type\n var type = buffer.readUint32();\n utils.notNetcdf(((type < 1) && (type > 6)), 'non valid type ' + type);\n\n // Read variable size\n // The 32-bit varSize field is not large enough to contain the size of variables that require\n // more than 2^32 - 4 bytes, so 2^32 - 1 is used in the varSize field for such variables.\n const varSize = buffer.readUint32();\n\n // Read offset\n // TODO change it for supporting 64-bit\n const offset = buffer.readUint32();\n\n // Count amount of record variables\n if (dimensionsIds[0] === recordId) {\n recordStep += varSize;\n }\n\n variables[v] = {\n name: name,\n dimensions: dimensionsIds,\n attributes: attributes,\n type: types.num2str(type),\n size: varSize,\n offset: offset,\n record: (dimensionsIds[0] === recordId)\n };\n }\n }\n\n return {\n variables: variables,\n recordStep: recordStep\n };\n}\n\nmodule.exports = header;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/header.js\n// module id = 5\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file diff --git a/package.json b/package.json index 6216888..57ac79e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "netcdfjs", - "version": "0.2.0", + "version": "0.3.0", "description": "Read and explore NetCDF files", "keywords": [ "netcdf",