nodenetcdf 4.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.clang-format +13 -0
- package/.github/workflows/nodejs.yml +97 -0
- package/LICENSE +13 -0
- package/README.md +330 -0
- package/binding.gyp +95 -0
- package/package.json +35 -0
- package/scripts/copy-deps.js +57 -0
- package/scripts/setup-vcpkg.js +93 -0
- package/scripts/verify-build-deps.js +61 -0
- package/src/Attribute.cpp +334 -0
- package/src/Attribute.h +46 -0
- package/src/Dimension.cpp +105 -0
- package/src/Dimension.h +40 -0
- package/src/File.cpp +170 -0
- package/src/File.h +42 -0
- package/src/Group.cpp +483 -0
- package/src/Group.h +49 -0
- package/src/Variable.cpp +1352 -0
- package/src/Variable.h +88 -0
- package/src/nodenetcdfjs.cpp +24 -0
- package/src/nodenetcdfjs.h +37 -0
- package/test/attribute.js +36 -0
- package/test/dimension.js +18 -0
- package/test/file.js +19 -0
- package/test/group.js +57 -0
- package/test/test_hgroups.nc +0 -0
- package/test/testrh.nc +0 -0
- package/test/variable.js +16 -0
package/src/Variable.h
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#ifndef NODENETCDFJS_VARIABLE_H
|
|
2
|
+
#define NODENETCDFJS_VARIABLE_H
|
|
3
|
+
|
|
4
|
+
#include <array>
|
|
5
|
+
#include <netcdf.h>
|
|
6
|
+
#include <node.h>
|
|
7
|
+
#include <node_object_wrap.h>
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
namespace nodenetcdfjs
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
class Variable : public node::ObjectWrap
|
|
14
|
+
{
|
|
15
|
+
public:
|
|
16
|
+
static void Init(v8::Local<v8::Object> exports);
|
|
17
|
+
Variable(int id_, int parent_id_) noexcept;
|
|
18
|
+
|
|
19
|
+
[[nodiscard]] bool get_name(char *name) const noexcept;
|
|
20
|
+
|
|
21
|
+
private:
|
|
22
|
+
// Delete copy and move operations for safety
|
|
23
|
+
Variable(const Variable &) = delete;
|
|
24
|
+
Variable &operator=(const Variable &) = delete;
|
|
25
|
+
Variable(Variable &&) = delete;
|
|
26
|
+
Variable &operator=(Variable &&) = delete;
|
|
27
|
+
|
|
28
|
+
static void Read(const v8::FunctionCallbackInfo<v8::Value> &args);
|
|
29
|
+
static void ReadSlice(const v8::FunctionCallbackInfo<v8::Value> &args);
|
|
30
|
+
static void ReadStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args);
|
|
31
|
+
static void Write(const v8::FunctionCallbackInfo<v8::Value> &args);
|
|
32
|
+
static void WriteSlice(const v8::FunctionCallbackInfo<v8::Value> &args);
|
|
33
|
+
static void WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args);
|
|
34
|
+
static void AddAttribute(const v8::FunctionCallbackInfo<v8::Value> &args);
|
|
35
|
+
|
|
36
|
+
static void GetId(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
37
|
+
static void GetType(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
38
|
+
static void GetDimensions(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
39
|
+
static void GetAttributes(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
40
|
+
static void GetName(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
41
|
+
static void SetName(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
42
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
43
|
+
static void GetEndianness(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
44
|
+
static void SetEndianness(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
45
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
46
|
+
static void GetChecksumMode(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
47
|
+
static void SetChecksumMode(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
48
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
49
|
+
static void GetChunkMode(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
50
|
+
static void SetChunkMode(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
51
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
52
|
+
static void GetChunkSizes(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
53
|
+
static void SetChunkSizes(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
54
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
55
|
+
static void GetFillMode(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
56
|
+
static void SetFillMode(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
57
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
58
|
+
static void GetFillValue(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
59
|
+
static void SetFillValue(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
60
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
61
|
+
static void GetCompressionShuffle(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
62
|
+
static void SetCompressionShuffle(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
63
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
64
|
+
static void GetCompressionDeflate(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
65
|
+
static void SetCompressionDeflate(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
66
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
67
|
+
static void GetCompressionLevel(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info);
|
|
68
|
+
static void SetCompressionLevel(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
69
|
+
const v8::PropertyCallbackInfo<void> &info);
|
|
70
|
+
static void Inspect(const v8::FunctionCallbackInfo<v8::Value> &args);
|
|
71
|
+
|
|
72
|
+
static v8::Persistent<v8::Function> constructor;
|
|
73
|
+
|
|
74
|
+
// Use constexpr arrays for compile-time constants
|
|
75
|
+
static constexpr std::array<unsigned char, 11> type_sizes = {1, 1, 2, 4, 4, 8, 1, 2, 4, 8, 0};
|
|
76
|
+
|
|
77
|
+
static constexpr std::array<const char *, 11> type_names = {"byte", "char", "short", "int", "float", "double",
|
|
78
|
+
"ubyte", "ushort", "uint", "int64", "string"};
|
|
79
|
+
|
|
80
|
+
int id{-1};
|
|
81
|
+
int parent_id{-1};
|
|
82
|
+
nc_type type{NC_NAT};
|
|
83
|
+
int ndims{0};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
} // namespace nodenetcdfjs
|
|
87
|
+
|
|
88
|
+
#endif
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#include "Attribute.h"
|
|
2
|
+
#include "Dimension.h"
|
|
3
|
+
#include "File.h"
|
|
4
|
+
#include "Group.h"
|
|
5
|
+
#include "Variable.h"
|
|
6
|
+
#include <node.h>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
namespace nodenetcdfjs
|
|
10
|
+
{
|
|
11
|
+
void InitAll(v8::Local<v8::Object> exports)
|
|
12
|
+
{
|
|
13
|
+
File::Init(exports);
|
|
14
|
+
Variable::Init(exports);
|
|
15
|
+
Group::Init(exports);
|
|
16
|
+
Dimension::Init(exports);
|
|
17
|
+
Attribute::Init(exports);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
NODE_MODULE_INIT()
|
|
21
|
+
{
|
|
22
|
+
InitAll(exports);
|
|
23
|
+
}
|
|
24
|
+
} // namespace nodenetcdfjs
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#ifndef NODENETCDFJS_H
|
|
2
|
+
#define NODENETCDFJS_H
|
|
3
|
+
|
|
4
|
+
#include <netcdf.h>
|
|
5
|
+
#include <node.h>
|
|
6
|
+
#include <string>
|
|
7
|
+
#include <string_view>
|
|
8
|
+
#include <unordered_map>
|
|
9
|
+
|
|
10
|
+
namespace nodenetcdfjs
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
inline void throw_netcdf_error(v8::Isolate *isolate, int retval) noexcept(false)
|
|
14
|
+
{
|
|
15
|
+
isolate->ThrowException(v8::Exception::TypeError(
|
|
16
|
+
v8::String::NewFromUtf8(isolate, nc_strerror(retval), v8::NewStringType::kNormal).ToLocalChecked()));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
[[nodiscard]] constexpr int get_type(std::string_view type_str) noexcept
|
|
20
|
+
{
|
|
21
|
+
constexpr std::pair<std::string_view, int> type_map[] = {
|
|
22
|
+
{"byte", NC_BYTE}, {"char", NC_CHAR}, {"short", NC_SHORT}, {"int", NC_INT}, {"float", NC_FLOAT},
|
|
23
|
+
{"double", NC_DOUBLE}, {"ubyte", NC_UBYTE}, {"ushort", NC_USHORT}, {"uint", NC_UINT}, {"string", NC_STRING}};
|
|
24
|
+
|
|
25
|
+
for (const auto &[key, value] : type_map)
|
|
26
|
+
{
|
|
27
|
+
if (type_str == key)
|
|
28
|
+
{
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return NC_NAT;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
} // namespace nodenetcdfjs
|
|
36
|
+
|
|
37
|
+
#endif
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
var expect = require("chai").expect,
|
|
2
|
+
nodenetcdf = require("../build/Release/nodenetcdf.node");
|
|
3
|
+
|
|
4
|
+
describe('Attribute', function() {
|
|
5
|
+
describe('name', function() {
|
|
6
|
+
it('should read group attribute name', function() {
|
|
7
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
8
|
+
var attributes = file.root.subgroups["mozaic_flight_2012030419144751_ascent"].attributes;
|
|
9
|
+
expect(attributes["airport_dep"].name).to.equal("airport_dep");
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('value', function() {
|
|
14
|
+
it('should read group attribute value', function() {
|
|
15
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
16
|
+
var attributes = file.root.subgroups["mozaic_flight_2012030419144751_ascent"].attributes;
|
|
17
|
+
expect(attributes["airport_dep"].value).to.equal("FRA");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('name', function() {
|
|
22
|
+
it('should read variable attribute name', function() {
|
|
23
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
24
|
+
var attributes = file.root.subgroups["mozaic_flight_2012030419144751_ascent"].variables["air_press"].attributes;
|
|
25
|
+
expect(attributes["name"].name).to.equal("name");
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('value', function() {
|
|
30
|
+
it('should read variable attribute name', function() {
|
|
31
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
32
|
+
var attributes = file.root.subgroups["mozaic_flight_2012030419144751_ascent"].variables["air_press"].attributes;
|
|
33
|
+
expect(attributes["name"].value).to.equal("air_pressure");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
var expect = require("chai").expect,
|
|
2
|
+
nodenetcdf = require("../build/Release/nodenetcdf.node");
|
|
3
|
+
|
|
4
|
+
describe('Dimension', function() {
|
|
5
|
+
describe('name', function() {
|
|
6
|
+
it('should read name', function() {
|
|
7
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
8
|
+
expect(file.root.dimensions["recNum"].name).to.equal("recNum");
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe('length', function() {
|
|
13
|
+
it('should read length', function() {
|
|
14
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
15
|
+
expect(file.root.dimensions["recNum"].length).to.equal(74);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
});
|
package/test/file.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
var expect = require("chai").expect,
|
|
2
|
+
nodenetcdf = require("../build/Release/nodenetcdf.node");
|
|
3
|
+
|
|
4
|
+
describe('File', function() {
|
|
5
|
+
describe('new', function() {
|
|
6
|
+
it('should throw an error when file not found', function() {
|
|
7
|
+
expect(function() {
|
|
8
|
+
var file = new nodenetcdf.File("DOESNOTEXIST", "r");
|
|
9
|
+
}).to.throw("No such file or directory");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should throw an error for wrong file mode', function() {
|
|
13
|
+
expect(function() {
|
|
14
|
+
var file = new nodenetcdf.File("test/testrh.nc", "WRONG");
|
|
15
|
+
}).to.throw("Unknown file mode");
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
});
|
package/test/group.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var expect = require("chai").expect,
|
|
2
|
+
nodenetcdf = require("../build/Release/nodenetcdf.node");
|
|
3
|
+
|
|
4
|
+
describe('Group', function() {
|
|
5
|
+
describe('variables', function() {
|
|
6
|
+
it('should read list of variables', function() {
|
|
7
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
8
|
+
expect(file.root.variables).to.have.property("UTC_time");
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe('dimensions', function() {
|
|
13
|
+
it('should read list of dimensions', function() {
|
|
14
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
15
|
+
expect(file.root.dimensions).to.have.property("recNum");
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('subgroups', function() {
|
|
20
|
+
it('should read list of subgroups', function() {
|
|
21
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
22
|
+
var subgroups = file.root.subgroups;
|
|
23
|
+
expect(subgroups).to.have.property("mozaic_flight_2012030319051051_descent");
|
|
24
|
+
expect(subgroups).to.have.property("mozaic_flight_2012030319051051_descent");
|
|
25
|
+
expect(subgroups).to.have.property("mozaic_flight_2012030321335035_descent");
|
|
26
|
+
expect(subgroups).to.have.property("mozaic_flight_2012030403540535_ascent");
|
|
27
|
+
expect(subgroups).to.have.property("mozaic_flight_2012030403540535_descent");
|
|
28
|
+
expect(subgroups).to.have.property("mozaic_flight_2012030412545335_ascent");
|
|
29
|
+
expect(subgroups).to.have.property("mozaic_flight_2012030419144751_ascent");
|
|
30
|
+
expect(subgroups["mozaic_flight_2012030419144751_ascent"].constructor.name).to.equal("Group");
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('attributes', function() {
|
|
35
|
+
it('should read list of attributes', function() {
|
|
36
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
37
|
+
var attributes = file.root.subgroups["mozaic_flight_2012030419144751_ascent"].attributes;
|
|
38
|
+
expect(attributes).to.have.property("airport_dep");
|
|
39
|
+
expect(attributes).to.have.property("flight");
|
|
40
|
+
expect(attributes).to.have.property("level");
|
|
41
|
+
expect(attributes).to.have.property("airport_arr");
|
|
42
|
+
expect(attributes).to.have.property("mission");
|
|
43
|
+
expect(attributes).to.have.property("time_dep");
|
|
44
|
+
expect(attributes).to.have.property("aircraft");
|
|
45
|
+
expect(attributes).to.have.property("link");
|
|
46
|
+
expect(attributes).to.have.property("phase");
|
|
47
|
+
expect(attributes).to.have.property("time_arr");
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('name', function() {
|
|
52
|
+
it('should read name', function() {
|
|
53
|
+
var file = new nodenetcdf.File("test/test_hgroups.nc", "r");
|
|
54
|
+
expect(file.root.name).to.equal("/");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
Binary file
|
package/test/testrh.nc
ADDED
|
Binary file
|
package/test/variable.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var expect = require("chai").expect,
|
|
2
|
+
nodenetcdf = require("../build/Release/nodenetcdf.node");
|
|
3
|
+
|
|
4
|
+
describe('Variable', function() {
|
|
5
|
+
it('should read a slice', function() {
|
|
6
|
+
var file = new nodenetcdf.File("test/testrh.nc", "r");
|
|
7
|
+
var results = Array.from(file.root.variables.var1.readSlice(0, 4));
|
|
8
|
+
expect(results).to.deep.equal([420, 197, 391.5, 399]);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should read a strided slice', function() {
|
|
12
|
+
var file = new nodenetcdf.File("test/testrh.nc", "r");
|
|
13
|
+
var results = Array.from(file.root.variables.var1.readStridedSlice(0, 2, 2));
|
|
14
|
+
expect(results).to.deep.equal([420, 391.5]);
|
|
15
|
+
});
|
|
16
|
+
});
|